From 56cdfc0e1832e46dc0e06ba4d64a669f10482c84 Mon Sep 17 00:00:00 2001 From: phillipivan Date: Mon, 23 Sep 2024 13:11:00 +1000 Subject: [PATCH 1/7] update devDependencies --- package.json | 6 +++--- yarn.lock | 31 +++++++++++++++++++------------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 087d543..5aeb28f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generic-emberplus", - "version": "2.4.2", + "version": "2.4.3", "main": "dist/index.js", "scripts": { "prepare": "husky", @@ -36,7 +36,7 @@ }, "devDependencies": { "@companion-module/tools": "^2.0.4", - "eslint": "^9.10.0", + "eslint": "^9.11.0", "husky": "^9.1.6", "lint-staged": "^15.2.10", "prettier": "^3.3.3", @@ -45,5 +45,5 @@ "typescript-eslint": "^8.6.0" }, "prettier": "@companion-module/tools/.prettierrc.json", - "packageManager": "yarn@4.4.1" + "packageManager": "yarn@4.5.0" } diff --git a/yarn.lock b/yarn.lock index a5daa1c..acf28fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -109,7 +109,14 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.10.0, @eslint/js@npm:^9.10.0": +"@eslint/js@npm:9.11.0": + version: 9.11.0 + resolution: "@eslint/js@npm:9.11.0" + checksum: 10c0/7403aeba28ba9cae3470d149b334a51375eb7fd850f167555c81cc72fe98e5cc5ac3059ccdbe68eb255a49d7498a7288d25429af0c7d20afeb4b3c0748349bb4 + languageName: node + linkType: hard + +"@eslint/js@npm:^9.10.0": version: 9.10.0 resolution: "@eslint/js@npm:9.10.0" checksum: 10c0/2ac45a002dc1ccf25be46ea61001ada8d77248d1313ab4e53f3735e5ae00738a757874e41f62ad6fbd49df7dffeece66e5f53ff0d7b78a99ce4c68e8fea66753 @@ -123,12 +130,12 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.1.0": - version: 0.1.0 - resolution: "@eslint/plugin-kit@npm:0.1.0" +"@eslint/plugin-kit@npm:^0.2.0": + version: 0.2.0 + resolution: "@eslint/plugin-kit@npm:0.2.0" dependencies: levn: "npm:^0.4.1" - checksum: 10c0/fae97cd4efc1c32501c286abba1b5409848ce8c989e1ca6a5bb057a304a2cd721e6e957f6bc35ce95cfd0871e822ed42df3c759fecdad72c30e70802e26f83c7 + checksum: 10c0/00b92bc52ad09b0e2bbbb30591c02a895f0bec3376759562590e8a57a13d096b22f8c8773b6bf791a7cf2ea614123b3d592fd006c51ac5fd0edbb90ea6d8760c languageName: node linkType: hard @@ -1244,16 +1251,16 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"eslint@npm:^9.10.0": - version: 9.10.0 - resolution: "eslint@npm:9.10.0" +"eslint@npm:^9.11.0": + version: 9.11.0 + resolution: "eslint@npm:9.11.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.11.0" "@eslint/config-array": "npm:^0.18.0" "@eslint/eslintrc": "npm:^3.1.0" - "@eslint/js": "npm:9.10.0" - "@eslint/plugin-kit": "npm:^0.1.0" + "@eslint/js": "npm:9.11.0" + "@eslint/plugin-kit": "npm:^0.2.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.3.0" "@nodelib/fs.walk": "npm:^1.2.8" @@ -1289,7 +1296,7 @@ asn1@evs-broadcast/node-asn1: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/7357f3995b15043eea83c8c0ab16c385ce3f28925c1b11cfcd6b2ede8faab3d91ede84a68173dd5f6e3e176e177984e6218de58b7b8388e53e2881f1ec07c836 + checksum: 10c0/3438a78172bc667dc87bc4ad864671bd93231c82c9d366899ea3a77fc3444c8cdd158e7fe3ca1cfe4cb566045b1b36c0ccae9fc20efeb4b187f1a534075a1177 languageName: node linkType: hard @@ -1536,7 +1543,7 @@ asn1@evs-broadcast/node-asn1: "@companion-module/tools": "npm:^2.0.4" "@types/node": "npm:^18.19.45" emberplus-connection: "npm:^0.2.1" - eslint: "npm:^9.10.0" + eslint: "npm:^9.11.0" husky: "npm:^9.1.6" lint-staged: "npm:^15.2.10" p-queue: "npm:^8.0.1" From 32400210d75e1e7c447b099029f70da5cb2ffdcf Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Tue, 24 Sep 2024 21:25:58 +1000 Subject: [PATCH 2/7] attempt reconnect (with delay) when initial connection queries fail; stronger typing for action recorder --- package.json | 1 + src/index.ts | 17 +++++++++++------ yarn.lock | 8 ++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 5aeb28f..e5eacdb 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "@companion-module/base": "~1.10.0", "@types/node": "^18.19.45", + "delay": "^6.0.0", "emberplus-connection": "^0.2.1", "p-queue": "^8.0.1" }, diff --git a/src/index.ts b/src/index.ts index e7eabbc..1bc851f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,9 +9,11 @@ import { EmberClient, Model as EmberModel } from 'emberplus-connection' // note import { ElementType } from 'emberplus-connection/dist/model' import type { TreeElement, EmberElement } from 'emberplus-connection/dist/model' import { GetVariablesList } from './variables' +import delay from 'delay' import PQueue from 'p-queue' const reconnectInterval: number = 300000 //emberplus-connection destroys socket after 5 minutes +const reconnectOnFailDelay: number = 10000 //reattempt delay when initial connection queries throw an error /** * Companion instance class for generic EmBER+ Devices @@ -138,14 +140,17 @@ export class EmberPlusInstance extends InstanceBase { await this.registerParameters() this.updateStatus(InstanceStatus.Ok) }) - .catch((e) => { + .catch(async (e) => { // get root this.log('error', 'Failed to discover root or subscribe to path: ' + e) - this.updateStatus(InstanceStatus.UnknownWarning) + this.updateStatus(InstanceStatus.UnknownWarning, e.toString()) + await this.emberClient.disconnect() + await delay(reconnectOnFailDelay) + this.setupEmberConnection() }) }) this.emberClient.on('disconnected', () => { - this.updateStatus(InstanceStatus.Connecting) + this.updateStatus(InstanceStatus.Connecting, 'Disconnected') this.log('warn', `Disconnected from ${this.config.host}:${this.config.port}`) this.reconnectTimerStart() }) @@ -235,8 +240,8 @@ export class EmberPlusInstance extends InstanceBase { this.setVariableValues(Object.fromEntries(this.state.parameters.entries())) if (this.isRecordingActions) { - let actionType: string - let actionValue: any + let actionType: ActionId + let actionValue: number | boolean | string if (node.contents.parameterType === EmberModel.ParameterType.Integer) { actionType = ActionId.SetValueInt actionValue = Number(node.contents.value) @@ -254,7 +259,7 @@ export class EmberPlusInstance extends InstanceBase { if (isNaN(actionValue)) return } else if (node.contents.parameterType === EmberModel.ParameterType.String) { actionType = ActionId.SetValueString - actionValue = node.contents.value?.toString() + actionValue = node.contents.value?.toString() ?? '' } else { return } diff --git a/yarn.lock b/yarn.lock index acf28fe..e5cdfc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1034,6 +1034,13 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard +"delay@npm:^6.0.0": + version: 6.0.0 + resolution: "delay@npm:6.0.0" + checksum: 10c0/5175e887512d65b2bfe9e1168b5ce7a488de99c1d0af52cb4f799bb13dd7cb0bbbba8a4f5c500a5b03fb42bec8621d6ab59244bd8dfbe9a2bf7b173f25621a10 + languageName: node + linkType: hard + "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -1542,6 +1549,7 @@ asn1@evs-broadcast/node-asn1: "@companion-module/base": "npm:~1.10.0" "@companion-module/tools": "npm:^2.0.4" "@types/node": "npm:^18.19.45" + delay: "npm:^6.0.0" emberplus-connection: "npm:^0.2.1" eslint: "npm:^9.11.0" husky: "npm:^9.1.6" From 26bccf738d4c6737964244c520432456aeb36577 Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Wed, 25 Sep 2024 08:41:09 +1000 Subject: [PATCH 3/7] subscribe actions and feedbacks on connect --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index 1bc851f..63ea730 100644 --- a/src/index.ts +++ b/src/index.ts @@ -138,6 +138,8 @@ export class EmberPlusInstance extends InstanceBase { const request = await this.emberClient.getDirectory(this.emberClient.tree) await request.response await this.registerParameters() + this.subscribeActions() + this.subscribeFeedbacks() this.updateStatus(InstanceStatus.Ok) }) .catch(async (e) => { From 2289e5c8743b1bc362463ddecebce20e0a1c5aea Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Wed, 25 Sep 2024 10:53:32 +1000 Subject: [PATCH 4/7] flesh out help.md --- companion/HELP.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/companion/HELP.md b/companion/HELP.md index 4dc2262..f0bb0a4 100644 --- a/companion/HELP.md +++ b/companion/HELP.md @@ -1,3 +1,86 @@ -## Generic Ember Plus +# Generic Ember Plus - [Ember Plus](https://github.com/Lawo/ember-plus) + +This is a generic ember plus module - successful use of this tool requires use and familiary with Ember Plus Viewer or a similar tool to identify the Ember Paths, and types, to be monitored and controlled. + +The module only supports connection via TCP + +## Configuration + +### Bonjour + +Some devices support mDNS announcements according to the Ember Plus [specification](https://github.com/Lawo/ember-plus/blob/master/documentation/Ember%2B%20Service%20Discovery.pdf). + +The module should discover. Otherwise device IP and Port can be manually entered. + +### Matrix Control + +If you require matrix control, enter the ember path(s) here. + +### Auto Take + +Defines matrix behaviour. + +### Paths to Monitor + +Paths defined here will be registed with the host on initialisation, and available as variables and for use in feedbacks. + +## Paths + +Central to the concept of ember+ is the address or path of the data element you wish to monitor or change. There are several ways to enter this in the module. + +- ### Decimal + + Paths can always be entered as a decimal address (ie _1.2.3.4_). + +- ### String + + Paths can also be entered as a period seperated string. Such as _Path.To.Ember.Element_. These text paths can be found in Ember Plus Viewer, however need to be reformatted to use period seperators rather than forward slashes. Note: Some characters (such as #) used in ember paths are not supported for use in variables by companion, and the expected variable will not be created - the path can still be used in actions and feedbacks however. + +- ### Decimal in Brackets + + Any path field that contains brackets [] will just use the contents enclosed in the brackets as the path. Thus you can copy paste any path with text and decimals from ember plus viewer, and keep the text for readability or enter your own description _This is a very useful path[1.2.3.4]_. Only the path will be used for variable creation. + +- ### Variables + Except in the module configuration, all of the above can be constructed with variables for both actions and feedbacks. + +## Value Fields + +For Set Value Actions one must ensure the correct data type is selected. In particular confusion can occur between Integer and ENUM types. + +For both actions and feedbacks, values are treated 'raw' - that is the transform specified in the _factor_ field is not applied. Companion expressions can be used to perform these transforms if necessary. +Similarly ENUMS are always refered to by Integer Index . + +## Actions + +- Set Value Integer +- Set Value Integer from Variable +- Set Value Real +- Set Value Boolean +- Set Value ENUM (as Integer) +- Set Value ENUM from Variable (as Integer) +- Set Value String +- Matrix Connect +- Matrix Disconnect +- Matrix Set Connection +- Take +- Clear +- Set Selected Source +- Set Selected Target + +## Feedbacks + +- Parameter Equals +- Parameter Equals String +- Take is possible +- Clear is possible +- Source Background If Selected +- Target Background if Selected + +Both Parameter Equals, and Parameter Equals String type convert all data to strings before performing an equality test, thus can be used on any node type. Ie, you can check a boolean node with the Parameter Equals String feedback by setting the Value to _true_. The path field for Parameter Equals and Parameter Equals String presents a dropdown of registered paths. New paths (including variables) can be entered and if valid will be automatically registered and added tp the drop downs and variables. + +## Presets + +- Take +- Clear From 38341b13bcf78d947126f59f8c6547cbbd4f887c Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Wed, 25 Sep 2024 12:33:27 +1000 Subject: [PATCH 5/7] update help --- companion/HELP.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/companion/HELP.md b/companion/HELP.md index f0bb0a4..f2e4aa6 100644 --- a/companion/HELP.md +++ b/companion/HELP.md @@ -8,21 +8,21 @@ The module only supports connection via TCP ## Configuration -### Bonjour +#### Bonjour Some devices support mDNS announcements according to the Ember Plus [specification](https://github.com/Lawo/ember-plus/blob/master/documentation/Ember%2B%20Service%20Discovery.pdf). The module should discover. Otherwise device IP and Port can be manually entered. -### Matrix Control +#### Matrix Control If you require matrix control, enter the ember path(s) here. -### Auto Take +#### Auto Take Defines matrix behaviour. -### Paths to Monitor +#### Paths to Monitor Paths defined here will be registed with the host on initialisation, and available as variables and for use in feedbacks. @@ -30,19 +30,19 @@ Paths defined here will be registed with the host on initialisation, and availab Central to the concept of ember+ is the address or path of the data element you wish to monitor or change. There are several ways to enter this in the module. -- ### Decimal +- #### Decimal: 1.2.3.4 Paths can always be entered as a decimal address (ie _1.2.3.4_). -- ### String +- #### String: Path.To.Ember.Node Paths can also be entered as a period seperated string. Such as _Path.To.Ember.Element_. These text paths can be found in Ember Plus Viewer, however need to be reformatted to use period seperators rather than forward slashes. Note: Some characters (such as #) used in ember paths are not supported for use in variables by companion, and the expected variable will not be created - the path can still be used in actions and feedbacks however. -- ### Decimal in Brackets +- #### Decimal in Brackets: My Useful Ember Path [1.2.3.4] Any path field that contains brackets [] will just use the contents enclosed in the brackets as the path. Thus you can copy paste any path with text and decimals from ember plus viewer, and keep the text for readability or enter your own description _This is a very useful path[1.2.3.4]_. Only the path will be used for variable creation. -- ### Variables +- #### Variables Except in the module configuration, all of the above can be constructed with variables for both actions and feedbacks. ## Value Fields From 689626969859ee3cf311ae77a2a7b2295f529f23 Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Wed, 25 Sep 2024 12:36:47 +1000 Subject: [PATCH 6/7] update emberplus connection --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index e5eacdb..abc7c68 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@companion-module/base": "~1.10.0", "@types/node": "^18.19.45", "delay": "^6.0.0", - "emberplus-connection": "^0.2.1", + "emberplus-connection": "^0.2.2", "p-queue": "^8.0.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index e5cdfc4..46d1d6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1062,9 +1062,9 @@ asn1@evs-broadcast/node-asn1: languageName: node linkType: hard -"emberplus-connection@npm:^0.2.1": - version: 0.2.1 - resolution: "emberplus-connection@npm:0.2.1" +"emberplus-connection@npm:^0.2.2": + version: 0.2.2 + resolution: "emberplus-connection@npm:0.2.2" dependencies: asn1: evs-broadcast/node-asn1 debug: "npm:^4.3.4" @@ -1072,7 +1072,7 @@ asn1@evs-broadcast/node-asn1: long: "npm:^3.2.0" smart-buffer: "npm:^3.0.3" tslib: "npm:^2.6.2" - checksum: 10c0/33a98476560664e921dc2e375256ae8f8e92d78c095ac03a123d91acccc38daaa5da313d7b5d0a63ef450b86d069da7eb999cbc8e921b09abeb399dcd3dc10c3 + checksum: 10c0/e7674b2990733800f3838f8ec4d9679b26336bc6c2e83b78dce2c10e9552c26f8fc3f08fbaa0ce8f089812c26ef7d4c3057b20cb90527a5e34e53cc6b4203430 languageName: node linkType: hard @@ -1550,7 +1550,7 @@ asn1@evs-broadcast/node-asn1: "@companion-module/tools": "npm:^2.0.4" "@types/node": "npm:^18.19.45" delay: "npm:^6.0.0" - emberplus-connection: "npm:^0.2.1" + emberplus-connection: "npm:^0.2.2" eslint: "npm:^9.11.0" husky: "npm:^9.1.6" lint-staged: "npm:^15.2.10" From 3af0f931dcbfc082115b57694b01c05aaf21e227 Mon Sep 17 00:00:00 2001 From: Phillip Ivan Pietruschka Date: Wed, 25 Sep 2024 13:24:49 +1000 Subject: [PATCH 7/7] improve auto-reconnect logic, help.md fixups --- companion/HELP.md | 14 ++++++++------ src/index.ts | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/companion/HELP.md b/companion/HELP.md index f2e4aa6..e9edefc 100644 --- a/companion/HELP.md +++ b/companion/HELP.md @@ -4,15 +4,13 @@ This is a generic ember plus module - successful use of this tool requires use and familiary with Ember Plus Viewer or a similar tool to identify the Ember Paths, and types, to be monitored and controlled. -The module only supports connection via TCP +The module only supports connection via TCP. ## Configuration #### Bonjour -Some devices support mDNS announcements according to the Ember Plus [specification](https://github.com/Lawo/ember-plus/blob/master/documentation/Ember%2B%20Service%20Discovery.pdf). - -The module should discover. Otherwise device IP and Port can be manually entered. +Some devices support mDNS announcements according to the Ember Plus [specification](https://github.com/Lawo/ember-plus/blob/master/documentation/Ember%2B%20Service%20Discovery.pdf). The module should discover these, otherwise device IP and Port can be manually entered. #### Matrix Control @@ -36,11 +34,11 @@ Central to the concept of ember+ is the address or path of the data element you - #### String: Path.To.Ember.Node - Paths can also be entered as a period seperated string. Such as _Path.To.Ember.Element_. These text paths can be found in Ember Plus Viewer, however need to be reformatted to use period seperators rather than forward slashes. Note: Some characters (such as #) used in ember paths are not supported for use in variables by companion, and the expected variable will not be created - the path can still be used in actions and feedbacks however. + Paths can also be entered as a period seperated string. Such as _Path.To.Ember.Node_. These text paths can be found in Ember Plus Viewer, however they need to be reformatted to use period seperators rather than forward slashes. Note: Some characters (such as #) used in ember paths are not supported for use in variables by companion, and the expected variable will not be created - the path can still be used in actions and feedbacks however. - #### Decimal in Brackets: My Useful Ember Path [1.2.3.4] - Any path field that contains brackets [] will just use the contents enclosed in the brackets as the path. Thus you can copy paste any path with text and decimals from ember plus viewer, and keep the text for readability or enter your own description _This is a very useful path[1.2.3.4]_. Only the path will be used for variable creation. + Any path field that contains brackets [] will just use the contents enclosed in the brackets as the path. Thus you can copy paste any path with text and decimals from Ember Plus Viewer, and keep the text for readability or enter your own description _This is a very useful path[1.2.3.4]_. Only the path will be used for variable creation. - #### Variables Except in the module configuration, all of the above can be constructed with variables for both actions and feedbacks. @@ -84,3 +82,7 @@ Both Parameter Equals, and Parameter Equals String type convert all data to stri - Take - Clear + +## Action Recorder + +The Action Recorder can record Set Value actions for ember nodes you are currently subscribed to. diff --git a/src/index.ts b/src/index.ts index 63ea730..8e61c52 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,8 +23,8 @@ export class EmberPlusInstance extends InstanceBase { private config!: EmberPlusConfig private state!: EmberPlusState private emberQueue!: PQueue - private reconnectTimer!: ReturnType | undefined - private isRecordingActions!: boolean + private reconnectTimer: ReturnType | undefined = undefined + private isRecordingActions: boolean = false // Override base types to make types stricter public checkFeedbacks(...feedbackTypes: string[]): void { @@ -156,6 +156,7 @@ export class EmberPlusInstance extends InstanceBase { this.log('warn', `Disconnected from ${this.config.host}:${this.config.port}`) this.reconnectTimerStart() }) + this.reconnectTimerStart() this.emberClient.connect().catch((e) => { this.updateStatus(InstanceStatus.ConnectionFailure) this.log('error', 'Connection Failure: ' + e)