2025-05-14 10:31:50 +02:00
2025-06-20 17:14:22 +02:00
< script src = "/measurement/menu.js" > < / script >
2025-06-12 17:05:28 +02:00
< script >
2025-05-14 10:31:50 +02:00
RED.nodes.registerType("measurement", {
category: "digital twin",
color: "#e4a363",
defaults: {
// Define default properties
name: { value: "", required: true },
enableLog: { value: false },
logLevel: { value: "error" },
// Define specific properties
scaling: { value: false },
i_min: { value: 0, required: true },
i_max: { value: 0, required: true },
i_offset: { value: 0 },
o_min: { value: 0, required: true },
o_max: { value: 1, required: true },
simulator: { value: false },
smooth_method: { value: "" },
count: { value: "10", required: true },
//define asset properties
supplier: { value: "" },
2025-06-20 17:14:22 +02:00
category: { value: "" },
assetType: { value: "" },
2025-05-14 10:31:50 +02:00
model: { value: "" },
unit: { value: "" },
},
inputs: 1,
2025-06-20 17:14:22 +02:00
outputs: 3,
2025-05-14 10:31:50 +02:00
inputLabels: ["Measurement Input"],
2025-06-20 17:14:22 +02:00
outputLabels: ["process", "dbase", "parent"],
2025-05-14 10:31:50 +02:00
icon: "font-awesome/fa-tachometer",
label: function () {
return this.name || "Measurement";
},
2025-06-20 17:14:22 +02:00
2025-05-14 10:31:50 +02:00
oneditprepare: function() {
2025-06-20 17:14:22 +02:00
const waitForMenuData = () => {
if (window.EVOLV?.nodes?.measurement?.initEditor) {
window.EVOLV.nodes.measurement.initEditor(this);
} else {
setTimeout(waitForMenuData, 50);
}
};
waitForMenuData();
},
2025-05-14 10:31:50 +02:00
oneditsave: function () {
const node = this;
console.log(`------------ Saving changes to node ------------`);
console.log(`${node.uuid}`);
// Save basic properties
2025-06-20 17:14:22 +02:00
["name", "supplier", "category", "assetType", "model", "unit", "smooth_method"].forEach(
2025-05-14 10:31:50 +02:00
(field) => (node[field] = document.getElementById(`node-input-${field}`).value || "")
);
// Save numeric and boolean properties
["scaling", "enableLog", "simulator"].forEach(
(field) => (node[field] = document.getElementById(`node-input-${field}`).checked)
);
["i_min", "i_max", "i_offset", "o_min", "o_max", "count"].forEach(
(field) => (node[field] = parseFloat(document.getElementById(`node-input-${field}`).value) || 0)
);
node.logLevel = document.getElementById("node-input-logLevel").value || "info";
// Validation checks
if (node.scaling & & (isNaN(node.i_min) || isNaN(node.i_max))) {
RED.notify("Scaling enabled, but input range is incomplete!", "error");
}
if (!node.unit) {
RED.notify("Unit selection is required.", "error");
}
2025-06-20 17:14:22 +02:00
// Validation checks - FIXED
if (node.assetType & & !node.unit) {
RED.notify("Unit must be set when specifying a type.", "error");
2025-05-14 10:31:50 +02:00
}
console.log("stored node modelData", node.modelMetadata);
console.log("------------ Changes saved to measurement node preparing to save to API ------------");
},
});
< / script >
<!-- Main UI -->
< script type = "text/html" data-template-name = "measurement" >
<!-- Node Name -->
< 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="Measurement Name"
style="width:70%;"
/>
< / div >
<!-- Scaling Checkbox -->
< div class = "form-row" >
< label for = "node-input-scaling"
>< i class = "fa fa-compress" > < / i > Scaling< /label
>
< input
type="checkbox"
id="node-input-scaling"
style="width:20px; vertical-align:baseline;"
/>
< span > Enable input scaling?< / span >
< / div >
<!-- Source Min/Max (only if scaling is true) -->
< div class = "form-row" id = "row-input-i_min" >
< label for = "node-input-i_min"
>< i class = "fa fa-arrow-down" > < / i > Source Min< / label >
< input type = "number" id = "node-input-i_min" placeholder = "0" / >
< / div >
< div class = "form-row" id = "row-input-i_max" >
< label for = "node-input-i_max"
>< i class = "fa fa-arrow-up" > < / i > Source Max< / label >
< input type = "number" id = "node-input-i_max" placeholder = "3000" / >
< / div >
<!-- Offset -->
< div class = "form-row" >
< label for = "node-input-i_offset"
>< i class = "fa fa-adjust" > < / i > Input Offset< / label >
< input type = "number" id = "node-input-i_offset" placeholder = "0" / >
< / div >
<!-- Output / Process Min/Max -->
< div class = "form-row" >
< label for = "node-input-o_min" > < i class = "fa fa-tag" > < / i > Process Min< / label >
< input type = "number" id = "node-input-o_min" placeholder = "0" / >
< / div >
< div class = "form-row" >
< label for = "node-input-o_max" > < i class = "fa fa-tag" > < / i > Process Max< / label >
< input type = "number" id = "node-input-o_max" placeholder = "1" / >
< / div >
<!-- Simulator Checkbox -->
< div class = "form-row" >
< label for = "node-input-simulator"
>< i class = "fa fa-cog" > < / i > Simulator< / label >
< input
type="checkbox"
id="node-input-simulator"
style="width:20px; vertical-align:baseline;"
/>
< span > Activate internal simulation?< / span >
< / div >
<!-- Smoothing Method -->
< div class = "form-row" >
< label for = "node-input-smooth_method"
>< i class = "fa fa-line-chart" > < / i > Smoothing< / label >
< select id = "node-input-smooth_method" style = "width:60%;" >
< / select >
< / div >
<!-- Smoothing Window -->
< div class = "form-row" >
< label for = "node-input-count" > Window< / label >
< input
type="number"
id="node-input-count"
placeholder="10"
style="width:60px;"
/>
< div class = "form-tips" > Number of samples for smoothing< / div >
< / div >
2025-06-20 17:14:22 +02:00
<!-- Optional Extended Fields: supplier, cat, type, model, unit -->
< hr / >
2025-05-14 10:31:50 +02:00
< div class = "form-row" >
2025-06-20 17:14:22 +02:00
< label for = "node-input-supplier" > < i class = "fa fa-industry" > < / i > Supplier< / label >
< select id = "node-input-supplier" style = "width:70%;" > < / select >
2025-05-14 10:31:50 +02:00
< / div >
< div class = "form-row" >
2025-06-20 17:14:22 +02:00
< label for = "node-input-category" > < i class = "fa fa-sitemap" > < / i > Category< / label >
< select id = "node-input-category" style = "width:70%;" > < / select >
< / div >
< div class = "form-row" >
< label for = "node-input-assetType" > < i class = "fa fa-puzzle-piece" > < / i > Type< / label >
< select id = "node-input-assetType" style = "width:70%;" > < / select >
2025-05-14 10:31:50 +02:00
< / div >
< div class = "form-row" >
< label for = "node-input-model" > < i class = "fa fa-wrench" > < / i > Model< / label >
2025-06-20 17:14:22 +02:00
< select id = "node-input-model" style = "width:70%;" > < / select >
2025-05-14 10:31:50 +02:00
< / div >
< div class = "form-row" >
< label for = "node-input-unit" > < i class = "fa fa-balance-scale" > < / i > Unit< / label >
2025-06-20 17:14:22 +02:00
< select id = "node-input-unit" style = "width:70%;" > < / select >
2025-05-14 10:31:50 +02:00
< / div >
< hr / >
<!-- loglevel checkbox -->
< div class = "form-row" >
< label for = "node-input-enableLog"
>< i class = "fa fa-cog" > < / i > Enable Log< / label >
< input
type="checkbox"
id="node-input-enableLog"
style="width:20px; vertical-align:baseline;"
/>
< span > Enable logging< / span >
< / div >
< div class = "form-row" id = "row-logLevel" >
< label for = "node-input-logLevel" > < i class = "fa fa-cog" > < / i > Log Level< / label >
< select id = "node-input-logLevel" style = "width:60%;" >
< option value = "info" > Info< / option >
< option value = "debug" > Debug< / option >
< option value = "warn" > Warn< / option >
< option value = "error" > Error< / option >
< / select >
< / div >
< / script >
< script type = "text/html" data-help-name = "measurement" >
< p > < b > Measurement Node< / b > : Scales, smooths, and simulates measurement data.< / p >
< p > Use this node to scale, smooth, and simulate measurement data. The node can be configured to scale input data to a specified range, smooth the data using a variety of methods, and simulate data for testing purposes.< / p >
< li > < b > Supplier:< / b > Select a supplier to populate machine options.< / li >
< li > < b > SubType:< / b > Select a subtype if applicable to further categorize the asset.< / li >
< li > < b > Model:< / b > Define the specific model for more granular asset configuration.< / li >
< li > < b > Unit:< / b > Assign a unit to standardize measurements or operations.< / li >
< li > < b > Scaling:< / b > Enable or disable input scaling. When enabled, you must provide the source min and max values.< / li >
< li > < b > Source Min/Max:< / b > Define the minimum and maximum values for the input range when scaling is enabled.< / li >
< li > < b > Input Offset:< / b > Specify an offset value to be added to the input measurement.< / li >
< li > < b > Process Min/Max:< / b > Define the minimum and maximum values for the output range after processing.< / li >
< li > < b > Simulator:< / b > Activate internal simulation for testing purposes.< / li >
< li > < b > Smoothing:< / b > Select a smoothing method to apply to the measurement data.< / li >
< li > < b > Window:< / b > Define the number of samples to use for smoothing.< / li >
< li > < b > Enable Log:< / b > Enable or disable logging for this node.< / li >
< li > < b > Log Level:< / b > Select the log level (Info, Debug, Warn, Error) for logging messages.< / li >
< / script >