@bannsaenger/node-red-contrib-artnet-controller
Version:
Node-RED node that controls lights via Art-Net. Acts as a Art-Net controller.
372 lines (356 loc) • 19.8 kB
HTML
<script type="text/x-red" data-template-name="Art-Net Out">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-artnetsender"><i class="fa fa-bookmark"></i> Sender</label>
<input type="text" id="node-input-artnetsender">
</div>
<div class="form-row">
<label for="node-input-ignoreaddress"><i class="fa fa-ban"></i> <span data-i18n="artnet.label.ignoreaddress"></span></label>
<input type="checkbox" id="node-input-ignoreaddress" style="display: inline-block; width: auto; vertical-align: top;">
</div>
<div class="form-row">
<label for="node-input-artnetsender"><i class="fa fa-replay"></i> <span data-i18n="artnet.label.feedback"></span></label>
<input type="text" id="node-input-feedback">
</div>
<div class="form-tips" id="tip-ignoreaddress" hidden><span data-i18n="[html]artnet.tip.ignoreaddress"></span></div>
<div class="form-tips" id="tip-feedback" hidden><span data-i18n="[html]artnet.tip.feedback"></span></div>
</script>
<script type="text/javascript">
RED.nodes.registerType('Art-Net Out',{
category: 'output',
color: '#a6bbcf',
defaults: {
name: {value: ""},
artnetsender: {value: "", type: "Art-Net Sender"},
ignoreaddress: {value: false},
feedback: {value: "none"}
},
inputs:1,
outputs:1,
align: "right",
icon: "light.png",
label: function() {
return this.name || "Art-Net Out";
},
oneditprepare: function () {
$('#node-input-ignoreaddress').on('focus', function () { $('#tip-ignoreaddress').show(); });
$('#node-input-ignoreaddress').on('blur', function () { $('#tip-ignoreaddress').hide(); });
$('#node-input-feedback').on('focus', function () { $('#tip-feedback').show(); });
$('#node-input-feedback').on('blur', function () { $('#tip-feedback').hide(); });
$('#node-input-ignoreaddress').prop('checked', this.savevalues);
$('#node-input-feedback').typedInput({types:[{value: 'feedback', options: [{value: 'none', label: "None"},{value: 'onlyEnd', label: 'Only end of transition'},{value: 'all', label: 'All'}]}]});
$('#node-input-feedback').typedInput('value', value);
},
oneditsave: function () {
this.ignoreaddress = $('#node-input-ignoreaddress').prop('checked');
this.feedback = $('#node-input-feedback').typedInput('value');
}
});
</script>
<script type="text/x-red" data-template-name="Art-Net In">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="artnet.label.name"></span></label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-artnetcontroller"><i class="fa fa-bookmark"></i> Controller</label>
<input type="text" id="node-input-artnetcontroller">
</div>
<div class="form-row">
<label for="node-input-net"><i class="fa fa-cog"></i> Net</label>
<input type="text" id="node-input-net">
</div>
<div class="form-row">
<label for="node-input-subnet"><i class="fa fa-cogs"></i> Subnet</label>
<input type="text" id="node-input-subnet">
</div>
<div class="form-row">
<label for="node-input-universe"><i class="fa fa-globe"></i> Universe</label>
<input type="text" id="node-input-universe">
</div>
<div class="form-row">
<label for="node-input-outformat"><i class="fa fa-file-code-o"></i> <span data-i18n="artnet.label.outformat"></label>
<input type="text" id="node-input-outformat">
</div>
<div class="form-row">
<label for="node-input-sendonchange"><i class="fa fa-ban"></i> <span data-i18n="artnet.label.sendonchange"></span></label>
<input type="checkbox" id="node-input-sendonchange" style="display: inline-block; width: auto; vertical-align: top;">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('Art-Net In',{
category: 'input',
color: '#a6bbcf',
defaults: {
name: {value: ""},
artnetcontroller: {value: "", type: "Art-Net Controller"},
net: {value: 0, validate:function(v) {return ((v >= 0) && (v < 128) && (v == parseInt(v, 10)))} },
subnet: {value: 0, validate:function(v) {return ((v >= 0) && (v < 16) && (v == parseInt(v, 10)))} },
universe: {value: 0, validate:function(v) {return ((v >= 0) && (v < 16) && (v == parseInt(v, 10)))} },
outformat: {value: "buckets"},
sendonchange: {value: true}
},
inputs:0,
outputs:1,
align: "right",
icon: "light.png",
label: function() {
if (this.name) return this.name;
var controllerAddress = RED.nodes.node(this.artnetcontroller);
return controllerAddress ? ('In:' + this.net + ':' + this.subnet + ':' + this.universe + '-' + controllerAddress.bind) : 'Art-Net In';
},
oneditprepare: function() {
$('#node-input-outformat').typedInput({types:[{value: 'outformat', options: [{value: 'buckets', label: 'Buckets'},{value: 'buffer', label: 'Universe as Uint8Array'}]}]});
$('#node-input-outformat').typedInput('value', value);
$('#node-input-sendonchange').prop('checked', this.sendonchange);
},
oneditsave: function() {
this.outformat = $('#node-input-outformat').typedInput('value');
this.sendonchange = $('#node-input-sendonchange').prop('checked');
}
});
</script>
<script type="text/x-red" data-template-name="Art-Net Sender">
<div class="form-row">
<label for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="artnet.label.name"></span></label>
<input type="text" id="node-config-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-config-input-artnetcontroller"><i class="fa fa-bookmark"></i> Controller</label>
<input type="text" id="node-config-input-artnetcontroller">
</div>
<div class="form-row">
<label for="node-config-input-address"><i class="fa fa-server"></i> <span data-i18n="artnet.label.bind"></span></label>
<input type="text" id="node-config-input-address">
</div>
<div class="form-row">
<label for="node-config-input-port"><i class="fa fa-long-arrow-right"></i> <span data-i18n="artnet.label.port"></span></label>
<input type="text" id="node-config-input-port">
</div>
<div class="form-row">
<label for="node-config-input-net"><i class="fa fa-cog"></i> Net</label>
<input type="text" id="node-config-input-net">
</div>
<div class="form-row">
<label for="node-config-input-subnet"><i class="fa fa-cogs"></i> Subnet</label>
<input type="text" id="node-config-input-subnet">
</div>
<div class="form-row">
<label for="node-config-input-universe"><i class="fa fa-globe"></i> Universe</label>
<input type="text" id="node-config-input-universe">
</div>
<div class="form-row">
<label for="node-config-input-maxrate"><i class="fa fa-rocket"></i> <span data-i18n="artnet.label.maxrate"></span></label>
<input type="text" id="node-config-input-maxrate">
</div>
<div class="form-row">
<label for="node-config-input-refresh"><i class="fa fa-clock-o"></i> <span data-i18n="artnet.label.refresh"></span></label>
<input type="text" id="node-config-input-refresh">
</div>
<div class="form-row">
<label for="node-config-input-savevalues"><i class="fa fa-hdd-o"></i> <span data-i18n="artnet.label.savevalues"></span></label>
<input type="checkbox" id="node-config-input-savevalues" style="display: inline-block; width: auto; vertical-align: top;">
</div>
<div class="form-tips" id="tip-address" hidden><span data-i18n="[html]artnet.tip.address"></span></div>
<div class="form-tips" id="tip-maxrate" hidden><span data-i18n="[html]artnet.tip.maxrate"></span></div>
<div class="form-tips" id="tip-refresh" hidden><span data-i18n="[html]artnet.tip.refresh"></span></div>
<div class="form-tips" id="tip-savevalues" hidden><span data-i18n="[html]artnet.tip.savevalues"></span></div>
</script>
<script type="text/javascript">
RED.nodes.registerType('Art-Net Sender',{
category: 'config',
defaults: {
name: {value: ""},
artnetcontroller: {value: "", type: "Art-Net Controller"},
address: {value: "127.0.0.1"},
port: {value: 6454, validate:function(v) {return ((v >= 0) && (v < 65536) && (v == parseInt(v, 10)))}},
net: {value: 0, validate:function(v) {return ((v >= 0) && (v < 128) && (v == parseInt(v, 10)))}},
subnet: {value: 0, validate:function(v) {return ((v >= 0) && (v < 16) && (v == parseInt(v, 10)))}},
universe: {value: 0, validate:function(v) {return ((v >= 0) && (v < 16) && (v == parseInt(v, 10)))}},
maxrate: {value: 10, validate:function(v) {
if ((v >= 0) && (v <= 50) && (v == parseInt(v, 10))) {
if (v == 0) return true;
var refresh = $("#node-config-input-refresh").val() || this.refresh;
if (refresh > (1000 / v)) return true;
}
return false;
}},
refresh: {value: 1000, validate:function(v) {
if ((v >= 20) && (v <= 100000) && (v == parseInt(v, 10))) {
var maxrate = $("#node-config-input-maxrate").val() || this.maxrate;
if (maxrate == 0) return true;
if (v > (1000 / maxrate)) return true;
}
return false;
}},
savevalues: {value: true}
},
label: function() {
return this.name || this.net + ':' + this.subnet + ':' + this.universe + '-' + this.address;
},
oneditprepare: function () {
$('#node-config-input-address').on('focus', function () { $('#tip-address').show(); });
$('#node-config-input-address').on('blur', function () { $('#tip-address').hide(); });
$('#node-config-input-maxrate').on('focus', function () { $('#tip-maxrate').show(); });
$('#node-config-input-maxrate').on('blur', function () { $('#tip-maxrate').hide(); });
$('#node-config-input-refresh').on('focus', function () { $('#tip-refresh').show(); });
$('#node-config-input-refresh').on('blur', function () { $('#tip-refresh').hide(); });
$('#node-config-input-savevalues').on('focus', function () { $('#tip-savevalues').show(); });
$('#node-config-input-savevalues').on('blur', function () { $('#tip-savevalues').hide(); });
$('#node-config-input-savevalues').prop('checked', this.savevalues);
},
oneditsave: function () {
this.savevalues = $('#node-config-input-savevalues').prop('checked');
}
});
</script>
<script type="text/html" data-template-name="Art-Net Controller">
<div class="form-row">
<label for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="artnet.label.name"></span></label>
<input type="text" id="node-config-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-config-input-bind"><i class="fa fa-server"></i> <span data-i18n="artnet.label.bind"></span></label>
<input type="text" id="node-config-input-bind">
</div>
<div class="form-row">
<label for="node-config-input-port"><i class="fa fa-long-arrow-right"></i> <span data-i18n="artnet.label.port"></span></label>
<input type="text" id="node-config-input-port">
</div>
<div class="form-row">
<label for="node-config-input-oemcode"><i class="fa fa-certificate"></i> <span data-i18n="artnet.label.oemcode"></span></label>
<input type="text" id="node-config-input-oemcode">
</div>
<div class="form-row">
<label for="node-config-input-estacode"><i class="fa fa-certificate"></i> <span data-i18n="artnet.label.estacode"></span></label>
<input type="text" id="node-config-input-estacode">
</div>
<div class="form-row">
<label for="node-config-input-sname"><i class="fa fa-tag"></i> <span data-i18n="artnet.label.sname"></span></label>
<input type="text" id="node-config-input-sname">
</div>
<div class="form-row">
<label for="node-config-input-lname"><i class="fa fa-tag"></i> <span data-i18n="artnet.label.lname"></span></label>
<input type="text" id="node-config-input-lname">
</div>
<div class="form-row"><hr></div>
<div class="form-row">
<span data-i18n="[html]artnet.description.debug"></span>
</div>
<div class="form-row">
<label for="node-config-input-loglevel"><i class="fa fa-print"></i> <span data-i18n="artnet.label.debug"></span></label>
<input type="text" id="node-config-input-loglevel">
</div>
<div class="form-tips" id="tip-bind"><span data-i18n="artnet.tip.bind"></span></div>
<div class="form-tips" id="tip-port" hidden><span data-i18n="artnet.tip.port"></span></div>
<div class="form-tips" id="tip-oemcode"><span data-i18n="artnet.tip.oemcode"></span></div>
<div class="form-tips" id="tip-estacode"><span data-i18n="artnet.tip.estacode"></span></div>
</script>
<script type="text/javascript">
RED.nodes.registerType('Art-Net Controller', {
category: 'config',
defaults: {
name: {value: ""},
bind: { value: '', required: true },
port: { value: 6454, validate:function(v) {return ((v >= 0) && (v < 65536) && (v == parseInt(v, 10)))} },
sname: { value: 'dmxnet', validate:RED.validators.regex(/^.{0,17}$/) },
lname: { value: 'dmxnet - OpenSource ArtNet Transceiver', validate:RED.validators.regex(/^.{0,63}$/) },
oemcode: { value: '0x2908', validate:RED.validators.regex(/^0x[0-9A-Fa-f]{4}$/) },
estacode: { value: '0x0000', validate:RED.validators.regex(/^0x[0-9A-Fa-f]{4}$/) },
loglevel: { value: 'warn' }
},
label: function() {
return this.bind || 'No IP';
},
oneditprepare: function() {
var bind = this.bind;
try {
$.getJSON('ips',function(ips) {
var inputOptions = {types:[{value: 'bind', options: []}]};
for (var i = 0; i < ips.length; i++) {
if (ips[i].name.includes('[IPv6]')) continue; // for safety reasons. No V6 addresses will be sent
inputOptions.types[0].options.push({value: ips[i].address, label: ips[i].name});
}
$('#node-config-input-bind').typedInput(inputOptions);
$('#node-config-input-bind').typedInput('value', bind);
});
}
catch(err) {
$('#node-config-input-bind').typedInput({types:[{value: 'bind', options: []}]});
}
// OEM Codes
var oemItems = [
{value: '0x0000', label: '0x0000 (ProductName: Dmx-Hub, Manufacturer: Artistic Licence Engineering Ltd)', hasValue: false},
{value: '0x2908', label: '0x2908 (ProductName: dmxnet, Manufacturer: margau)', hasValue: false},
{value: 'custom', label: 'custom', icon:'red/images/typedInput/target.svg', validate: /^0x[0-9A-Fa-f]{4}$/}
];
var oemType = "custom";
for (var i in oemItems) {
if (this.oemcode == oemItems[i].value) {
oemType = this.oemcode;
}
}
$('#node-config-input-oemcode').typedInput({
default: oemType,
types: oemItems
});
// ESTA Codes
var estaItems = [
{value: '0x0000', label: '0x0000 (Manufacturer: ESTA/PLASA)', hasValue: false},
{value: '0x414C', label: '0x414C (Manufacturer: Artistic Licence Engineering Ltd.)', hasValue: false},
{value: 'custom', label: 'custom', icon:'red/images/typedInput/target.svg', validate: /^0x[0-9A-Fa-f]{4}$/}
];
var estaType = "custom";
for (var i in estaItems) {
if (this.estacode == estaItems[i].value) {
estaType = this.estacode;
}
}
$('#node-config-input-estacode').typedInput({
default: estaType,
types: estaItems
});
// Loglevel
$('#node-config-input-loglevel').typedInput({
types: [{
value: 'loglevel',
options: [
{value: 'error', label: 'error'},
{value: 'warn', label: 'warn (default)'},
{value: 'info', label: 'info'},
{value: 'verbose', label: 'verbose'},
{value: 'debug', label: 'debug'},
{value: 'silly', label: 'silly'}
]
}]
});
$('#node-config-input-bind').on('focus', function () { $('#tip-bind').show(); });
$('#node-config-input-bind').on('blur', function () { $('#tip-bind').hide(); });
$('#node-config-input-port').on('focus', function () { $('#tip-port').show(); });
$('#node-config-input-port').on('blur', function () { $('#tip-port').hide(); });
$('#node-config-input-oemcode').on('focus', function () { $('#tip-oemcode').show(); });
$('#node-config-input-oemcode').on('blur', function () { $('#tip-oemcode').hide(); });
$('#node-config-input-estacode').on('focus', function () { $('#tip-oemcode').show(); });
$('#node-config-input-estacode').on('blur', function () { $('#tip-oemcode').hide(); });
},
oneditsave: function() {
var myOemType = $('#node-config-input-oemcode').typedInput('type');
if (myOemType == 'custom') {
// shape the value to upper case hex digits
$('#node-config-input-oemcode').typedInput('value', '0x' + $('#node-config-input-oemcode').typedInput('value').toString().substring(2).toUpperCase());
} else {
$('#node-config-input-oemcode').typedInput('value', myOemType);
}
var myEstaType = $('#node-config-input-estacode').typedInput('type');
if (myEstaType == 'custom') {
// shape the value to upper case hex digits
$('#node-config-input-estacode').typedInput('value', '0x' + $('#node-config-input-estacode').typedInput('value').toString().substring(2).toUpperCase());
} else {
$('#node-config-input-estacode').typedInput('value', myEstaType);
}
}
});
</script>