loupedeck-commander 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,16 @@
1
- import { exec } from 'child_process'
2
-
3
- export async function sh (cmd) {
4
- // console.log('TRIGGER -> ', cmd)
5
-
6
- return new Promise(function (resolve, reject) {
7
- exec(cmd, (err, stdout, stderr) => {
8
- console.log('executed cmd, stdout:', stdout)
9
- if (err) {
10
- reject(err)
11
- } else {
12
- resolve({ stdout, stderr })
13
- }
14
- })
15
- })
16
- }
1
+ import { exec } from 'child_process'
2
+
3
+ export async function sh (cmd) {
4
+ // console.log('TRIGGER -> ', cmd)
5
+
6
+ return new Promise(function (resolve, reject) {
7
+ exec(cmd, (err, stdout, stderr) => {
8
+ console.log('executed cmd, stdout:', stdout)
9
+ if (err) {
10
+ reject(err)
11
+ } else {
12
+ resolve({ stdout, stderr })
13
+ }
14
+ })
15
+ })
16
+ }
package/common/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { BaseLoupeDeckHandler } from './BaseLoupeDeckHandler.mjs'
2
-
3
- module.exports = {
4
- BaseLoupeDeckHandler
5
- }
1
+ import { BaseLoupeDeckHandler } from './BaseLoupeDeckHandler.mjs'
2
+
3
+ module.exports = {
4
+ BaseLoupeDeckHandler
5
+ }
package/common/utils.mjs CHANGED
@@ -1,106 +1,106 @@
1
- import { readFileSync, writeFileSync } from 'node:fs'
2
- import YAML from 'yaml'
3
-
4
- /**
5
- * Read a Config file in either JSON or YAML Fileformat
6
- * @param {string} fileName - The name of the file to read
7
- * @returns {object} - The parsed object from the file
8
- */
9
- export function readConfigFile (fileName) {
10
- let obj = undefined
11
- try {
12
- //console.log("Reading File:", fileName)
13
- let data = readFileSync(fileName, 'utf8')
14
- // If the file is a YAML file, parse it
15
- if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) {
16
- obj = YAML.parse(data)
17
- } else if (fileName.endsWith('.json')) {
18
- // If the file is a JSON file, parse it
19
- obj = JSON.parse(data)
20
- // automatically convert all json to yaml
21
- writeYAMLFile(fileName.replace(".json",".yaml"), obj)
22
- }
23
- } catch (error) {
24
- console.info(`Error reading File: ${fileName}`, error)
25
- }
26
- return obj
27
- }
28
-
29
- /**
30
- * Write a JSON File
31
- */
32
- export function writeJSONFile (fileName, jsonObj) {
33
- const data = JSON.stringify(jsonObj, null, 4)
34
- writeFileSync(fileName, data)
35
- }
36
-
37
- /**
38
- * Write a JSON File
39
- */
40
- export function writeYAMLFile (fileName, jsonObj) {
41
- const data = YAML.stringify(jsonObj)
42
- writeFileSync(fileName, data)
43
- }
44
-
45
-
46
- /**
47
- * Calculate the delta of a value within a range between min and max with overflow
48
- * @param {*} data
49
- * @param {*} delta
50
- * @param {*} min
51
- * @param {*} max
52
- * @returns
53
- */
54
- export function calcDelta (data, delta, min = 0, max = 100) {
55
- data = data + delta
56
- if (data > max) { data = min }
57
- else if (data < min) { data = max }
58
- return data
59
- }
60
-
61
- /**
62
- * Invert a color in hex format (#RRGGBB) to its inverted color
63
- * @param {*} colorAsHex
64
- * @returns
65
- */
66
- export function invertColor(colorAsHex){
67
- let rgb = colorToRGB(colorAsHex)
68
- for (var i = 0; i < rgb.length; i++) {
69
- rgb[i] = (i === 3 ? 1 : 255) - rgb[i];
70
- }
71
- let invertedColor = `#${rgb[0].toString(16)}${rgb[1].toString(16)}${rgb[2].toString(16)})`
72
- //let invertedColor = `#${rgb[0].toString(16).padStart(2, '0')}${rgb[1].toString(16).padStart(2, '0')}${rgb[2].toString(16).padStart(2, '0')})`
73
- //console.log("invert", colorAsHex,"=>",invertedColor)
74
- return invertedColor
75
- }
76
-
77
- /**
78
- * Convert a color in hex format (#RRGGBB) to RGB array
79
- * @param {*} colorAsHex
80
- * @returns
81
- */
82
- export function colorToRGB(colorAsHex){
83
- const r = parseInt(colorAsHex.slice(1, 3), 16)
84
- const g = parseInt(colorAsHex.slice(3, 5), 16)
85
- const b = parseInt(colorAsHex.slice(5, 7), 16)
86
- return [r,g,b]
87
- }
88
-
89
- /**
90
- * Synchronize the parameters of a node with the default node
91
- * @param {*} node
92
- * @param {*} defaultnode
93
- * @returns node
94
- */
95
- export function syncParams(node, defaultnode){
96
- if (node === undefined || defaultnode === undefined)
97
- return node
98
- let keys = Object.keys(defaultnode)
99
- for (var i=0;i<keys.length;i++){
100
- let key = keys[i]
101
- if (!(key in node))
102
- node[key] = defaultnode[key]
103
- }
104
- return node
105
- }
106
-
1
+ import { readFileSync, writeFileSync } from 'node:fs'
2
+ import YAML from 'yaml'
3
+
4
+ /**
5
+ * Read a Config file in either JSON or YAML Fileformat
6
+ * @param {string} fileName - The name of the file to read
7
+ * @returns {object} - The parsed object from the file
8
+ */
9
+ export function readConfigFile (fileName) {
10
+ let obj = undefined
11
+ try {
12
+ //console.log("Reading File:", fileName)
13
+ let data = readFileSync(fileName, 'utf8')
14
+ // If the file is a YAML file, parse it
15
+ if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) {
16
+ obj = YAML.parse(data)
17
+ } else if (fileName.endsWith('.json')) {
18
+ // If the file is a JSON file, parse it
19
+ obj = JSON.parse(data)
20
+ // automatically convert all json to yaml
21
+ writeYAMLFile(fileName.replace(".json",".yaml"), obj)
22
+ }
23
+ } catch (error) {
24
+ console.info(`Error reading File: ${fileName}`, error)
25
+ }
26
+ return obj
27
+ }
28
+
29
+ /**
30
+ * Write a JSON File
31
+ */
32
+ export function writeJSONFile (fileName, jsonObj) {
33
+ const data = JSON.stringify(jsonObj, null, 4)
34
+ writeFileSync(fileName, data)
35
+ }
36
+
37
+ /**
38
+ * Write a JSON File
39
+ */
40
+ export function writeYAMLFile (fileName, jsonObj) {
41
+ const data = YAML.stringify(jsonObj)
42
+ writeFileSync(fileName, data)
43
+ }
44
+
45
+
46
+ /**
47
+ * Calculate the delta of a value within a range between min and max with overflow
48
+ * @param {*} data
49
+ * @param {*} delta
50
+ * @param {*} min
51
+ * @param {*} max
52
+ * @returns
53
+ */
54
+ export function calcDelta (data, delta, min = 0, max = 100) {
55
+ data = data + delta
56
+ if (data > max) { data = min }
57
+ else if (data < min) { data = max }
58
+ return data
59
+ }
60
+
61
+ /**
62
+ * Invert a color in hex format (#RRGGBB) to its inverted color
63
+ * @param {*} colorAsHex
64
+ * @returns
65
+ */
66
+ export function invertColor(colorAsHex){
67
+ let rgb = colorToRGB(colorAsHex)
68
+ for (var i = 0; i < rgb.length; i++) {
69
+ rgb[i] = (i === 3 ? 1 : 255) - rgb[i];
70
+ }
71
+ let invertedColor = `#${rgb[0].toString(16)}${rgb[1].toString(16)}${rgb[2].toString(16)})`
72
+ //let invertedColor = `#${rgb[0].toString(16).padStart(2, '0')}${rgb[1].toString(16).padStart(2, '0')}${rgb[2].toString(16).padStart(2, '0')})`
73
+ //console.log("invert", colorAsHex,"=>",invertedColor)
74
+ return invertedColor
75
+ }
76
+
77
+ /**
78
+ * Convert a color in hex format (#RRGGBB) to RGB array
79
+ * @param {*} colorAsHex
80
+ * @returns
81
+ */
82
+ export function colorToRGB(colorAsHex){
83
+ const r = parseInt(colorAsHex.slice(1, 3), 16)
84
+ const g = parseInt(colorAsHex.slice(3, 5), 16)
85
+ const b = parseInt(colorAsHex.slice(5, 7), 16)
86
+ return [r,g,b]
87
+ }
88
+
89
+ /**
90
+ * Synchronize the parameters of a node with the default node
91
+ * @param {*} node
92
+ * @param {*} defaultnode
93
+ * @returns node
94
+ */
95
+ export function syncParams(node, defaultnode){
96
+ if (node === undefined || defaultnode === undefined)
97
+ return node
98
+ let keys = Object.keys(defaultnode)
99
+ for (var i=0;i<keys.length;i++){
100
+ let key = keys[i]
101
+ if (!(key in node))
102
+ node[key] = defaultnode[key]
103
+ }
104
+ return node
105
+ }
106
+
package/config.yaml CHANGED
@@ -1,6 +1,8 @@
1
- application: Example
2
- profiles:
3
- - name: profile-1
4
- file: profile-1.yaml
5
- - name: profile-2
6
- file: profile-2.yaml
1
+ application: Example
2
+ parameters:
3
+ verbose: true
4
+ profiles:
5
+ - name: profile-1
6
+ file: profile-1.yaml
7
+ - name: profile-2
8
+ file: profile-2.yaml
package/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { BaseLoupeDeckHandler } from './common/BaseLoupeDeckHandler.mjs'
2
-
3
- export { BaseLoupeDeckHandler }
1
+ import { BaseLoupeDeckHandler } from './common/BaseLoupeDeckHandler.mjs'
2
+
3
+ export { BaseLoupeDeckHandler }
@@ -1,71 +1,71 @@
1
- import format from 'string-template'
2
- import { EventEmitter } from 'node:events'
3
-
4
- export class BaseIf extends EventEmitter {
5
- formattedCommand
6
- cmd
7
- options
8
- call (cmd, options = {}) {
9
- var res = this.Check(options)
10
- if (res < 0){
11
- this.LogError("Missing essential options in dictionary => Quitting\n",res,options)
12
- return false
13
- }
14
-
15
- this.cmd = cmd
16
- this.options = options
17
- this.formattedCommand = this.formatString(cmd, options)
18
- this.LogDebug("Formatted command: ", this.formattedCommand,"\n")
19
- this.LogDebug("Options",JSON.stringify(options),"\n" )
20
- return this.formattedCommand
21
- }
22
-
23
- async stop (){
24
-
25
- }
26
-
27
- formatString (cmd, options = {}) {
28
- let f =""
29
- try{
30
- f = format(cmd, options)
31
- }catch(e){}
32
- return f
33
- }
34
-
35
- Check(options) {
36
- if (!"id" in options)
37
- return -1
38
- if (!"key" in options)
39
- return -2
40
- if (!"state" in options)
41
- return -3
42
- if (!"min" in options)
43
- return -4
44
- if (!"max" in options)
45
- return -5
46
- if (!"color" in options)
47
- return -6
48
- if (!"image" in options)
49
- return -7
50
- return 0
51
- }
52
-
53
- LogError(...args){
54
- let str = new String(args)
55
- process.stderr.write(str.toString())
56
- }
57
-
58
- LogDebug(...args){
59
- if (this.options && this.options.verbose){
60
- let str = args.join(' ')
61
- process.stdout.write(str.toString())
62
- }
63
- }
64
-
65
- LogInfo(...args){
66
- let str = new String(args)
67
- process.stdout.write(str.toString())
68
- }
69
- }
70
-
71
-
1
+ import format from 'string-template'
2
+ import { EventEmitter } from 'node:events'
3
+
4
+ export class BaseIf extends EventEmitter {
5
+ formattedCommand
6
+ cmd
7
+ options
8
+ call (cmd, options = {}) {
9
+ var res = this.Check(options)
10
+ if (res < 0){
11
+ this.LogError("Missing essential options in dictionary => Quitting\n",res,options)
12
+ return false
13
+ }
14
+
15
+ this.cmd = cmd
16
+ this.options = options
17
+ this.formattedCommand = this.formatString(cmd, options)
18
+ this.LogDebug("Formatted command: ", this.formattedCommand,"\n")
19
+ this.LogDebug("Options",JSON.stringify(options),"\n" )
20
+ return this.formattedCommand
21
+ }
22
+
23
+ async stop (){
24
+
25
+ }
26
+
27
+ formatString (cmd, options = {}) {
28
+ let f =""
29
+ try{
30
+ f = format(cmd, options)
31
+ }catch(e){}
32
+ return f
33
+ }
34
+
35
+ Check(options) {
36
+ if (!"id" in options)
37
+ return -1
38
+ if (!"key" in options)
39
+ return -2
40
+ if (!"state" in options)
41
+ return -3
42
+ if (!"min" in options)
43
+ return -4
44
+ if (!"max" in options)
45
+ return -5
46
+ if (!"color" in options)
47
+ return -6
48
+ if (!"image" in options)
49
+ return -7
50
+ return 0
51
+ }
52
+
53
+ LogError(...args){
54
+ let str = new String(args)
55
+ process.stderr.write(str.toString())
56
+ }
57
+
58
+ LogDebug(...args){
59
+ if (this.options && this.options.verbose){
60
+ let str = args.join(' ')
61
+ process.stdout.write(str.toString())
62
+ }
63
+ }
64
+
65
+ LogInfo(...args){
66
+ let str = new String(args)
67
+ process.stdout.write(str.toString())
68
+ }
69
+ }
70
+
71
+
@@ -1,90 +1,90 @@
1
- import * as http from 'node:http'
2
- import url from 'node:url'
3
- import { BaseIf } from './baseif.mjs'
4
-
5
- /**
6
- * Our Special-Handler just used the Default - and adds Vibration after triggers through Button-Releases
7
- */
8
- export class HTTPif extends BaseIf {
9
- async call (url1, options = {}) {
10
- var res = this.Check(options)
11
- if (res<0){
12
- // this.LogError(`HTTPif call: Missing essential options in dictionary => Quitting`,res,"\n")
13
- return false
14
- }
15
- let urlFormatted = super.call(url1, options)
16
- let myURL
17
- try {
18
- myURL = new url.URL(urlFormatted)
19
- await this.get(myURL, options)
20
- } catch (e) {
21
- this.LogError(`HTTPif: error with URL: ${e.message}\n`)
22
- return false
23
- }
24
- return true
25
- }
26
-
27
- async stop(){
28
- this.LogInfo("HTTPif: Stopped\n")
29
-
30
- }
31
-
32
- Check(options) {
33
- var res= super.Check(options)
34
- if (res <0){
35
- this.LogError(`HTTPif: mandatory parameter missing\n`)
36
- return res
37
- }
38
- if (!options.hostname){
39
- this.LogError(`HTTPif: mandatory parameter hostname missing\n`)
40
- return -21
41
- }
42
- return 0
43
- }
44
-
45
- /**
46
- * Handle a HTTP Get request with Basic Authentification
47
- * @param {*} myURL Uri
48
- */
49
- async get (myURL) {
50
- const auth = 'Basic ' + Buffer.from(myURL.username + ':' + myURL.password).toString('base64')
51
- const getOptions = {
52
- hostname: myURL.hostname,
53
- port: myURL.port,
54
- path: myURL.pathname,
55
- agent: false, // Create a new agent just for this one request
56
- headers: {
57
- Authorization: auth
58
- }
59
- }
60
-
61
- this.LogInfo(`HTTPIf: call URL ${myURL} ${getOptions}\n`)
62
-
63
-
64
- const prom = new Promise((resolve, reject) => {
65
- const req = http.get(getOptions, (response) => {
66
- const chunksOfData = []
67
-
68
- response.on('data', (fragments) => {
69
- chunksOfData.push(fragments)
70
- })
71
-
72
- response.on('end', () => {
73
- const responseBody = Buffer.concat(chunksOfData)
74
- resolve(responseBody.toString())
75
- })
76
-
77
- response.on('error', (error) => {
78
- resolve("")
79
- })
80
- })
81
-
82
- req.on('error', (e) => {
83
- this.LogError(`HTTPif: ignore other errors like ERRNOTCONNECTED: ${e.message}\n`)
84
- return false
85
- });
86
- }).catch(function (error) { // (*)
87
- return false
88
- })
89
- }
90
- }
1
+ import * as http from 'node:http'
2
+ import url from 'node:url'
3
+ import { BaseIf } from './baseif.mjs'
4
+
5
+ /**
6
+ * Our Special-Handler just used the Default - and adds Vibration after triggers through Button-Releases
7
+ */
8
+ export class HTTPif extends BaseIf {
9
+ async call (url1, options = {}) {
10
+ var res = this.Check(options)
11
+ if (res<0){
12
+ // this.LogError(`HTTPif call: Missing essential options in dictionary => Quitting`,res,"\n")
13
+ return false
14
+ }
15
+ let urlFormatted = super.call(url1, options)
16
+ let myURL
17
+ try {
18
+ myURL = new url.URL(urlFormatted)
19
+ await this.get(myURL, options)
20
+ } catch (e) {
21
+ this.LogError(`HTTPif: error with URL: ${e.message}\n`)
22
+ return false
23
+ }
24
+ return true
25
+ }
26
+
27
+ async stop(){
28
+ this.LogInfo("HTTPif: Stopped\n")
29
+
30
+ }
31
+
32
+ Check(options) {
33
+ var res= super.Check(options)
34
+ if (res <0){
35
+ this.LogError(`HTTPif: mandatory parameter missing\n`)
36
+ return res
37
+ }
38
+ if (!options.hostname){
39
+ this.LogError(`HTTPif: mandatory parameter hostname missing\n`)
40
+ return -21
41
+ }
42
+ return 0
43
+ }
44
+
45
+ /**
46
+ * Handle a HTTP Get request with Basic Authentification
47
+ * @param {*} myURL Uri
48
+ */
49
+ async get (myURL) {
50
+ const auth = 'Basic ' + Buffer.from(myURL.username + ':' + myURL.password).toString('base64')
51
+ const getOptions = {
52
+ hostname: myURL.hostname,
53
+ port: myURL.port,
54
+ path: myURL.pathname,
55
+ agent: false, // Create a new agent just for this one request
56
+ headers: {
57
+ Authorization: auth
58
+ }
59
+ }
60
+
61
+ this.LogInfo(`HTTPIf: call URL ${myURL} ${getOptions}\n`)
62
+
63
+
64
+ const prom = new Promise((resolve, reject) => {
65
+ const req = http.get(getOptions, (response) => {
66
+ const chunksOfData = []
67
+
68
+ response.on('data', (fragments) => {
69
+ chunksOfData.push(fragments)
70
+ })
71
+
72
+ response.on('end', () => {
73
+ const responseBody = Buffer.concat(chunksOfData)
74
+ resolve(responseBody.toString())
75
+ })
76
+
77
+ response.on('error', (error) => {
78
+ resolve("")
79
+ })
80
+ })
81
+
82
+ req.on('error', (e) => {
83
+ this.LogError(`HTTPif: ignore other errors like ERRNOTCONNECTED: ${e.message}\n`)
84
+ return false
85
+ });
86
+ }).catch(function (error) { // (*)
87
+ return false
88
+ })
89
+ }
90
+ }
@@ -1,34 +1,34 @@
1
- import * as shellif from '../interfaces/shellif.mjs'
2
- import * as httpif from '../interfaces/httpif.mjs'
3
- import * as opcuaif from '../interfaces/opcuaif.mjs'
4
- import { EventEmitter } from 'node:events'
5
-
6
- export var opcuainterface = undefined
7
- export var httpinterface = undefined
8
- export var shellinterface = undefined
9
- export var profileEmitter = undefined
10
-
11
- export async function InitializeInterfaces(appConfig){
12
- if (opcuainterface === undefined ){
13
- opcuainterface = new opcuaif.OPCUAIf()
14
- }
15
- // the opcua interface needs the profile to register nodes with subscriptions:
16
- opcuainterface.init(appConfig.parameters,appConfig)
17
- if (httpinterface === undefined)
18
- httpinterface = new httpif.HTTPif()
19
- if (shellinterface === undefined)
20
- shellinterface = new shellif.SHELLif()
21
- if (profileEmitter === undefined)
22
- profileEmitter = new EventEmitter()
23
- }
24
-
25
- export async function StopInterfaces(){
26
- if (opcuainterface !== undefined )
27
- await opcuainterface.stop()
28
- if (httpinterface !== undefined)
29
- await httpinterface.stop()
30
- if (shellinterface !== undefined)
31
- await shellinterface.stop()
32
-
33
- }
34
-
1
+ import * as shellif from '../interfaces/shellif.mjs'
2
+ import * as httpif from '../interfaces/httpif.mjs'
3
+ import * as opcuaif from '../interfaces/opcuaif.mjs'
4
+ import { EventEmitter } from 'node:events'
5
+
6
+ export var opcuainterface = undefined
7
+ export var httpinterface = undefined
8
+ export var shellinterface = undefined
9
+ export var profileEmitter = undefined
10
+
11
+ export async function InitializeInterfaces(appConfig){
12
+ if (opcuainterface === undefined ){
13
+ opcuainterface = new opcuaif.OPCUAIf()
14
+ }
15
+ // the opcua interface needs the profile to register nodes with subscriptions:
16
+ opcuainterface.init(appConfig.parameters,appConfig)
17
+ if (httpinterface === undefined)
18
+ httpinterface = new httpif.HTTPif()
19
+ if (shellinterface === undefined)
20
+ shellinterface = new shellif.SHELLif()
21
+ if (profileEmitter === undefined)
22
+ profileEmitter = new EventEmitter()
23
+ }
24
+
25
+ export async function StopInterfaces(){
26
+ if (opcuainterface !== undefined )
27
+ await opcuainterface.stop()
28
+ if (httpinterface !== undefined)
29
+ await httpinterface.stop()
30
+ if (shellinterface !== undefined)
31
+ await shellinterface.stop()
32
+
33
+ }
34
+