Skip to content

Commit

Permalink
Merge pull request #41 from phillipivan/main
Browse files Browse the repository at this point in the history
Auto Reconnect
  • Loading branch information
phillipivan authored Sep 25, 2024
2 parents 7449cdf + 3af0f93 commit 0e4ac80
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 30 deletions.
87 changes: 86 additions & 1 deletion companion/HELP.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,88 @@
## 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 these, 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: 1.2.3.4

Paths can always be entered as a decimal address (ie _1.2.3.4_).

- #### String: Path.To.Ember.Node

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.

- #### 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

## Action Recorder

The Action Recorder can record Set Value actions for ember nodes you are currently subscribed to.
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "generic-emberplus",
"version": "2.4.2",
"version": "2.4.3",
"main": "dist/index.js",
"scripts": {
"prepare": "husky",
Expand Down Expand Up @@ -31,12 +31,13 @@
"dependencies": {
"@companion-module/base": "~1.10.0",
"@types/node": "^18.19.45",
"emberplus-connection": "^0.2.1",
"delay": "^6.0.0",
"emberplus-connection": "^0.2.2",
"p-queue": "^8.0.1"
},
"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",
Expand All @@ -45,5 +46,5 @@
"typescript-eslint": "^8.6.0"
},
"prettier": "@companion-module/tools/.prettierrc.json",
"packageManager": "yarn@4.4.1"
"packageManager": "yarn@4.5.0"
}
24 changes: 16 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,8 +23,8 @@ export class EmberPlusInstance extends InstanceBase<EmberPlusConfig> {
private config!: EmberPlusConfig
private state!: EmberPlusState
private emberQueue!: PQueue
private reconnectTimer!: ReturnType<typeof setTimeout> | undefined
private isRecordingActions!: boolean
private reconnectTimer: ReturnType<typeof setTimeout> | undefined = undefined
private isRecordingActions: boolean = false

// Override base types to make types stricter
public checkFeedbacks(...feedbackTypes: string[]): void {
Expand Down Expand Up @@ -136,19 +138,25 @@ export class EmberPlusInstance extends InstanceBase<EmberPlusConfig> {
const request = await this.emberClient.getDirectory(this.emberClient.tree)
await request.response
await this.registerParameters()
this.subscribeActions()
this.subscribeFeedbacks()
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()
})
this.reconnectTimerStart()
this.emberClient.connect().catch((e) => {
this.updateStatus(InstanceStatus.ConnectionFailure)
this.log('error', 'Connection Failure: ' + e)
Expand Down Expand Up @@ -235,8 +243,8 @@ export class EmberPlusInstance extends InstanceBase<EmberPlusConfig> {

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)
Expand All @@ -254,7 +262,7 @@ export class EmberPlusInstance extends InstanceBase<EmberPlusConfig> {
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
}
Expand Down
49 changes: 32 additions & 17 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -1027,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"
Expand All @@ -1048,17 +1062,17 @@ 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"
eventemitter3: "npm:^4.0.7"
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

Expand Down Expand Up @@ -1244,16 +1258,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"
Expand Down Expand Up @@ -1289,7 +1303,7 @@ asn1@evs-broadcast/node-asn1:
optional: true
bin:
eslint: bin/eslint.js
checksum: 10c0/7357f3995b15043eea83c8c0ab16c385ce3f28925c1b11cfcd6b2ede8faab3d91ede84a68173dd5f6e3e176e177984e6218de58b7b8388e53e2881f1ec07c836
checksum: 10c0/3438a78172bc667dc87bc4ad864671bd93231c82c9d366899ea3a77fc3444c8cdd158e7fe3ca1cfe4cb566045b1b36c0ccae9fc20efeb4b187f1a534075a1177
languageName: node
linkType: hard

Expand Down Expand Up @@ -1535,8 +1549,9 @@ 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"
emberplus-connection: "npm:^0.2.1"
eslint: "npm:^9.10.0"
delay: "npm:^6.0.0"
emberplus-connection: "npm:^0.2.2"
eslint: "npm:^9.11.0"
husky: "npm:^9.1.6"
lint-staged: "npm:^15.2.10"
p-queue: "npm:^8.0.1"
Expand Down

0 comments on commit 0e4ac80

Please sign in to comment.