From cea5c95c82531ab3a360f366509dc95aeda50eb4 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Wed, 8 Jan 2025 00:21:52 -0800 Subject: [PATCH] dummy-switch: select which interfaces to implement --- plugins/dummy-switch/.vscode/settings.json | 2 +- plugins/dummy-switch/package-lock.json | 130 +++++++++++---------- plugins/dummy-switch/package.json | 2 +- plugins/dummy-switch/src/main.ts | 92 +++++++++++---- plugins/dummy-switch/tsconfig.json | 2 +- 5 files changed, 142 insertions(+), 86 deletions(-) diff --git a/plugins/dummy-switch/.vscode/settings.json b/plugins/dummy-switch/.vscode/settings.json index 77ccdbd6db..a620593fa1 100644 --- a/plugins/dummy-switch/.vscode/settings.json +++ b/plugins/dummy-switch/.vscode/settings.json @@ -1,4 +1,4 @@ { - "scrypted.debugHost": "127.0.0.1", + "scrypted.debugHost": "scrypted-nvr", } \ No newline at end of file diff --git a/plugins/dummy-switch/package-lock.json b/plugins/dummy-switch/package-lock.json index 07657bb839..4328e18bf9 100644 --- a/plugins/dummy-switch/package-lock.json +++ b/plugins/dummy-switch/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/dummy-switch", - "version": "0.0.24", + "version": "0.0.25", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/dummy-switch", - "version": "0.0.24", + "version": "0.0.25", "dependencies": { "@types/node": "^16.6.1", "axios": "^1.3.6" @@ -23,35 +23,41 @@ "license": "ISC", "dependencies": { "@scrypted/sdk": "file:../sdk", - "@scrypted/server": "file:../server", - "http-auth-utils": "^3.0.2", - "node-fetch-commonjs": "^3.1.1", - "typescript": "^4.4.3" + "http-auth-utils": "^5.0.1", + "typescript": "^5.5.3" }, "devDependencies": { - "@types/node": "^16.9.0" + "@types/node": "^20.11.0", + "monaco-editor": "^0.50.0", + "ts-node": "^10.9.2" } }, "../../sdk": { "name": "@scrypted/sdk", - "version": "0.2.97", + "version": "0.3.106", "dev": true, "license": "ISC", "dependencies": { - "@babel/preset-typescript": "^7.18.6", - "adm-zip": "^0.4.13", - "axios": "^0.21.4", - "babel-loader": "^9.1.0", - "babel-plugin-const-enum": "^1.1.0", - "esbuild": "^0.15.9", + "@babel/preset-typescript": "^7.26.0", + "@rollup/plugin-commonjs": "^28.0.1", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-typescript": "^12.1.1", + "@rollup/plugin-virtual": "^3.0.2", + "adm-zip": "^0.5.16", + "axios": "^1.7.8", + "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", + "rollup": "^4.27.4", + "tmp": "^0.2.3", + "ts-loader": "^9.5.1", + "tslib": "^2.8.1", + "typescript": "^5.6.3", + "webpack": "^5.96.1", + "webpack-bundle-analyzer": "^4.10.2" }, "bin": { "scrypted-changelog": "bin/scrypted-changelog.js", @@ -63,11 +69,9 @@ "scrypted-webpack": "bin/scrypted-webpack.js" }, "devDependencies": { - "@types/node": "^18.11.18", - "@types/stringify-object": "^4.0.0", - "stringify-object": "^3.3.0", - "ts-node": "^10.4.0", - "typedoc": "^0.23.21" + "@types/node": "^22.10.1", + "ts-node": "^10.9.2", + "typedoc": "^0.26.11" } }, "../sdk": { @@ -92,11 +96,11 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz", - "integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -121,9 +125,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", @@ -182,35 +186,39 @@ "version": "file:../../common", "requires": { "@scrypted/sdk": "file:../sdk", - "@scrypted/server": "file:../server", - "@types/node": "^16.9.0", - "http-auth-utils": "^3.0.2", - "node-fetch-commonjs": "^3.1.1", - "typescript": "^4.4.3" + "@types/node": "^20.11.0", + "http-auth-utils": "^5.0.1", + "monaco-editor": "^0.50.0", + "ts-node": "^10.9.2", + "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": "^0.21.4", - "babel-loader": "^9.1.0", - "babel-plugin-const-enum": "^1.1.0", - "esbuild": "^0.15.9", + "@babel/preset-typescript": "^7.26.0", + "@rollup/plugin-commonjs": "^28.0.1", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-typescript": "^12.1.1", + "@rollup/plugin-virtual": "^3.0.2", + "@types/node": "^22.10.1", + "adm-zip": "^0.5.16", + "axios": "^1.7.8", + "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", - "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" + "rimraf": "^6.0.1", + "rollup": "^4.27.4", + "tmp": "^0.2.3", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "tslib": "^2.8.1", + "typedoc": "^0.26.11", + "typescript": "^5.6.3", + "webpack": "^5.96.1", + "webpack-bundle-analyzer": "^4.10.2" } }, "@types/node": { @@ -224,11 +232,11 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz", - "integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -247,9 +255,9 @@ "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", diff --git a/plugins/dummy-switch/package.json b/plugins/dummy-switch/package.json index 292c1ce8be..64d259179f 100644 --- a/plugins/dummy-switch/package.json +++ b/plugins/dummy-switch/package.json @@ -40,5 +40,5 @@ "@scrypted/common": "file:../../common", "@scrypted/sdk": "file:../../sdk" }, - "version": "0.0.24" + "version": "0.0.25" } diff --git a/plugins/dummy-switch/src/main.ts b/plugins/dummy-switch/src/main.ts index cb49f69ab6..9d10ab2bfe 100644 --- a/plugins/dummy-switch/src/main.ts +++ b/plugins/dummy-switch/src/main.ts @@ -2,11 +2,60 @@ import { BinarySensor, DeviceCreator, DeviceCreatorSettings, DeviceProvider, Loc import sdk from '@scrypted/sdk'; import { ReplaceMotionSensor, ReplaceMotionSensorNativeId } from './replace-motion-sensor'; import { ReplaceBinarySensor, ReplaceBinarySensorNativeId } from './replace-binary-sensor'; +import { StorageSettings } from '@scrypted/sdk/storage-settings'; const { log, deviceManager } = sdk; class DummyDevice extends ScryptedDeviceBase implements OnOff, Lock, StartStop, OccupancySensor, MotionSensor, BinarySensor, Settings { timeout: NodeJS.Timeout; + storageSettings = new StorageSettings(this, { + reset: { + title: 'Reset Sensor', + description: 'Reset the motion sensor and binary sensor after the given seconds. Enter 0 to never reset.', + defaultValue: 10, + type: 'number', + placeholder: '10', + onPut: () => { + clearTimeout(this.timeout); + } + }, + actionTypes: { + title: 'Action Types', + description: 'Select the action types to expose.', + defaultValue: [ + ScryptedInterface.OnOff, + ScryptedInterface.StartStop, + ScryptedInterface.Lock, + ], + multiple: true, + choices: [ + ScryptedInterface.OnOff, + ScryptedInterface.StartStop, + ScryptedInterface.Lock, + ], + onPut: () => { + this.reportInterfaces(); + }, + }, + sensorTypes: { + title: 'Sensor Types', + description: 'Select the sensor types to expose.', + defaultValue: [ + ScryptedInterface.MotionSensor, + ScryptedInterface.BinarySensor, + ScryptedInterface.OccupancySensor, + ], + multiple: true, + choices: [ + ScryptedInterface.MotionSensor, + ScryptedInterface.BinarySensor, + ScryptedInterface.OccupancySensor, + ], + onPut: () => { + this.reportInterfaces(); + }, + } + }); constructor(nativeId: string) { super(nativeId); @@ -19,6 +68,22 @@ class DummyDevice extends ScryptedDeviceBase implements OnOff, Lock, StartStop, this.occupied = false; } + async reportInterfaces() { + const interfaces: ScryptedInterface[] = this.storageSettings.values.sensorTypes || []; + if (!interfaces.length) + interfaces.push(ScryptedInterface.MotionSensor, ScryptedInterface.BinarySensor, ScryptedInterface.OccupancySensor); + const actionTyoes = this.storageSettings.values.actionTypes || []; + if (!actionTyoes.length) + actionTyoes.push(ScryptedInterface.OnOff, ScryptedInterface.StartStop, ScryptedInterface.Lock); + + await sdk.deviceManager.onDeviceDiscovered({ + nativeId: this.nativeId, + interfaces: [...interfaces, ...actionTyoes, ScryptedInterface.Settings], + type: ScryptedDeviceType.Switch, + name: this.providedName, + }); + } + lock(): Promise { return this.turnOff(); } @@ -31,20 +96,12 @@ class DummyDevice extends ScryptedDeviceBase implements OnOff, Lock, StartStop, stop(): Promise { return this.turnOff(); } + async getSettings(): Promise { - return [ - { - key: 'reset', - title: 'Reset Sensor', - description: 'Reset the motion sensor and binary sensor after the given seconds. Enter 0 to never reset.', - value: this.storage.getItem('reset') || '10', - placeholder: '10', - } - ] + return this.storageSettings.getSettings(); } async putSetting(key: string, value: SettingValue): Promise { - this.storage.setItem(key, value.toString()); - clearTimeout(this.timeout); + return this.storageSettings.putSetting(key, value); } // note that turnOff locks the lock @@ -131,12 +188,6 @@ class DummyDeviceProvider extends ScryptedDeviceBase implements DeviceProvider, const nativeId = 'shell:' + Math.random().toString(); const name = settings.name?.toString(); - await this.onDiscovered(nativeId, name); - - return nativeId; - } - - async onDiscovered(nativeId: string, name: string) { await deviceManager.onDeviceDiscovered({ nativeId, name, @@ -151,6 +202,8 @@ class DummyDeviceProvider extends ScryptedDeviceBase implements DeviceProvider, ], type: ScryptedDeviceType.Switch, }); + + return nativeId; } async getDevice(nativeId: string) { @@ -163,11 +216,6 @@ class DummyDeviceProvider extends ScryptedDeviceBase implements DeviceProvider, if (!ret) { ret = new DummyDevice(nativeId); - // remove legacy scriptable interface - if (ret.interfaces.includes(ScryptedInterface.Scriptable)) { - setTimeout(() => this.onDiscovered(ret.nativeId, ret.providedName), 2000); - } - if (ret) this.devices.set(nativeId, ret); } diff --git a/plugins/dummy-switch/tsconfig.json b/plugins/dummy-switch/tsconfig.json index 34a847ad82..ba9b4d395b 100644 --- a/plugins/dummy-switch/tsconfig.json +++ b/plugins/dummy-switch/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "module": "commonjs", + "module": "Node16", "target": "ES2021", "resolveJsonModule": true, "moduleResolution": "Node16",