@metz-connect/node-red-ewio2
Version:
Provides nodes to access EWIO2 interfaces like IOs and metering - from Node-RED
238 lines (231 loc) • 13.1 kB
HTML
<script type="text/javascript">
/**
* Stores IO information of connected EWIO2, that the current value and pulse counter is available if IO port in config menu is changed.
* Object is deleted when EWIO2 is changed (changed by selecting another element in dropdown or opening configuration menu).
* @memberof digitalInNode
*/
var digitalIns = {};
/**
* Receives an object with all values of an digital IN pin. If it is the currently selected digital IN pin, the settings in digital IN configuration menu are updated.
* @memberof digitalInNode
*/
RED.comms.subscribe("publish/ewio2/config/di/#", function (topic, msg) {
const recvPrevIoPort = topic.split("/")[5];
const recvNodeId = topic.split("/")[4];
const ioType = topic.split("/")[3];
// get ewio2 id of disabled select
var ewio2Id =$("#node-input-ewio2 option").eq($("#node-input-ewio2").prop("selectedIndex")).val();
// message was received for the currently selected EWIO2
if(ewio2Id == recvNodeId) {
// only add options for the choosen type
if(msg.ioType == ioType) {
// the msg must contain at least 7 elemtens (7 for e.g. setValue response; 8 for livedata (contains also moduleName))
if(Object.keys(msg).length >= 7) {
const dropdownValue = JSON.stringify({"nodeId": recvNodeId, "host": msg.host, "addr": msg.address});
if(!optionExists(dropdownValue, "#node-input-ioportDi")) {
const moduleName = ((msg.moduleName) && (msg.moduleName != "")) ? " @ " + msg.moduleName : "";
$("#node-input-ioportDi").append($('<option>', {
value: dropdownValue,
text: msg.name + moduleName
}));
}
// temporarilly store received msgs (only for this EWIO2), to have the current value and pulse counter value and flag
digitalIns[dropdownValue] = msg;
// set value and pulse counter radio button (true / false) of the choosen and received IO port
let selectedIoPort = $('#node-input-ioportDi').val();
log("selected: " + selectedIoPort + "; recvPrevIoPort: " + recvPrevIoPort);
if(recvPrevIoPort != "undefined") {
const recvPrevIoPortObj = JSON.parse(recvPrevIoPort);
const configNode = RED.nodes.node(ewio2Id);
if (configNode && recvPrevIoPortObj.nodeId === ewio2Id && recvPrevIoPortObj.host == configNode.host) {
selectedIoPort = recvPrevIoPort;
}
}
// set "last" value as selected value in dropdown
$('#node-input-ioportDi').val(selectedIoPort);
// trigger ioport change, to set correct prevIoPort
$('#node-input-ioportDi').trigger("change");
// enable all html elements on valid digital IN values
enableHtmlElements(true, "ioportDi");
// enable digital in specific html elements
enableDiSpecificElements(true);
// enable topic html element
enableTopicElement(true);
}
}
}
});
/**
* Frontend part of digital IN node.
* @memberof digitalInNode
*/
RED.nodes.registerType('EWIO2 - Digital IN', {
category: 'METZ CONNECT',
color: '#4682B4',
defaults: {
ewio2: { value: "", type: "EWIO2" },
name: { value: "" },
ioportDi: { value: "", required: true },
value: { value: "" },
valueText: { value: "" },
pulseCntr: { value: "" },
inputSignal: { value: "" },
risingEdge: { value: "" },
fallingEdge: { value: "" },
outputTopic: { value: "" }
},
// set pulse counter value input
inputs:1,
outputs:1,
icon: "ewio2-digital-input.svg",
label: function() {
return this.name||"EWIO2 - Digital IN";
},
oneditprepare: function() {
let prevIoPort = this.ioportDi;
const nodeId = this.id;
const node = this;
let prevEwio2Data = getConfigNodeDataStructure(this.ewio2, nodeId);
// save the current selected EWIO2, when configuration menu item "ewio2" gets focus. Forward to Node-RED runtime, to be able to publish value again to Node-RED editor.
$("#node-input-ewio2").focus(function () {
prevEwio2Data = getConfigNodeDataStructure(this.value, nodeId);
})
// whenever EWIO2 configuration is changed, async function is called (to "await" for connection)
$("#node-input-ewio2").change(async function () {
log("onchange ewio2: prev: " + prevEwio2Data.data.configNodeId + "; current: " + this.value);
// clear IO-Port dropdown and locally stored data
$("#node-input-ioportDi option").remove();
digitalIns = {};
// clear value
$("#node-input-value").prop("checked", false);
$("#node-input-valueText").val("0");
// clear pulse counter
$("#node-input-pulseCntr").prop("checked", false);
// clear and hide error msg
$('#label-error-status').text("");
$('#section-error-status').hide();
// disable IO port for every selected EWIO2 configuration node
enableIoPortElement("ioportDi", false);
// disable digital in specific html elements
enableDiSpecificElements(false);
// disable topic html element
enableTopicElement(false);
let configNodeId = this.value;
if (!configNodeId || configNodeId == "_ADD_") {
return;
}
// disable all html elements only when a valid EWIO2 configuration node is available
enableHtmlElements(false, "ioportDi");
try {
// one EWIO2 is selected in configuration menu and customer changes to another EWIO2 > close websocket connection of "unselected" EWIO2
if (prevEwio2Data.data.configNodeId != "" && prevEwio2Data.data.configNodeId != "_ADD_") {
const selectedEwio2Data = getConfigNodeDataStructure(this.value, nodeId);
if (JSON.stringify(prevEwio2Data.data) !== JSON.stringify(selectedEwio2Data.data)) {
log(prevEwio2Data.data.configNodeId + " deselected -> close websocket connection");
await closeDeleteWebsocket(prevEwio2Data.data, nodeId);
log("close websocket done");
}
}
// reset prevIoPort, if another EWIO2 is choosen
log(prevIoPort + " typeof: " + typeof prevIoPort);
if (prevIoPort) {
log("prevIoPort-nodeId: " + JSON.parse(prevIoPort).nodeId + "; current EWIO2 id: " + this.value);
if (JSON.parse(prevIoPort).nodeId != this.value) {
prevIoPort = "";
log("reset prevIoPort to ''");
}
}
log("prevIoPort to send: " + prevIoPort);
await getEwio2ConfigData(getConfigNodeDataStructure(configNodeId, nodeId), "di", prevIoPort, nodeId, undefined);
prevEwio2Data = getConfigNodeDataStructure(this.value, nodeId);
}
catch (error) {
log("digital in onchange EWIO2 error");
log(error);
}
});
$("#node-input-ioportDi").change(async function () {
prevIoPort = this.value;
log("onchange ioport: " + prevIoPort);
// only save value, if a value is choosen. Nothing choosen not possible, due to dropdown
if(this.value != "") {
// set value and manual mode radio button (true / false) of the newly choosen IO port
const receivedValue = digitalIns[this.value].value;
$("#node-input-value").prop("checked", (receivedValue === "1") ? true : false );
const receivedPulseCntr = digitalIns[this.value].pulseCntrChecked;
$("#node-input-pulseCntr").prop("checked", (receivedPulseCntr === "1") ? true : false );
toggleDiPulseCntrStatusValue(digitalIns[this.value].pulseCntrValue, digitalIns[this.value].pulseCntrChecked, node);
}
});
},
oneditsave: async function() {
log("digital IN: oneditsave");
let configNodeId = $("#node-input-ewio2").val() || this.ewio2;
await prepareCloseWebsocket(configNodeId, this.id);
},
oneditcancel: async function() {
log("digital IN: oneditcancel");
let configNodeId = $("#node-input-ewio2").val() || this.ewio2;
await prepareCloseWebsocket(configNodeId, this.id);
},
oneditdelete: async function() {
log("digital IN: oneditdelete; node-ID: " + this.id);
let configNodeId = $("#node-input-ewio2").val() || this.ewio2;
await prepareCloseWebsocket(configNodeId, this.id);
}
});
</script>
<script type="text/html" data-template-name="EWIO2 - Digital IN">
<div id="section-error-status" class="form-row" hidden>
<label id="label-error-status" style="color:red; width:inherit"><i class="fa fa-warning"></i> Error</label>
</div>
<div class="form-row">
<label for="node-input-ewio2"><i class="fa fa-microchip"></i> EWIO2</label>
<input type="text" id="node-input-ewio2">
</div>
<div class="form-row">
<label for="node-input-ioportDi"><i class="fa fa-wrench"></i> <span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.port"></label>
<select id="node-input-ioportDi" style="width:70%"></select>
</div>
<div id="section-value" class="form-row">
<label for="node-input-value"><i class="fa fa-bullseye"></i> <span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.status"></label>
<input type="radio" id="node-input-value" disabled style="display: inline-block; width: auto; vertical-align: top;">
</div>
<div id="section-valueText" class="form-row" hidden>
<label for="node-input-valueText"><i class="fa fa-bullseye"></i> <span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.value"></label>
<input type="text" id="node-input-valueText" disabled>
</div>
<div class="form-row">
<label for="node-input-pulseCntr"><i class="fa fa-arrow-circle-o-up"></i> <span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.pulseCntr"></label>
<input type="radio" id="node-input-pulseCntr" disabled style="display: inline-block; width: auto; vertical-align: top;">
</div>
<hr>
<div class="form-row">
<h4><span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.trigger"></h4>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-inputSignal" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-inputSignal" style="width: auto" data-i18n="@metz-connect/node-red-ewio2/ewio2:label.inputSignal"></label>
</div>
<div class="form-row">
<input type="checkbox" id="node-input-risingEdge" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-risingEdge" style="width: auto" id="lbl-risingEdge" data-i18n="@metz-connect/node-red-ewio2/ewio2:label.risingEdge"></label>
</div>
<div id="section-fallingEdge" class="form-row">
<input type="checkbox" id="node-input-fallingEdge" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-fallingEdge" style="width: auto" data-i18n="@metz-connect/node-red-ewio2/ewio2:label.fallingEdge"></label>
</div>
<hr>
<div class="form-row">
<h4><span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.nodeOutput"></h4>
</div>
<div class="form-row">
<label for="node-input-outputTopic"><i class="fa fa-map-signs"></i> Topic</label>
<input type="text" id="node-input-outputTopic">
</div>
<hr>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="@metz-connect/node-red-ewio2/ewio2:label.name"></label>
<input type="text" id="node-input-name"/>
</div>
</script>