Skip to content

Commit c90c592

Browse files
authored
Merge pull request #74 from istnv/feat/mctrlxxx
Adds Blank/Freeze commands for older MCTRLXXX
2 parents 1f43168 + 9d61a46 commit c90c592

File tree

5 files changed

+142
-81
lines changed

5 files changed

+142
-81
lines changed

actions.js

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,5 @@
11
const nova_config = require('./choices')
22

3-
// calculates the checksum that is required when sending a bytestream for layer configuration to the VX1000
4-
function getLayerUpdateCommandVX1000Checksum(pipCommandBuffer) {
5-
// we can't include the first two bytes in our checksum calculation, so we are taking a subarray excluding the first two bytes
6-
const summableBuffer = pipCommandBuffer.subarray(2)
7-
8-
let sum = 0
9-
10-
// sum up all of the bytes (except for the first two bytes)
11-
for (let i = 0; i < summableBuffer.length; i++) {
12-
sum += summableBuffer[i]
13-
}
14-
15-
// add the magic number (from novastar) to the end of the sum to generate the checksum
16-
sum += 0x5555
17-
18-
// split the sum into two bytes in little endian, this will be placed on the end of our command to serve as the checksum for the VX1000 to verify
19-
const resultChecksumBuffer = Buffer.allocUnsafe(2)
20-
resultChecksumBuffer.writeInt16LE(sum)
21-
22-
return resultChecksumBuffer
23-
}
24-
253
// function to build the byte sequence given the configurable layer options for configuring layers on VX1000
264
function getLayerUpdateCommandVX1000(
275
enabled,
@@ -92,7 +70,7 @@ function getLayerUpdateCommandVX1000(
9270
bufferArray.push(initialOpacityBuffer)
9371

9472
// calculate checksum for the last two bytes
95-
bufferArray.push(getLayerUpdateCommandVX1000Checksum(Buffer.concat(bufferArray)))
73+
bufferArray.push(instance.getCommandChecksum(Buffer.concat(bufferArray)))
9674

9775
// combine all the buffers into a single buffer to send to the device
9876
let commandBuffer = Buffer.concat(bufferArray)
@@ -101,17 +79,15 @@ function getLayerUpdateCommandVX1000(
10179
return commandBuffer
10280
}
10381

104-
function makeBrightnessCommand(pct) {
105-
let val = Math.round(255 * (pct / 100))
82+
function makeBrightnessCommand(pct,instance) {
83+
let val = Math.round(255 * pct / 100)
10684
let buf = []
10785

10886
buf.push(
109-
Buffer.from([
110-
0x55, 0xaa, 0x00, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, val,
111-
]),
87+
Buffer.from([0x55,0xaa, 0x00, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, val,]),
11288
)
11389
//buf.push(val)
114-
buf.push(getLayerUpdateCommandVX1000Checksum(Buffer.concat(buf)))
90+
buf.push(instance.getCommandChecksum(Buffer.concat(buf)))
11591

11692
return Buffer.concat(buf)
11793
}
@@ -177,7 +153,8 @@ exports.getActions = function (instance) {
177153
/*
178154
Adjust value based on dynamic variable here
179155
*/
180-
let cmd = makeBrightnessCommand(val)
156+
let cmd = makeBrightnessCommand(val,instance)
157+
instance.log('debug',instance.toHexString(cmd));
181158
instance.socket.send(cmd)
182159
},
183160
}
@@ -186,14 +163,14 @@ exports.getActions = function (instance) {
186163
// Change Input
187164
// VX6s, VX4S, NovaProHD, MCTRL4k, VX1000, VX600
188165

189-
if (
190-
instance.config.modelID == 'vx4s' ||
191-
instance.config.modelID == 'vx6s' ||
192-
instance.config.modelID == 'mctrl4k' ||
193-
instance.config.modelID == 'vx1000' ||
194-
instance.config.modelID == 'novaProHD' ||
195-
instance.config.modelID == 'vx600'
196-
)
166+
if (instance.model.inputs) {
167+
// instance.config.modelID == 'vx4s' ||
168+
// instance.config.modelID == 'vx6s' ||
169+
// instance.config.modelID == 'mctrl4k' ||
170+
// instance.config.modelID == 'vx1000' ||
171+
// instance.config.modelID == 'novaProHD' ||
172+
// instance.config.modelID == 'vx600'
173+
// )
197174
actions['change_input'] = {
198175
name: 'Change Input',
199176
options: [
@@ -211,6 +188,7 @@ exports.getActions = function (instance) {
211188
instance.socket.send(element.cmd)
212189
},
213190
}
191+
}
214192

215193
// Change Test patterns
216194
// All models
@@ -254,7 +232,8 @@ exports.getActions = function (instance) {
254232

255233
// Working mode
256234
// VX6s & J6
257-
if (instance.config.modelID == 'vx6s' || instance.config.modelID == 'j6') {
235+
if (instance.model.workingModes) {
236+
// instance.config.modelID == 'vx6s' || instance.config.modelID == 'j6') {
258237
actions['change_working_mode'] = {
259238
name: 'Change Working Mode',
260239
options: [
@@ -276,7 +255,8 @@ exports.getActions = function (instance) {
276255

277256
// PIP
278257
// VX4S, NovaProHD
279-
if (instance.config.modelID == 'vx4s' || instance.config.modelID == 'novaProHD') {
258+
if (instance.model.piponoffs) {
259+
// instance.config.modelID == 'vx4s' || instance.config.modelID == 'novaProHD') {
280260
actions['pip_onoff'] = {
281261
name: 'PIP On/Off',
282262
options: [
@@ -297,7 +277,8 @@ exports.getActions = function (instance) {
297277
}
298278

299279
// Layer update / configuration (VX1000 only)
300-
if (instance.config.modelID == 'vx1000') {
280+
if (instance.model.layers) {
281+
//instance.config.modelID == 'vx1000') {
301282
actions['update_layer_vx1000'] = {
302283
name: 'Update Layer VX1000',
303284
options: [

choices.js

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,38 @@ exports.CHOICES_TESTPATTERNS = [
5454

5555
// VX4S Display Modes
5656
exports.CHOICES_DISPLAYMODE = [
57-
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x00,0xC7,0x56]) },
58-
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x01,0xC8,0x56]) },
59-
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x02,0xC9,0x56]) }
57+
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x00,0xC7,0x56]) },
58+
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x01,0xC8,0x56]) },
59+
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x20,0x02,0x01,0x00,0x02,0xC9,0x56]) }
6060
]
6161

6262
// VX6S Display Modes
6363
exports.CHOICES_DISPLAYMODE_VX6S = [
64-
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x38,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA7,0x56]) },
65-
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x35,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA5,0x56]) },
66-
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x37,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA2,0x56]) }
64+
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x38,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA7,0x56]) },
65+
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x35,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA5,0x56]) },
66+
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x37,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x01,0x00,0x03,0xA2,0x56]) }
6767
]
6868

