loupedeck-commander 1.4.1 → 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.
- package/LICENSE +201 -201
- package/README.md +131 -131
- package/common/ApplicationConfig.mjs +300 -300
- package/common/BaseLoupeDeckHandler.mjs +393 -381
- package/common/ButtonField.mjs +168 -166
- package/common/button.mjs +533 -520
- package/common/cmd-executer.mjs +16 -16
- package/common/index.mjs +5 -5
- package/common/utils.mjs +106 -106
- package/config.yaml +8 -8
- package/index.mjs +3 -3
- package/interfaces/baseif.mjs +71 -71
- package/interfaces/httpif.mjs +90 -90
- package/interfaces/interfaces.mjs +34 -34
- package/interfaces/opcuaif.mjs +484 -481
- package/interfaces/shellif.mjs +58 -58
- package/package.json +32 -32
- package/profile-1.yaml +186 -188
- package/profile-2.yaml +213 -215
- package/test.mjs +40 -40
package/common/cmd-executer.mjs
CHANGED
|
@@ -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,8 +1,8 @@
|
|
|
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
|
|
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 }
|
package/interfaces/baseif.mjs
CHANGED
|
@@ -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
|
+
|
package/interfaces/httpif.mjs
CHANGED
|
@@ -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
|
+
|