node-red-contrib-knx-ultimate
Version:
Control your KNX intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.
794 lines (737 loc) • 62.6 kB
HTML
<!-- <script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/jquery.searchableSelect.js"></script> -->
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/KNXFunctionCodeSnippets.js"></script>
<script type="text/javascript">
RED.nodes.registerType('knxUltimate', {
category: "KNX Ultimate",
color: '#7dd484',
defaults: {
//buttonState: {value: true},
server: { type: "knxUltimate-config", required: true },
topic: { value: "" },
setTopicType: { value: "str" },
outputtopic: { value: "" },
dpt: { value: "" },
initialread: { value: 0 },
notifyreadrequest: { value: false },
notifyresponse: { value: false },
notifywrite: { value: true },
notifyreadrequestalsorespondtobus: { value: false },
notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized: { value: "0" },
name: { value: "" },
outputtype: { value: "write" },
outputRBE: { value: "true" },
inputRBE: { value: "false" },
formatmultiplyvalue: { value: 1 },
formatnegativevalue: { value: "leave" },
formatdecimalsvalue: { value: 999 },
passthrough: { value: "no" },
sendMsgToKNXCode: { value: "" },
receiveMsgFromKNXCode: { value: "" },
listenallga: { value: "" }
},
inputs: 1,
outputs: 1,
icon: "node-knx-icon.svg",
label: function () {
const functionSendMsgToKNXCode = (this.sendMsgToKNXCode !== undefined && this.sendMsgToKNXCode !== '') ? "f(x) " : "";
const functionreceiveMsgFromKNXCode = (this.receiveMsgFromKNXCode !== undefined && this.receiveMsgFromKNXCode !== '') ? " f(x)" : "";
return ((this.outputRBE === "true" || this.outputRBE === true) ? "|rbe| " : "") + functionSendMsgToKNXCode + (this.name || this.topic || "KNX Device") + (this.setTopicType === 'str' || this.setTopicType === undefined ? '' : ' [' + (this.setTopicType === 'listenAllGA' ? 'Universal' : this.setTopicType) + ']') + functionreceiveMsgFromKNXCode + ((this.inputRBE === "true" || this.inputRBE === true) ? " |rbe|" : "")
},
paletteLabel: "KNX DEVICE",
// button: {
// enabled: function() {
// // return whether or not the button is enabled, based on the current
// // configuration of the node
// return !this.changed
// },
// visible: function() {
// // return whether or not the button is visible, based on the current
// // configuration of the node
// return this.hasButton
// },
// //toggle: "buttonState",
// onclick: function() {}
// },
oneditprepare: function () {
// Go to the help panel
try {
RED.sidebar.show("help");
} catch (error) { }
var node = this;
if ($("#node-input-server").val() === "_ADD_") {
// Node-Red 4.0.x has a bug not selecting the default server node
try {
$("#node-input-server").prop("selectedIndex", 0);
} catch (error) {
}
}
var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
$("#tabs").tabs();
// 15/09/2020 Supergiovane, set the help sample based on Datapoint
function knxUltimateDptsGetHelp(_dpt, _forceClose) {
if ($("#node-input-server").val() !== "_ADD_" && $("#node-input-server").val() !== '' && _dpt !== null && _dpt !== '') {
$.getJSON("knxUltimateDptsGetHelp?dpt=" + _dpt + "&serverId=" + $("#node-input-server").val() + "&" + { _: new Date().getTime() }, (data) => {
try {
$("#example-editor").html("");
$("#sampleCodeEditor").html();
node.sampleEditor.destroy();
delete node.sampleEditor;
} catch (error) {
}
try {
if (data.help !== "NO") {
node.sampleEditor = RED.editor.createEditor({
id: 'example-editor',
mode: 'ace/mode/javascript',
value: data.help//this.exampleText
})//.renderer.setShowGutter(false);//A.setReadOnly(true).setShowPrintMargin(false);
if (data.helplink !== "") $("#sampleCodeEditor").html(" <i class=\"fa fa-question-circle\"></i> <a target=\"_blank\" href=\"" + data.helplink + "\"><u>Link example of " + _dpt + "</u></a>");
} else {
// No help avaiable
node.sampleEditor = RED.editor.createEditor({
id: 'example-editor',
mode: 'ace/mode/javascript',
value: "Currently, no sample payload is avaiable, sorry."
})//.renderer.setShowGutter(false);//B.setReadOnly(true).setShowPrintMargin(false);
if (data.helplink !== "") $("#sampleCodeEditor").html(" <i class=\"fa fa-question-circle\"></i> <a target=\"_blank\" href=\"" + data.helplink + "\"><u>Link to wiki</u></a>");
}
} catch (error) {
}
})
}
}
node.sendMsgToKNXCodeEditor = RED.editor.createEditor({
id: 'sendMsgToKNXCode-editor',
mode: 'ace/mode/nrjavascript',
value: node.sendMsgToKNXCode
});
node.receiveMsgFromKNXCodeEditor = RED.editor.createEditor({
id: 'receiveMsgFromKNXCode-editor',
mode: 'ace/mode/nrjavascript',
value: node.receiveMsgFromKNXCode
});
// Snippets
$("#snippetOne").on("click", function (event) {
node.sendMsgToKNXCodeEditor.session.setValue(KNXFunctionSnippetOne);
});
$("#snippetTwo").on("click", function (event) {
node.receiveMsgFromKNXCodeEditor.session.setValue(KNXFunctionSnippetTwo);
});
$("#snippetThree").on("click", function (event) {
node.receiveMsgFromKNXCodeEditor.session.setValue(KNXFunctionSnippetThree);
});
$("#snippetFour").on("click", function (event) {
node.sendMsgToKNXCodeEditor.session.setValue(KNXFunctionSnippetFour);
});
$("#snippetFive").on("click", function (event) {
node.sendMsgToKNXCodeEditor.session.setValue(KNXFunctionSnippetFive);
});
$("#snippetSix").on("click", function (event) {
node.sendMsgToKNXCodeEditor.session.setValue(KNXFunctionSnippetSix);
});
function checkUI() {
// Backward compatibility
if (node.outputRBE === true || $("#node-input-outputRBE").val() === true) {
node.outputRBE = 'true';
$("#node-input-outputRBE").val("true")
}
if (node.outputRBE === undefined || node.outputRBE === false || $("#node-input-outputRBE").val() === false) {
node.outputRBE = 'false';
$("#node-input-outputRBE").val("false")
}
if (node.inputRBE === true || $("#node-input-inputRBE").val() === true) {
node.inputRBE = 'true';
$("#node-input-inputRBE").val("true")
}
if (node.inputRBE === undefined || node.inputRBE === false || $("#node-input-inputRBE").val() === false) {
node.inputRBE = 'false';
$("#node-input-inputRBE").val("false")
}
if (node.passthrough === undefined) {
node.passthrough = 'no';
$("#node-input-passthrough").val("no")
}
if (node.initialread === undefined || node.initialread === false) {
node.initialread = 0;
$("#node-input-initialread").val(0)
}
oNodeServer = RED.nodes.node($("#node-input-server").val());
if (oNodeServer === undefined) {
// Show the DEPLOY FIRST message
$("#divDeployFirst").show();
$("#divMain").hide();
} else {
$("#divDeployFirst").hide();
$("#divMain").show();
try {
if (typeof oNodeServer.csv !== "undefined" && oNodeServer.csv !== "") {
$("#isETSFileLoaded").val("si");
$("#divknxFunctionHelperGAList").show();
} else {
$("#isETSFileLoaded").val("no");
$("#divknxFunctionHelperGAList").hide();
}
} catch (error) {
$("#isETSFileLoaded").val("no");
$("#divknxFunctionHelperGAList").hide();
}
if (oNodeServer.knxSecureSelected) {
$("#divknxsecure").show();
} else {
$("#divknxsecure").hide();
}
if ($("#node-input-server").val() !== "_ADD_" && $("#node-input-server").val() !== '') {
$.getJSON("knxUltimateDpts?serverId=" + $("#node-input-server").val() + "&_=" + new Date().getTime(), (data) => {
$("#node-input-dpt").empty();
data.forEach(dpt => {
$("#node-input-dpt").append($("<option></option>")
.attr("value", dpt.value)
.text(dpt.text))
});
$("#node-input-dpt").val(node.dpt);
// Load help sample
knxUltimateDptsGetHelp(node.dpt, true);
})
}
// Add write and response as default for existing nodes like was default before
if (node.notifywrite === undefined) {
node.notifywrite = true
node.notifyresponse = true
$("#node-input-notifywrite").prop("checked", true)
$("#node-input-notifyresponse").prop("checked", true)
}
// Add Write as default for existing clients output
if (node.outputtype === undefined) {
node.outputtype = "write"
$("#node-input-outputtype").val("write")
}
$("#node-input-notifyreadrequest").on('change', function () {
if ($("#node-input-notifyreadrequest").is(":checked")) {
if ($("#node-input-setTopicType").val() === "listenAllGA") {
} else {
$("#divnotifyreadrequestautoreact").show();
}
} else {
$("#divnotifyreadrequestautoreact").hide();
}
})
// Set the group address type
if (node.setTopicType === undefined) {
node.setTopicType = 'str';
$("#node-input-setTopicType").val('str');
}
// KNX Function helper: search for a GA and devicename
// ----------------------------------------------------------
try {
$("#node-input-knxFunctionHelperGAList").autocomplete('destroy');
$("#node-input-knxFunctionHelperGAList").removeClass(); // Rimuove eventuali classi aggiunte dall'autocompletamento
} catch (error) { }
$("#node-input-knxFunctionHelperGAList").off(); // Rimuovi tutti gli eventi associati
$("#node-input-knxFunctionHelperGAList").val(''); // Pulisce il valore del campo di input, se necessario
$("#node-input-knxFunctionHelperGAList").autocomplete({
minLength: 0,
source: function (request, response) {
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id + "&" + { _: new Date().getTime() }, (data) => {
response($.map(data, function (value, key) {
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
return {
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
value: value.ga + " " + value.devicename // Value
}
} else {
return null;
}
}));
});
}, select: function (event, ui) {
}
}).focus(function () {
$(this).autocomplete('search', $(this).val() + 'exactmatch');
});
// ----------------------------------------------------------
$("#node-input-setTopicType").on('change', function () {
try {
$("#divDatapointSelection").show();
$("#node-input-topic").show();
$("#node-input-topic").autocomplete('destroy');
$("#node-input-topic").off(); // Rimuovi tutti gli eventi associati
$("#node-input-topic").val(''); // Pulisce il valore del campo di input, se necessario
$("#node-input-topic").prop('disabled', false); // Assicura che il campo non sia disabilitato
$("#node-input-topic").removeClass(); // Rimuove eventuali classi aggiunte dall'autocompletamento
} catch (error) {
}
if ($("#node-input-setTopicType").val() === 'str') {
$("#node-input-topic").prop('placeholder', 'Select your GA');
// Autocomplete suggestion with ETS csv File
$("#node-input-topic").autocomplete({
minLength: 0,
source: function (request, response) {
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id + "&" + { _: new Date().getTime() }, (data) => {
response($.map(data, function (value, key) {
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
return {
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
value: value.ga // Value
}
} else {
return null;
}
}));
});
}, select: function (event, ui) {
// Sets Datapoint and device name automatically
var sDevName = ui.item.label.split("#")[1].trim();
try {
sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
} catch (error) {
}
$('#node-input-name').val(sDevName);
var optVal = $("#node-input-dpt option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
// Select the option value
$("#node-input-dpt").val(optVal);
$("#node-input-dpt").trigger("change");
}
}).focus(function () {
$(this).autocomplete('search', $(this).val() + 'exactmatch');
});
$("#divDatapointSelection").show();
$("#divNode-input-initialread").show();
$("#divOutputRBE").show()
$("#divInputRBE").show()
} else if ($("#node-input-setTopicType").val() === 'listenAllGA') {
$("#node-input-topic").hide();
$("#divDatapointSelection").hide()
$("#divOutputRBE").hide()
$("#node-input-outputRBE").val("false")
$("#divInputRBE").hide()
$("#node-input-inputRBE").val("false")
$("#divnotifyreadrequestautoreact").hide();
$("#divTopic").hide()
$("#divNode-input-initialread").hide();
// Call a fake datapoint to load a sample "Universal Node"
knxUltimateDptsGetHelp("0.000", true); // 15/09/2020 Supergiovane, load sample help
} else {
// 15/09/2020 Supergiovane, load the help sample of the current datapoint
knxUltimateDptsGetHelp($("#node-input-dpt").val(), false); // 15/09/2020 Supergiovane, load sample help
$("#divOutputRBE").show()
$("#divInputRBE").show()
$("#divTopic").show()
if ($("#node-input-notifyreadrequest").is(":checked")) {
$("#divnotifyreadrequestautoreact").show();
} else {
$("#divnotifyreadrequestautoreact").hide();
}
$("#divNode-input-initialread").show();
$("#node-input-topic").prop('placeholder', $("#node-input-setTopicType").val());
if ($("#node-input-topic").val() === '') $("#node-input-topic").val('MyVariable');
$("#divDatapointSelection").hide();
}
});
// Hide or show the GA and DPT fields if Notify on all Group Addresses is checked
if (oNodeServer !== undefined && oNodeServer !== null) {
if (oNodeServer.csv !== undefined && oNodeServer.csv !== "") {
// There is a ETS csv file, show the init read option
$("#divNode-input-initialread").show()
} else {
// 25/10/2019 Warn user that the node will node encode/decode datagram, if Listen All GA's if the config node doesn't contain the csv
if ($("#node-input-setTopicType").val() === 'listenAllGA') {
// There isn't a ETS csv file, hide and deselect the init read option
$("#divNode-input-initialread").hide();
$("#node-input-initialread").val(0);
} else {
$("#divNode-input-initialread").show()
}
}
} else {
$("#node-input-setTopicType").val('str')
$("#divTopic").show()
$("#divDatapointSelection").show()
$("#divOutputRBE").show()
$("#divInputRBE").show()
$("#divNode-input-initialread").show()
}
// *****************************
setTimeout(() => {
if ($("#node-input-setTopicType").val() === 'listenAllGA') {
// Call a fake datapoint to load a sample "Universal Node"
knxUltimateDptsGetHelp("0.000", true); // 15/09/2020 Supergiovane, load sample help
}
}, 300);
}
}
// 02/04/2020 Alert user about data type
// ###########################
$("#node-input-dpt").on("change", function (event) {
// Load help sample
knxUltimateDptsGetHelp(event.target.value, false);
});
// ###########################
// If KNX Function is populated, set focus on the KNX Function tab.
if (this.sendMsgToKNXCodeEditor.getValue() !== '' || this.receiveMsgFromKNXCodeEditor.getValue()) {
$("#tabs").tabs(
{ active: 1 }
);
}
// Backwart compatibility listenAllGA
if (node.listenallga === true) {
$("#node-input-setTopicType").val('listenAllGA');
}
// 19/02/2020 Used to alert the user if the CSV file has not been loaded and to get the server sooner als deploy
// ###########################
$("#node-input-server").change(function () {
checkUI();
});
// ###########################
},
oneditsave: function () {
// Return to the info tab
try {
RED.sidebar.show("info");
} catch (error) { }
var node = this;
this.sendMsgToKNXCode = this.sendMsgToKNXCodeEditor.getValue();
this.receiveMsgFromKNXCode = this.receiveMsgFromKNXCodeEditor.getValue();
if ($("#node-input-setTopicType").val() === "listenAllGA") {
this.listenallga = true;
} else {
this.listenallga = false;
}
//this.propertyType = $("#node-input-property").typedInput('type');
// 19/02/2020 Warn user that the node will node encode/decode datagram, if Listen All GA's if the config node doesn't contain the csv
if ($("#isETSFileLoaded").val() === "no") {
// Notify the user
if ($("#node-input-setTopicType").val() === 'listenAllGA') {
var checkResult = node._("knxUltimate.advanced.notify-NoETSFile");
var myNotification = RED.notify(checkResult,
{
modal: true,
fixed: true,
type: 'error',
buttons: [
{
text: "OK",
click: function (e) {
myNotification.close();
}
}]
})
}
// $("#node-input-listenallga").prop("checked", false)
// $("#divOutputRBE").show()
// $("#divInputRBE").show()
}
// 15/09/2020 Supergiovane, Detele the sample help editor
try {
node.sampleEditor.destroy();
delete node.sampleEditor;
node.sendMsgToKNXCodeEditor.destroy();
delete node.sendMsgToKNXCodeEditor;
node.receiveMsgFromKNXCodeEditor.destroy();
delete node.receiveMsgFromKNXCodeEditor;
//RED.editor.destroy(); // 23/01/2024 added
} catch (error) { }
},
oneditcancel: function () {
// Return to the info tab
try {
RED.sidebar.show("info");
} catch (error) { }
// 15/09/2020 Supergiovane, Detele the sample help editor
try {
node.sampleEditor.destroy();
delete node.sampleEditor;
node.sendMsgToKNXCodeEditor.destroy();
delete node.sendMsgToKNXCodeEditor;
node.receiveMsgFromKNXCodeEditor.destroy();
delete node.receiveMsgFromKNXCodeEditor;
RED.editor.destroy(); // 23/01/2024 added
} catch (error) { }
}
})
// RED.events.on("nodes:change", function (node) {
// checkUI();
// });
</script>
<script type="text/html" data-template-name="knxUltimate">
<!-- Setted by oneditprepare and used in oneditsave to warn user if no CSV file has been loaded -->
<input id="isETSFileLoaded" name="isETSFileLoaded" type="hidden" value="false" />
<div class="form-row">
<b>KNX Device node</b>
<br />
<br />
<label for="node-input-server">
<i class="fa fa-circle-o"></i> Gateway
</label>
<input type="text" id="node-input-server" />
</div>
<div id="divMain">
<div class="form-row">
<label for="node-input-topic">
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAB7CAAAewgFu0HU+AAAF6WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMSAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDMtMjNUMTY6MjE6MDkrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTAzLTIzVDE2OjI4OjI3KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTAzLTIzVDE2OjI4OjI3KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9InNSR0IgSUVDNjE5NjYtMi4xIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjc4M2I5OWIxLTkwMjYtNGQ2OC05N2FmLTRkM2E2ZWY4Zjk2OCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4N2E3YTg0NS0xMDljLTRkMTMtOGEzOS04OWVhOTMyMDQ0ZWMiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo4N2E3YTg0NS0xMDljLTRkMTMtOGEzOS04OWVhOTMyMDQ0ZWMiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjg3YTdhODQ1LTEwOWMtNGQxMy04YTM5LTg5ZWE5MzIwNDRlYyIgc3RFdnQ6d2hlbj0iMjAyMC0wMy0yM1QxNjoyMTowOSswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjEgKE1hY2ludG9zaCkiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjc4M2I5OWIxLTkwMjYtNGQ2OC05N2FmLTRkM2E2ZWY4Zjk2OCIgc3RFdnQ6d2hlbj0iMjAyMC0wMy0yM1QxNjoyODoyNyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjEgKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+DGyPFQAAAE9JREFUKJG1UEEOACAIgub/v2yHalnJVoe4uIEKSgccJ9jroVmjA0+ujZtWku3DgZmgBiT4egN9CmmEAAfA/5HUW0OQu7dKmOCzmM3k9YYKZv8ZEZ/YgNsAAAAASUVORK5CYII="></img>
Group Addr.</label>
<select id="node-input-setTopicType" style="width:120px">
<option value="str">3-Levels</option>
<option value="listenAllGA">Universal mode (listen to all Group Addresses)</option>
<option value="flow">Flow</option>
<option value="global">Gobal</option>
<option value="env">$Env variable</option>
</select>
<input type="text" id="node-input-topic" placeholder="Start typing to search" style="width:180px" />
</div>
<div class="form-row" id="divDatapointSelection">
<label for="node-input-dpt">
<img
src="data:image/png;base64,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"></img>
Datapoint
</label>
<select id="node-input-dpt"></select>
<span id="sampleCodeEditor" style="color:red;" />
</div>
<!-- <div class="form-row">
<input type="checkbox" id="node-input-listenallga"
style="display:inline-block; width:auto; vertical-align:top;" />
<label style="width:auto" for="node-input-listenallga">
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAB7CAAAewgFu0HU+AAAFGmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMSAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDMtMjNUMTY6MjM6MjMrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTAzLTIzVDE2OjI1OjM0KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTAzLTIzVDE2OjI1OjM0KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9InNSR0IgSUVDNjE5NjYtMi4xIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOmJmNGM3NWVjLTIwNGYtNGY1YS05YTMxLTQ5NTU5YWJmZDE4NSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpiZjRjNzVlYy0yMDRmLTRmNWEtOWEzMS00OTU1OWFiZmQxODUiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpiZjRjNzVlYy0yMDRmLTRmNWEtOWEzMS00OTU1OWFiZmQxODUiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmJmNGM3NWVjLTIwNGYtNGY1YS05YTMxLTQ5NTU5YWJmZDE4NSIgc3RFdnQ6d2hlbj0iMjAyMC0wMy0yM1QxNjoyMzoyMyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjEgKE1hY2ludG9zaCkiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+nhtLUgAAAE9JREFUKJG1UMsOACAIgub//7IdqvVQtjrExU1EEQLuiGCvgTNgl5D74MmVZPu4wIxQAgm+/sDec2VhgQPgf0sq1unjMlYJE/3MZrvy+kMFZQkZEWfC7ikAAAAASUVORK5CYII="></img>
<span data-i18n="knxUltimate.properties.node-input-listenallga"></span>
</label>
</div> -->
<div id="tabs">
<ul>
<li><a href="#tabs-1"><i class="fa fa-braille"></i> Advanced options</a></li>
<li><a href="#tabs-2"><i class="fa fa-code"></i> KNX Function</a></li>
<li><a href="#tabs-3"><i class="fa fa-medkit"></i> Payload Sample</a></li>
</ul>
<div id="tabs-1">
<div class="form-row" style="padding:10px">
<div class="form-row">
<dt>
<i class="fa fa-desktop"></i> General properties
</dt>
</div>
<div class="form-row">
<label style="width:180px" for="node-input-name">
<i class="fa fa-tag"></i>
<span data-i18n="knxUltimate.properties.node-input-name"></span>
</label>
<input style="width:220px;" type="text" id="node-input-name"
data-i18n="[placeholder]knxUltimate.properties.node-input-name" />
</div>
<div class="form-row" id="divTopic">
<label style="width:180px" for="node-input-outputtopic">
<i class="fa fa-tasks"></i>
<span data-i18n="knxUltimate.properties.node-input-outputtopic"></span>
</label>
<input style="width:220px;" type="text" id="node-input-outputtopic"
data-i18n="[placeholder]knxUltimate.placeholder.leaveempty" />
</div>
<div class="form-row">
<label style="width:180px" for="node-input-passthrough">
<i class="fa fa-long-arrow-right"></i> Passthrough
</label>
<select id="node-input-passthrough">
<option value="no">No</option>
<option value="yes">Yes, pass the input msg to the output msg</option>
<option value="yesownprop">Yes, but put the input msg into msg.inputmessage property of the
output msg
</option>
</select>
</div>
<hr>
<div class="form-row">
<dt>
<i class="fa fa-arrow-right"></i>| From node's INPUT PIN to KNX BUS
</dt>
</div>
<div class="form-row">
<label style="width:180px" for="node-input-outputtype">
<i class="fa fa-paper-plane-o"></i> Telegram type
</label>
<select id="node-input-outputtype">
<option value="write" data-i18n="knxUltimate.selectlists.Output_write"></option>
<option value="response" data-i18n="knxUltimate.selectlists.Output_response"></option>
<option value="read" data-i18n="knxUltimate.selectlists.Output_read"></option>
<option value="update" data-i18n="knxUltimate.selectlists.Output_update"></option>
</select>
</div>
<div class="form-row" id="divOutputRBE">
<label style="width:180px" for="node-input-outputRBE">
<i class="fa fa-filter"></i> RBE filter
</label>
<select id="node-input-outputRBE">
<option value="true">Enable (send the payload to KNX only if changed)</option>
<option value="false">Disable</option>
</select>
</div>
<hr>
<div class="form-row">
<dt>
|<i class="fa fa-arrow-right"></i> From KNX BUS to node's ouput PIN
</dt>
</div>
<div class="form-row" id="divNode-input-initialread">
<label style="width:180px" for="node-input-initialread">
<i class="fa fa-question-circle-o"></i> Read status on start
</label>
<select id="node-input-initialread">
<option value=0 data-i18n="knxUltimate.properties.node-input-initialread0"></option>
<option value=1 data-i18n="knxUltimate.properties.node-input-initialread1"></option>
<option value=2 data-i18n="knxUltimate.properties.node-input-initialread2"></option>
<option value=3 data-i18n="knxUltimate.properties.node-input-initialread3"></option>
</select>
</div>
<div class="form-row" id="divInputRBE">
<label style="width:180px" for="node-input-inputRBE">
<i class="fa fa-filter"></i> RBE filter
</label>
<select id="node-input-inputRBE">
<option value="true">Enable (react only if payload changes)</option>
<option value="false">Disable</option>
</select>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-notifywrite"
style="display:inline-block; width:auto; vertical-align:top;" />
<label style="width:85%" for="node-input-notifywrite">
<i class="fa fa-sign-in"></i> React to write telegrams
</label>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-notifyresponse"
style="display:inline-block; width:auto; vertical-align:top;" />
<label style="width:85%" for="node-input-notifyresponse">
<i class="fa fa-sign-in"></i> React to response telegrams
</label>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-notifyreadrequest"
style="display:inline-block; width:auto; vertical-align:top;" />
<label style="width:85%" for="node-input-notifyreadrequest">
<i class="fa fa-sign-in"></i> React to read telegrams
</label>
</div>
<div id="divnotifyreadrequestautoreact">
<dd>
<div class="form-row">
<input type="checkbox" id="node-input-notifyreadrequestalsorespondtobus"
style="display:inline-block; width:auto; vertical-align:top;" />
<label style="width:85%" for="node-input-notifyreadrequestalsorespondtobus">
<span
data-i18n="knxUltimate.properties.node-input-notifyreadrequestalsorespondtobus"></span>
</label>
</div>
<div class="form-row">
<label style="width:auto">
<span
data-i18n="knxUltimate.properties.node-input-notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized"></span>
</label>
<input style="width:auto" type="text"
id="node-input-notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized"
data-i18n="[placeholder]knxUltimate.placeholder.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized" />
</div>
</dd>
</div>
<div class="form-row">
<dt>
<i class="fa fa-sort-numeric-asc"></i> Format numeric values coming from the KNX BUS
</dt>
</div>
<div class="form-row">
<label style="width:180px" for="node-input-formatmultiplyvalue">
<i class="fa fa-calculator"></i>
<span data-i18n="knxUltimate.properties.node-input-formatmultiplyvalue"></span>
</label>
<select id="node-input-formatmultiplyvalue">
<option value=1 data-i18n="knxUltimate.selectlists.Multiply_leave"></option>
<option value=0.001 data-i18n="knxUltimate.selectlists.Multiply_divide1000"></option>
<option value=0.01 data-i18n="knxUltimate.selectlists.Multiply_divide100"></option>
<option value=0.1 data-i18n="knxUltimate.selectlists.Multiply_divide10"></option>
<option value=10 data-i18n="knxUltimate.selectlists.Multiply_multiply10"></option>
<option value=100 data-i18n="knxUltimate.selectlists.Multiply_multiply100"></option>
<option value=1000 data-i18n="knxUltimate.selectlists.Multiply_multiply1000"></option>
</select>
</div>
<div class="form-row">
<label style="width:180px" for="node-input-formatdecimalsvalue">
<i class="fa fa-expand"></i>
<span data-i18n="knxUltimate.properties.node-input-formatdecimalsvalue"></span>
</label>
<select id="node-input-formatdecimalsvalue">
<option value=999 data-i18n="knxUltimate.selectlists.Decimals_leave"></option>
<option value=0 data-i18n="knxUltimate.selectlists.Decimals_roundint"></option>
<option value=1 data-i18n="knxUltimate.selectlists.Decimals_round1"></option>
<option value=2 data-i18n="knxUltimate.selectlists.Decimals_round2"></option>
<option value=3 data-i18n="knxUltimate.selectlists.Decimals_round3"></option>
<option value=4 data-i18n="knxUltimate.selectlists.Decimals_round4"></option>
</select>
</div>
<div class="form-row">
<label style="width:180px" for="node-input-formatnegativevalue">
<i class="fa fa-minus-circle"></i>
<span data-i18n="knxUltimate.properties.node-input-formatnegativevalue"></span>
</label>
<select id="node-input-formatnegativevalue">
<option value="leave" data-i18n="knxUltimate.selectlists.Negatives_leave"></option>
<option value="zero" data-i18n="knxUltimate.selectlists.Negatives_zero"></option>
<option value="abs" data-i18n="knxUltimate.selectlists.Negatives_abs"></option>
</select>
</div>
</div>
</div>
<div id="tabs-2">
<div class="form-row" style="padding:10px">
<div class="form-row" id="divknxFunctionHelperGAList">
<label for="node-input-knxFunctionHelperGAList">
<i class="fa fa-search"></i> Search GA
</label>
<input type="text" id="node-input-knxFunctionHelperGAList" placeholder="Start typing to search" />
</div>
<div class="form-row">
<dt>
<i class="fa fa-arrow-right"></i>| From node's INPUT PIN to KNX BUS
</dt>
</div>
<div style="height:200px;min-height:150px;padding:0px;">
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor"
id="sendMsgToKNXCode-editor"></div>
</div>
<i class="fa fa-code"></i> Select a snippet to be inserted<br />
<button type="button" id="snippetOne" class="red-ui-button">Status GA check</button>
<button type="button" id="snippetFour" class="red-ui-button">Toggle value</button>
<button type="button" id="snippetFive" class="red-ui-button">Send false after 5 secs</button>
<button type="button" id="snippetSix" class="red-ui-button">Send 20% to another GA</button>
<hr>
<div class="form-row">
<dt>
|<i class="fa fa-arrow-right"></i> From KNX BUS to node's OUTPUT PIN
</dt>
</div>
<div style="height:200px;min-height:150px;padding:0px;">
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor"
id="receiveMsgFromKNXCode-editor"></div>
</div>
<i class="fa fa-code"></i> Select a snippet to be inserted<br />
<button type="button" id="snippetTwo" class="red-ui-button">Show msg constructor</button>
<button type="button" id="snippetThree" class="red-ui-button">Add property to msg</button>
</div>
</div>
<div id="tabs-3">
<div style="height:200px;min-height:150px;padding:0px;">
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor" id="example-editor"></div>
</div>
</div>
</div>
</div>
<div id="divDeployFirst">
<div class="form-tips" style="margin-top:11px">
<span data-i18n="knxUltimate.deployfirst"></span>
</div>
</div>
<br /><br />
</script>
<script type="text/markdown" data-help-name="knxUltimate">
<p>This node lets you