69-
// VX6S Working Modes
70-
exports.CHOICES_WORKINGMODE_VX6S = [
71-
{ id: '0', label: 'Direct', cmd: Buffer.from([0x55,0xAA,0x00,0xEC,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x00,0x13,0x01,0x00,0x00,0x80,0x57]) },
72-
{ id: '1', label: 'Switcher', cmd: Buffer.from([0x55,0xAA,0x00,0x1E,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x00,0x13,0x01,0x00,0x01,0xB3,0x56]) }
73-
]
69+
// VX600 Display Modes
70+
exports.CHOICES_DISPLAYMODE_VX600 = [
71+
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x03,0x00,0x70,0x56]) },
72+
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0x00,0xFF,0xFF,0x01,0x00,0x02,0x01,0x00,0x02,0x01,0x00,0xFF,0xD8,0x59]) },
73+
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0x00,0xFF,0xFF,0x01,0x00,0x00,0x01,0x00,0x02,0x01,0x00,0xFF,0xD6,0x59]) }
74+
];
75+
76+
// MCTRL Series Display Modes
77+
exports.CHOICES_DISPLAYMODE_MCTRL = [
78+
{ id: '0', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0x01,0x00,0x02,0x01,0x00,0x02,0x01,0x00,0xFF,0xD7,0x5A]) },
79+
{ id: '1', label: 'Unfreeze', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0x01,0x00,0x02,0x01,0x00,0x02,0x01,0x00,0x00,0xD8,0x59]) },
80+
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x01,0x00,0x02,0x01,0x00,0xFF,0xD5,0x5A]) },
81+
{ id: '3', label: 'Unblank', cmd: Buffer.from([0x55,0xAA,0x00,0x80,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x01,0x00,0x02,0x01,0x00,0x00,0xD6,0x59]) },
82+
];
7483

