Skip to content

Commit 241861a

Browse files
authored
first release
1 parent 0e2c654 commit 241861a

23 files changed

+3645
-237
lines changed

Diff for: .husky/pre-commit

-1
This file was deleted.

Diff for: .prettierignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
package.json
2-
/LICENSE.md
2+
/LICENSE.md
3+
*.pdf

Diff for: LICENSE

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
MIT License
1+
The MIT License
22

3-
Copyright (c) 2022 Bitfocus AS - Open Source
3+
Copyright (c) 2019 Bitfocus AS & Andreas H. Thomsen (McHauge)
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal
@@ -9,13 +9,14 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99
copies of the Software, and to permit persons to whom the Software is
1010
furnished to do so, subject to the following conditions:
1111

12-
The above copyright notice and this permission notice shall be included in all
13-
copies or substantial portions of the Software.
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
1414

1515
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21-
SOFTWARE.
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.
22+

Diff for: MMX_4262_C_OL.pdf

1.82 MB
Binary file not shown.

Diff for: README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# companion-module-[replace with module name]
1+
# Extron® MMX TCP module
2+
## companion-module-extron-MMX-tcp
23

34
See [HELP.md](./companion/HELP.md) and [LICENSE](./LICENSE)
45

Diff for: actions.js

+294
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
export function getActionDefinitions(self) {
2+
return {
3+
RouteAV: {
4+
name: 'Route Audio & Video',
5+
options: [
6+
{
7+
type: 'dropdown',
8+
id: 'id_output',
9+
label: 'Output:',
10+
//tooltip: '',
11+
default: '1',
12+
choices: self.OUTPUT
13+
},
14+
{
15+
type: 'dropdown',
16+
id: 'id_input',
17+
label: 'Input:',
18+
default: '1',
19+
choices: self.INPUT,
20+
},
21+
],
22+
callback: async (action) => {
23+
24+
const cmd = unescape(await self.parseVariablesInString(action.options.id_input + '*' + action.options.id_output + '!'))
25+
26+
if (cmd != '') {
27+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
28+
29+
if (self.socket !== undefined && self.socket.isConnected) {
30+
self.socket.send(cmd)
31+
} else {
32+
self.log('debug', 'Socket not connected :(')
33+
}
34+
}
35+
},
36+
},
37+
RouteV: {
38+
name: 'Route Video',
39+
options: [
40+
{
41+
type: 'dropdown',
42+
id: 'id_output',
43+
label: 'Output:',
44+
//tooltip: '',
45+
default: '1',
46+
choices: self.OUTPUT
47+
},
48+
{
49+
type: 'dropdown',
50+
id: 'id_input',
51+
label: 'Input:',
52+
default: '1',
53+
choices: self.INPUT,
54+
},
55+
],
56+
callback: async (action) => {
57+
58+
const cmd = unescape(await self.parseVariablesInString(action.options.id_input + '*' + action.options.id_output + '%'))
59+
60+
if (cmd != '') {
61+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
62+
63+
if (self.socket !== undefined && self.socket.isConnected) {
64+
self.socket.send(cmd)
65+
} else {
66+
self.log('debug', 'Socket not connected :(')
67+
}
68+
}
69+
},
70+
},
71+
RouteA: {
72+
name: 'Route Audio',
73+
options: [
74+
{
75+
type: 'dropdown',
76+
id: 'id_output',
77+
label: 'Output:',
78+
//tooltip: '',
79+
default: '1',
80+
choices: self.OUTPUT
81+
},
82+
{
83+
type: 'dropdown',
84+
id: 'id_input',
85+
label: 'Input:',
86+
default: '1',
87+
choices: self.INPUT,
88+
},
89+
],
90+
callback: async (action) => {
91+
92+
const cmd = unescape(await self.parseVariablesInString(action.options.id_input + '*' + action.options.id_output + '$'))
93+
94+
if (cmd != '') {
95+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
96+
97+
if (self.socket !== undefined && self.socket.isConnected) {
98+
self.socket.send(cmd)
99+
} else {
100+
self.log('debug', 'Socket not connected :(')
101+
}
102+
}
103+
},
104+
},
105+
VideoMute: {
106+
name: 'Video Un-/Mute',
107+
options: [
108+
{
109+
type: 'dropdown',
110+
id: 'id_output',
111+
label: 'Output:',
112+
//tooltip: '',
113+
default: '1',
114+
choices: self.OUTPUT.concat({ id: 'All', label: 'All' })
115+
},
116+
{
117+
type: 'dropdown',
118+
id: 'id_mute',
119+
label: 'Mute/Unmute:',
120+
//tooltip: '',
121+
default: '1',
122+
choices: [
123+
{ id: '1', label: 'Mute' },
124+
{ id: '0', label: 'Unmute' },
125+
],
126+
},
127+
],
128+
callback: async (action) => {
129+
if (action.options.id_output === 'All') {
130+
var cmd = unescape(await self.parseVariablesInString(action.options.id_mute + '*B'))
131+
} else {
132+
var cmd = unescape(await self.parseVariablesInString(action.options.id_output + '*' + action.options.id_mute + 'B'))
133+
}
134+
135+
if (cmd !== '') {
136+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
137+
138+
if (self.socket !== undefined && self.socket.isConnected) {
139+
self.socket.send(cmd)
140+
} else {
141+
self.log('debug', 'Socket not connected :(')
142+
}
143+
}
144+
},
145+
},
146+
AudioMute: {
147+
name: 'Audio Un-/Mute',
148+
options: [
149+
{
150+
type: 'dropdown',
151+
id: 'id_output',
152+
label: 'Output:',
153+
//tooltip: '',
154+
default: '1',
155+
choices: self.OUTPUT.concat({ id: 'All', label: 'All' })
156+
},
157+
{
158+
type: 'dropdown',
159+
id: 'id_mute',
160+
label: 'Mute/Unmute:',
161+
//tooltip: '',
162+
default: '1',
163+
choices: [
164+
{ id: '1', label: 'Mute' },
165+
{ id: '0', label: 'Unmute' },
166+
],
167+
},
168+
],
169+
callback: async (action) => {
170+
if (action.options.id_output === 'All') {
171+
self.log('debug', 'all')
172+
var cmd = unescape(await self.parseVariablesInString(action.options.id_mute + '*Z'))
173+
} else {
174+
var cmd = unescape(await self.parseVariablesInString(action.options.id_output + '*' + action.options.id_mute + 'Z'))
175+
}
176+
177+
if (cmd !== '') {
178+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
179+
180+
if (self.socket !== undefined && self.socket.isConnected) {
181+
self.socket.send(cmd)
182+
} else {
183+
self.log('debug', 'Socket not connected :(')
184+
}
185+
}
186+
},
187+
},
188+
AudioLevel: {
189+
name: 'Audio Level',
190+
options: [
191+
{
192+
type: 'dropdown',
193+
id: 'id_input',
194+
label: 'Input:',
195+
default: '1',
196+
choices: self.INPUT,
197+
},
198+
{
199+
type: 'dropdown',
200+
id: 'id_level',
201+
label: 'Level:',
202+
//tooltip: '',
203+
default: '0G',
204+
choices: Array.from({ length: (24 - (-18)) / 1 + 1 }, (_, i) => {
205+
const value = 24 - i * 1;
206+
return { id: `${Math.abs(value)}${value >= 0 ? 'G' : 'g'}`, label: `${value >= 0 ? '+' : ''}${value}dB` };
207+
}),
208+
},
209+
210+
],
211+
callback: async (action) => {
212+
213+
const cmd = unescape(await self.parseVariablesInString(action.options.id_input + '*' + action.options.id_level))
214+
215+
if (cmd != '') {
216+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
217+
218+
if (self.socket !== undefined && self.socket.isConnected) {
219+
self.socket.send(cmd)
220+
} else {
221+
self.log('debug', 'Socket not connected :(')
222+
}
223+
}
224+
},
225+
},
226+
AudioLevelIncDec: {
227+
name: 'Audio Level In-/Decrease',
228+
options: [
229+
{
230+
type: 'dropdown',
231+
id: 'id_input',
232+
label: 'Input:',
233+
default: '1',
234+
choices: self.INPUT,
235+
},
236+
{
237+
type: 'dropdown',
238+
id: 'id_dir',
239+
label: 'Direction:',
240+
default: '+',
241+
tooltip: 'in 1dB steps',
242+
choices: [
243+
{ id: '+', label: 'Increase +1dB' },
244+
{ id: '-', label: 'Decrease -1dB' },
245+
],
246+
},
247+
],
248+
callback: async (action) => {
249+
250+
const cmd = unescape(await self.parseVariablesInString(action.options.id_input + action.options.id_dir + 'G'))
251+
252+
if (cmd != '') {
253+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
254+
255+
if (self.socket !== undefined && self.socket.isConnected) {
256+
self.socket.send(cmd)
257+
} else {
258+
self.log('debug', 'Socket not connected :(')
259+
}
260+
}
261+
},
262+
},
263+
Frontpanel: {
264+
name: 'Frontpanel',
265+
options: [
266+
{
267+
type: 'dropdown',
268+
id: 'id_lock',
269+
label: 'Lock/Unlock:',
270+
default: '1',
271+
choices: [
272+
{ id: '1', label: 'Lock' },
273+
{ id: '0', label: 'Unlock' },
274+
],
275+
},
276+
],
277+
278+
callback: async (action) => {
279+
280+
const cmd = unescape(await self.parseVariablesInString(action.options.id_lock + 'X'))
281+
282+
if (cmd != '') {
283+
self.log('debug', 'sending to ' + self.config.host + ': ' + cmd.toString())
284+
285+
if (self.socket !== undefined && self.socket.isConnected) {
286+
self.socket.send(cmd)
287+
} else {
288+
self.log('debug', 'Socket not connected :(')
289+
}
290+
}
291+
},
292+
},
293+
}
294+
}

