node-red-contrib-bacnet
Version:
The BACnet toolbox package for Node-RED from the P4NR B2B Community.
210 lines (195 loc) • 9.74 kB
HTML
<!--
The MIT License
Copyright (c) 2017,2018,2019,2020,2021,2022,2023,2024 Klaus Landsdorf (http://plus4nodered.com/)
All rights reserved.
node-red-contrib-bacnet
--> <script type='text/javascript'> RED.nodes.registerType('BACnet-Write', {
category: 'BACnet',
color: "#16BAC4",
defaults: {
name: {value: ''},
objectType: {value: '', required:true, validate: RED.validators.number()},
instance: {type: "BACnet-Instance", required:true},
valueTag: {value: '', required:true, validate: RED.validators.number()},
valueValue: {value: ''},
propertyId: {value: '', required:true, validate: RED.validators.number()},
priority: {value: ''},
device: {type: "BACnet-Device", required:true},
server: {type: "BACnet-Client", required:true},
multipleWrite: {value: false}
},
inputs: 1,
outputs: 1,
align: "right",
icon: "bacnet-icon.png",
label: function () {
return this.name || "BACnet Write";
},
labelStyle: function () {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function () {
let node = this
let multipleWriteCheckbox = $("#node-input-multipleWrite")
let propertyRow = $("#priority-row")
multipleWriteCheckbox.change(function () {
if ($(this).is(":checked")) {
propertyRow.hide();
} else {
propertyRow.show();
}
});
let objectTypeLookupField = $("#node-lookup-objectType")
let objectTypeField = $("#node-input-objectType")
objectTypeLookupField.click(function () {
objectTypeLookupField.addClass('disabled')
$.getJSON('/bacnet/ObjectTypes', function (data) {
objectTypeLookupField.removeClass('disabled')
node.lookupItems = []
$.each(data, function (i, entry) {
node.lookupItems.push({value: entry.typeValue, label: entry.label})
})
objectTypeField.autocomplete({
source: node.lookupItems,
minLength: 0,
focus: function (event, ui) {
objectTypeField.val(parseInt(ui.item.value) || 0);
return false;
},
select: function (event, ui) {
objectTypeField.val(parseInt(ui.item.value) || 0)
return false;
},
close: function (event, ui) {
objectTypeField.autocomplete("destroy")
}
}).autocomplete("search", "")
})
})
let datatypeLookupField = $("#node-lookup-propertyId")
let datatypeField = $("#node-input-propertyId")
datatypeLookupField.click(function () {
datatypeLookupField.addClass('disabled')
$.getJSON('/bacnet/PropertyIds', function (data) {
datatypeLookupField.removeClass('disabled')
node.lookupItems = []
$.each(data, function (i, entry) {
node.lookupItems.push({value: entry.typeValue, label: entry.label})
})
datatypeField.autocomplete({
source: node.lookupItems,
minLength: 0,
focus: function (event, ui) {
datatypeField.val(parseInt(ui.item.value) || 0);
return false;
},
select: function (event, ui) {
datatypeField.val(parseInt(ui.item.value) || 0)
return false;
},
close: function (event, ui) {
datatypeField.autocomplete("destroy")
}
}).autocomplete("search", "")
})
})
let tagTypeLookupField = $("#node-lookup-valueTag")
let tagTypeField = $("#node-input-valueTag")
tagTypeLookupField.click(function () {
tagTypeLookupField.addClass('disabled')
$.getJSON('/bacnet/ApplicationTags', function (data) {
tagTypeLookupField.removeClass('disabled')
node.lookupItems = []
$.each(data, function (i, entry) {
node.lookupItems.push({value: entry.typeValue, label: entry.label})
})
tagTypeField.autocomplete({
source: node.lookupItems,
minLength: 0,
focus: function (event, ui) {
tagTypeField.val(parseInt(ui.item.value) || 0);
return false;
},
select: function (event, ui) {
tagTypeField.val(parseInt(ui.item.value) || 0)
return false;
},
close: function (event, ui) {
tagTypeField.autocomplete("destroy")
}
}).autocomplete("search", "")
})
})
}
}); </script> <script type='text/x-red' data-template-name='BACnet-Write'>
<div class='form-row'> <label for='node-input-name'><i class='icon-tag'></i> <span
data-i18n='node-red:common.label.name'></span></label> <input type='text' id='node-input-name' placeholder=''> </div>
<div class='form-row'> <label for='node-input-objectType'><i class='icon-search'></i> <span
data-i18n='bacnet-contrib.label.objectType'></span></label> <input type='text' id='node-input-objectType'
style='width:60%' placeholder='8'> <a id='node-lookup-objectType' class='btn'><i id='node-lookup-topic-icon'
class='fa fa-search'></i></a> </div> <div class='form-row'> <label for='node-input-instance'><i class='icon-globe'></i>
<span data-i18n='bacnet-contrib.label.instance'></span></label> <input type='text' id='node-input-instance'> </div> <div
class='form-row'> <h4>Value</h4> <hr> </div> <div class='form-row'> <label for='node-input-valueTag'><i
class='icon-search'></i> <span data-i18n='bacnet-contrib.label.valueTag'></span></label> <input type='text'
id='node-input-valueTag' style='width:60%' placeholder='9'> <a id='node-lookup-valueTag' class='btn'><i
id='node-lookup-topic-icon' class='fa fa-search'></i></a> </div> <div class='form-row'> <label
for='node-input-valueValue'><i class='icon-tag'></i> <span data-i18n='bacnet-contrib.label.valueValue'></span></label>
<input type='text' id='node-input-valueValue' placeholder=''> </div> <div class='form-row'> <h4>Properties</h4> <hr>
</div> <div class='form-row'> <label for='node-input-propertyId'><i class='icon-search'></i> <span
data-i18n='bacnet-contrib.label.propertyId'></span></label> <input type='text' id='node-input-propertyId'
style='width:60%' placeholder='85'> <a id='node-lookup-propertyId' class='btn'><i id='node-lookup-topic-icon'
class='fa fa-search'></i></a> </div> <div class='form-row'> <label for='node-input-priority'><i class='icon-tag'></i>
<span data-i18n='bacnet-contrib.label.priority'></span></label> <input type='text' id='node-input-priority'
placeholder='16'> </div> <div class='form-row'> <hr> <h4>Device and Interface</h4> <hr> </div> <div class='form-row'>
<label for='node-input-device'><i class='icon-globe'></i> <span data-i18n='bacnet-contrib.label.device'></span></label>
<input type='text' id='node-input-device'> </div> <div class='form-row'> <label for='node-input-server'><i
class='icon-globe'></i> <span data-i18n='bacnet-contrib.label.server'></span></label> <input type='text'
id='node-input-server'> </div> <hr> <div class='form-row'> <label style='min-width:160px'
for='node-input-multipleWrite'><i class='fa fa-th'></i> <span data-i18n='bacnet-contrib.label.multipleWrite'></span>
</label> <input type='checkbox' id='node-input-multipleWrite' style='max-width:30px'> </div> </script> <script
type='text/x-red' data-help-name='BACnet-Write'>
<h2>BACnet Write node</h2> <h3>BETA</h3> <a href='https://fh1ch.github.io/node-bacstack/' target='_blank'>API Docs</a>
<p>The msg object properties are used if they filled up with some, otherwise it uses the node settings</p> <h3>
Multiple Write</h3> <h4>Input</h4> <p>msg.payload.deviceIPAddress</p> <strong>msg.payload.values</strong> <i>
Array of objects with properties:</i> <p>objectId.type</p> <p>objectId.instance</p> <p>values</p> <i>
Array of objects with properties:</i> <p>property.id</p> <p>property.index</p> <p>value</p> <i>
Array of objects with properties:</i> <p>tag</p> <p>value</p> <p>Example of msg.payload.values:</p> <pre>
let values = [{ objectId: {
type: objectType,
instance: objectInstance
},
values: [{
property: {
id: propertyId,
index: index
},
value: [{
tag: valueTag,
value: valueValue
}],
priority: priority
}]
}]
</pre> <pre>
const values = [{
objectId: {type: 8, instance: 44301},
values: [{
property: {id: 28, index: 12},
value: [{type: 1, value: true}],
priority: 15
}]
}];
</pre> <p>priority</p> <strong>msg.payload.options (all optional)</strong> <p>msg.payload.options.maxSegments</p>
<p>msg.payload.options.maxAdpu</p> <p>msg.payload.options.invokeId</p> <h3>Simple Write</h3> <h4>Input</h4> <p>
msg.payload.deviceIPAddress</p> <strong>msg.payload.objectId</strong> <p>msg.payload.objectId.type</p> <p>
msg.payload.objectId.instance</p> <p>msg.payload.propertyId</p> <strong>msg.payload.values</strong> <i>
Array of objects with properties:</i> <p>tag</p> <p>value</p> <strong>msg.payload.options (all optional)</strong> <p>
msg.payload.options.maxSegments</p> <p>msg.payload.options.maxAdpu</p> <p>msg.payload.options.invokeId</p> <p>
msg.payload.options.arrayIndex</p> <p>msg.payload.options.priority</p> <pre>
objectId: {type: 8, instance: 44301},
propertyId: 28,
values: [{
type: 4,
value: 100
}]
</pre> <h3>All Modes</h3> <h4>Output</h4> <p>msg.payload</p> </script>