7584
// NovaProUHD Jr & VX1000 Display Modes
7685
exports.CHOICES_DISPLAYMODE_VX1000 = [
77-
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x03,0x00,0x70,0x56]) },
78-
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x04,0x00,0x71,0x56]) },
79-
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x05,0x00,0x72,0x56]) }
86+
{ id: '0', label: 'Normal', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x03,0x00,0x70,0x56]) },
87+
{ id: '1', label: 'Freeze', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x04,0x00,0x71,0x56]) },
88+
{ id: '2', label: 'Black', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x13,0x02,0x00,0x05,0x00,0x72,0x56]) }
8089
];
8190

8291
// VX6S Working Modes
@@ -85,11 +94,12 @@ exports.CHOICES_WORKINGMODE_VX6S = [
8594
{ id: '1', label: 'Switcher', cmd: Buffer.from([0x55,0xAA,0x00,0x1E,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x00,0x13,0x01,0x00,0x01,0xB3,0x56]) }
8695
]
8796

88-
// VX6S Working Modes
97+
// J6 Working Modes
8998
exports.CHOICES_WORKINGMODE_J6 = [
9099
{ id: '0', label: 'Splicer Mode', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x00,0x13,0x01,0x00,0x00,0x94,0x56]) },
91100
{ id: '1', label: 'Switcher Mode', cmd: Buffer.from([0x55,0xAA,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x00,0x13,0x01,0x00,0x01,0x95,0x56]) }
92101
]
102+
93103
// MCTRL4K Inputs
94104
exports.CHOICES_INPUTS_MCTRL4K = [
95105
{ id: '0', label: 'DVI', cmd: Buffer.from([0x55,0xAA,0x00,0x3E,0xFE,0xFF,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x01,0x00,0x61,0x18,0x58]) },
@@ -350,22 +360,29 @@ exports.CHOICES_CONNECTORCODE_VX1000 = [
350360
]
351361

352362
exports.CONFIG_MODEL = {
353-
vx4s: { id: 'vx4s', label: 'VX4S', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_VX4S, displayModes: exports.CHOICES_DISPLAYMODE, presets: exports.CHOICES_PRESETS_VX4S, piponoffs: exports.CHOICES_PIP_ONOFF },
363+
vx4s: { id: 'vx4s', label: 'VX4S', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_VX4S, displayModes: exports.CHOICES_DISPLAYMODE,
364+
presets: exports.CHOICES_PRESETS_VX4S, piponoffs: exports.CHOICES_PIP_ONOFF },
354365

355-
vx6s: { id: 'vx6s', label: 'VX6s', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_VX6S, displayModes: exports.CHOICES_DISPLAYMODE_VX6S, presets: exports.CHOICES_PRESETS_VX6S, workingModes: exports.CHOICES_WORKINGMODE_VX6S },
366+
vx6s: { id: 'vx6s', label: 'VX6s', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_VX6S, displayModes: exports.CHOICES_DISPLAYMODE_VX6S,
367+
presets: exports.CHOICES_PRESETS_VX6S, workingModes: exports.CHOICES_WORKINGMODE_VX6S },
356368

357-
novaProHD: { id: 'novaProHD', label: 'NovaPro HD', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_NOVAPROHD, displayModes: exports.CHOICES_DISPLAYMODE, piponoffs: exports.CHOICES_PIP_ONOFF },
369+
novaProHD: { id: 'novaProHD', label: 'NovaPro HD', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_NOVAPROHD, displayModes: exports.CHOICES_DISPLAYMODE,
370+
piponoffs: exports.CHOICES_PIP_ONOFF },
358371

359-
novaProUHDJr: { id: 'novaProUHDJr', label: 'NovaPro UHD Jr', brightness: exports.CHOICES_BRIGHTNESS_VX1000, displayModes: exports.CHOICES_DISPLAYMODE_VX1000, presets: exports.CHOICES_PRESETS_NovaProUHDJr },
372+
novaProUHDJr: { id: 'novaProUHDJr', label: 'NovaPro UHD Jr', brightness: exports.CHOICES_BRIGHTNESS_VX1000, displayModes: exports.CHOICES_DISPLAYMODE_VX1000,
373+
presets: exports.CHOICES_PRESETS_NovaProUHDJr },
360374

361375
mctrl4k: { id: 'mctrl4k', label: 'MCTRL4K', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_MCTRL4K, displayModes: exports.CHOICES_DISPLAYMODE },
362376

363-
vx1000: {
377+
mctrl: { id: 'mctrl', label: 'MCTRLxx0', brightness: exports.CHOICES_BRIGHTNESS, inputs: exports.CHOICES_INPUTS_MCTRL, displayModes: exports.CHOICES_DISPLAYMODE_MCTRL },
378+
379+
vx1000: {
364380
id: 'vx1000', label: 'VX1000', brightness: exports.CHOICES_BRIGHTNESS_VX1000, displayModes: exports.CHOICES_DISPLAYMODE_VX1000, inputs: exports.CHOICES_INPUTS_VX1000, presets: exports.CHOICES_PRESETS_VX1000, pipOnOffs: exports.CHOICES_PIP_ONOFF,
365381
layers: exports.CHOICES_LAYERS_VX1000, cardNo: exports.CHOICES_CARDNO_VX1000, layerPriority: exports.CHOICES_LAYERPRIORITY_VX1000, connectorCode: exports.CHOICES_CONNECTORCODE_VX1000
366382
},
367383

368-
vx600: { id: 'vx600', label: 'VX600', brightness: exports.CHOICES_BRIGHTNESS_VX1000, displayModes: exports.CHOICES_DISPLAYMODE_VX1000, inputs: exports.CHOICES_INPUTS_VX600, presets: exports.CHOICES_PRESETS_VX1000 },
384+
vx600: { id: 'vx600', label: 'VX600', brightness: exports.CHOICES_BRIGHTNESS_VX1000, displayModes: exports.CHOICES_DISPLAYMODE_VX1000,
385+
inputs: exports.CHOICES_INPUTS_VX600, presets: exports.CHOICES_PRESETS_VX1000 },
369386

370387
vx16s: { id: 'vx16s', label: 'VX16S', brightness: exports.CHOICES_BRIGHTNESS, displayModes: exports.CHOICES_DISPLAYMODE_VX1000, presets: exports.CHOICES_PRESETS_VX1000 },
371388

companion/HELP.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
## NovaStar Controller
1+
# NovaStar Controller
22

33
This module will allow you to control the following NovaStar products: MCTRL4K, VX4S, VX6S, NovaProHD, NovaPro UHD Jr,VX1000, VX600, VX16s And J6
44

5-
### Configuration
5+
There is also some support for MSD300, MCTRL300, MCTRL500, MSD600, MCTRL600, MCTRL660.
6+
Some of these models can be controlled with a RS232 interface bridge.
7+
8+
## Configuration
69

710
- Enter the IP address of the device in the configuration settings.
811
- The device will use TCP port 5200.
@@ -13,8 +16,7 @@ This module will allow you to control the following NovaStar products: MCTRL4K,
1316
- Set Brightness (0.5% - 100%)
1417
- Change Test Patterns
1518
- Change Display Mode
16-
- Change Inputs
17-
- change working mode on VX6S AND J6
19+
- Change working mode on VX6S AND J6
1820
- Recall Presets on VX6s, UHD Jr, VX600, VX16s, VX1000, J6
1921
- Change main and PIP layer settings for VX1000
2022

@@ -27,6 +29,6 @@ This module will allow you to control the following NovaStar products: MCTRL4K,
2729
---
2830

2931
Contributions for development and maintenance of this open source module are always welcome
30-
https://github.com/sponsors/istnv
32+
<https://github.com/sponsors/istnv>
3133

3234
---

0 commit comments

Comments
 (0)