Diff for: companion/HELP.md

+40-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,41 @@
1-
## Your module
1+
# Extron® MMX TCP module
22

3-
Write some help for your users here!
3+
A module to control Extron® MMX AV switchers via serial RS232 in conjunction with generic TCP Serial module.
4+
Commands are Extron® SIS™ (Extron Simple Instruction Set) and taken from documentation:
5+
https://media.extron.com/public/download/files/userman/MMX_4262_C_OL.pdf
6+
[or here](../MMX_4262_C_OL.pdf)
7+
8+
## Configuration
9+
10+
| Option | Description |
11+
| --------------------- | ---------------------------------------------------------------- |
12+
| Target IP | Destination Host name / IP of the generic TCP Serial Module (TSP)|
13+
| Target Port | Destination port |
14+
| Save TCP Response | Option to save the last response received via TCP |
15+
16+
## Actions
17+
18+
- Create a video and audio tie/route
19+
- Create a video only tie/route
20+
- Create an audio only tie/route
21+
- Mute/Unmute Audio and or Video
22+
- Set audio level (+24dB to -18dB)
23+
- Increment/Decrement audio level
24+
- Frontpanel Lock/Unlock
25+
26+
## Feedbacks
27+
- View video output tie/route
28+
- View audio output tie/route
29+
- View Audio / Video mute
30+
- View audio level
31+
- View front panel lock status
32+
- Information request
33+
34+
## Variables
35+
36+
If enabled, the last response received via TCP will be stored in `$(NAME:tcp_response)`
37+
`$(NAME:AudioLevelIn1)`
38+
`$(NAME:AudioLevelIn2)`
39+
`$(NAME:AudioLevelIn3)`
40+
`$(NAME:AudioLevelIn4)`
41+
`$(NAME:FrontpanelLock)`

0 commit comments

Comments
 (0)