node-red-contrib-yotta-gpio
Version:
Yotta GPIO API nodes for Node-RED
420 lines (382 loc) • 14.5 kB
HTML
<script type="text/html" data-template-name="Read_AI">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-model"><i class="fa fa-cube"></i> 產品型號</label>
<select id="node-input-model"></select>
</div>
<div class="form-row">
<label for="node-input-modelqty"><i class="fa fa-sliders"></i> 輸入</label>
<select id="node-input-modelqty"></select>
</div>
<div class="form-row">
<label for="node-input-modbusid"><i class="fa fa-id-badge"></i> Modbus ID</label>
<input type="text" id="node-input-modbusid">
</div>
<div class="form-row">
<label for="node-input-modbusqty"><i class="fa fa-sort-numeric-asc"></i> 數量</label>
<input type="text" id="node-input-modbusqty">
</div>
<div class="form-row">
<label for="node-input-modbusaddr"><i class="fa fa-map-marker"></i> 起始位址</label>
<input type="text" id="node-input-modbusaddr" readonly >
</div>
<!-- <fieldset style="border: 1px solid #ccc; padding: 10px; border-radius: 5px;">
<input type="checkbox" id="chbx" name="agree" value="Yes!" />
<label for="chbx">I agree</label>
</fieldset> -->
</script>
<script type="text/javascript">
RED.nodes.registerType('Read_AI', {
category: 'YOTTA GPIO',
color: '#87CEFA',
paletteLabel: "Read-AI", // 左側欄位顯示的節點名稱
defaults: {
name: { value: "" },
model: { value: "" },
modelQty: { value: "" },
modbusId: { value: "1",required: true, validate: RED.validators.number() },
modbusQty:{ value: "1",
required: true,
validate: function(v) {
return RED.validators.number()(v) && Number(v) > 0;
}
},
modbusAddr: { value: "" }
},
inputs: 1,
outputs: 1,
icon: "status.svg",
label: function () {
return this.name || this.model;
},
oneditprepare: function () {
const $model = $("#node-input-model");
const $modelqty = $("#node-input-modelqty");
const $modbusid = $("#node-input-modbusid");
const $modbusqty = $("#node-input-modbusqty");
const $modbusaddr = $("#node-input-modbusaddr");
var savedModel = this.model;
var savedQty = this.modelQty;
var savedModebusId = this.modbusId;
var savedModbusQty = this.modbusQty;
var savedModbusAddr = this.modbusAddr;
var moduleData;
debugger; // 在瀏覽器中執行Ctr+Shit+i開啟除錯畫面,可以針對html中的程式除錯
$.getJSON("Read_AI/0", function (data) { //向後端獲取產品訊息
moduleData = data;
// 填入型號選單
//$.each(moduleData, function (modelName,modelInfo) {
// if(modelInfo.AI > 0){
// $model.append($("<option></option>").val(modelName).text(modelName));
// }
//});
$.each(moduleData, function (categoryName, models) {
const $optgroup = $("<optgroup></optgroup>")
.attr("label", categoryName);
$.each(models, function (modelName, modelInfo) {
if (modelInfo.AI > 0) {
$optgroup.append(
$("<option></option>").val(modelName).text(modelName)
);
}
});
// 如果 optgroup 下有 option 再加入
if ($optgroup.children().length > 0) {
$model.append($optgroup);
}
});
if (!savedModel) {
savedModel = $model.find("option:first").val();
} else $model.val(savedModel); //若savedModel非空,載入model欄位初值
if (savedQty) $modelqty.val(savedQty); //若savedQty非空,載入Qty欄位初值
if (savedModebusId) $modbusid.val(savedModebusId); //若savedId非空,載入modbusid欄位初值
if (savedModbusQty) $modbusqty.val(savedModbusQty); //若savedModbusQty非空,載入modbusqty欄位初值
$model.on("change", function () {
savedModel = $(this).val();
savedQty = 0;
updateQtyAndAddress(savedModel);
});
$modelqty.on("change", function () {
savedQty = $(this).val();
//const addr = moduleData[savedModel].address["AI"] + Number(savedQty);
const modelInfo = findModelInfo(savedModel);
const addr = modelInfo.address["AI"] + Number(savedQty);
$modbusaddr.val(addr !== null ? addr : "N/A");
});
$modbusid.on("keyup", function () { //輸入中(keyup)或輸入完畢後離開欄位(change),都能觸發驗證或處理邏輯。
const val = Number($(this).val().trim());
if (val == 0 || isNaN(val) ) { //判斷modbus ID欄位內容是否合法,不合法將欄位邊框變紅色
$(this).addClass("input-error");
} else {
$(this).removeClass("input-error");
}
});
$modbusqty.on("keyup", function () { //輸入中(keyup)或輸入完畢後離開欄位(change),都能觸發驗證或處理邏輯。
const val = Number($(this).val().trim());
if (val == 0 || isNaN(val)) { //判斷modbus 數量欄位內容是否合法,不合法將欄位邊框變紅色
$(this).addClass("input-error");
} else {
$(this).removeClass("input-error");
}
});
// 觸發初始化選項
if (savedModel) {
updateQtyAndAddress(savedModel);
//if(savedModebusId == "") $modbusid.val("1");
//if(savedModbusQty == "") $modbusqty.val("1");
$modbusid.trigger("keyup");
$modbusqty.trigger("keyup");
}
})
.fail(function() {
console.log( "error" );
});
function findModelInfo(modelName) {
for (const category in moduleData) {
if (moduleData[category][modelName]) {
return moduleData[category][modelName];
}
}
return null;
}
function updateQtyAndAddress(model, type) { //將指定model的輸出/入類別編號填入option選單內。
$modelqty.empty(); //清空<select id="node-input-modelqty"> 這個欄位中的所有 <option>,以便重新建立。
//const count = moduleData[model]["AI"]-1;
//const addr = moduleData[model].address["AI"] +Number(savedQty);
const modelInfo = findModelInfo(model);
if (!modelInfo) return;
const count = modelInfo["AI"] - 1;
const addr = modelInfo.address["AI"] + Number(savedQty);
for (let i = 0; i <= count; i++) {
$modelqty.append($("<option></option>").val(i).text("AI " + i));
}
if (savedQty) $modelqty.val(savedQty);
$modbusaddr.val(addr !== null ? addr : "N/A");
}
},
oneditsave: function () {
this.name = $("#node-input-name").val();
this.model = $("#node-input-model").val();
this.modelQty = $("#node-input-modelqty").val();
this.modbusId = $("#node-input-modbusid").val();
this.modbusAddr = $("#node-input-modbusaddr").val();
this.modbusQty = $("#node-input-modbusqty").val();
},
oneditresize: function (size) {
}
});
</script>
<script type="text/x-red" data-help-name="Read_AI">
<p>
<strong>Read_AI</strong> 節點用於將指定數值寫入 AI (Analog Input) 腳位,並與 <code>Modbus-Flex-Getter</code> 節點配合使用。
</p>
<h3>功能說明</h3>
<ul>
<li><strong>產品型號</strong>:支援多種 Yotta 模組型號</li>
<li><strong>輸出腳位</strong>:可選擇 AI 腳位 (例如 AI 0、AI 1 等)</li>
<li><strong>Modbus ID</strong>:目標設備的通訊位址</li>
<li><strong>數量</strong>:讀取的腳位數量</li>
</ul>
<h3>注意事項</h3>
<ul>
<li>Modbus ID、腳位數量與起始位址必須正確對應實際設備</li>
<li>務必與 <code>Modbus-Flex-Getter</code> 節點搭配使用</li>
<li>未填寫必要欄位將導致資料封包錯誤</li>
</ul>
<h3>使用範例</h3>
<p>讀取AI 0~3:</p>
<pre><code style="font-size: smaller">
[
{
"id": "682283343ccb2c91",
"type": "tab",
"label": "流程6",
"disabled": false,
"info": "",
"env": []
},
{
"id": "eaaaeabe8ec8aa8d",
"type": "inject",
"z": "682283343ccb2c91",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "0",
"payloadType": "num",
"x": 90,
"y": 120,
"wires": [
[
"d2f84e581899f54a"
]
]
},
{
"id": "10fc938111bf1649",
"type": "debug",
"z": "682283343ccb2c91",
"name": "debug 50",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 700,
"y": 120,
"wires": []
},
{
"id": "c6c06cb0a7e8a6a6",
"type": "inject",
"z": "682283343ccb2c91",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "0",
"payloadType": "num",
"x": 90,
"y": 220,
"wires": [
[
"68d94f58930d12db"
]
]
},
{
"id": "73c24c346a435a5b",
"type": "comment",
"z": "682283343ccb2c91",
"name": "單點讀取",
"info": "",
"x": 260,
"y": 80,
"wires": []
},
{
"id": "41f4060209983c0e",
"type": "comment",
"z": "682283343ccb2c91",
"name": "多點讀取",
"info": "",
"x": 260,
"y": 180,
"wires": []
},
{
"id": "c54d4e97d0db0a5c",
"type": "modbus-flex-getter",
"z": "682283343ccb2c91",
"name": "",
"showStatusActivities": false,
"showErrors": false,
"logIOActivities": false,
"server": "43a839a6b2d13bf4",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"keepMsgProperties": false,
"x": 470,
"y": 120,
"wires": [
[
"10fc938111bf1649"
],
[]
]
},
{
"id": "d2f84e581899f54a",
"type": "Read_AI",
"z": "682283343ccb2c91",
"name": "",
"model": "A-1812",
"modelQty": "",
"modbusId": "1",
"modbusQty": "1",
"modbusAddr": "",
"x": 260,
"y": 120,
"wires": [
[
"c54d4e97d0db0a5c"
]
]
},
{
"id": "68d94f58930d12db",
"type": "Read_AI",
"z": "682283343ccb2c91",
"name": "",
"model": "A-1812",
"modelQty": "0",
"modbusId": "1",
"modbusQty": "4",
"modbusAddr": "0",
"x": 260,
"y": 220,
"wires": [
[
"c54d4e97d0db0a5c"
]
]
},
{
"id": "43a839a6b2d13bf4",
"type": "modbus-client",
"name": "",
"clienttype": "tcp",
"bufferCommands": true,
"stateLogEnabled": false,
"queueLogEnabled": false,
"tcpHost": "127.0.0.1",
"tcpPort": "502",
"tcpType": "DEFAULT",
"serialPort": "/dev/ttyUSB",
"serialType": "RTU-BUFFERD",
"serialBaudrate": "9600",
"serialDatabits": "8",
"serialStopbits": "1",
"serialParity": "none",
"serialConnectionDelay": "100",
"serialAsciiResponseStartDelimiter": "0x3A",
"unit_id": "1",
"commandDelay": "1",
"clientTimeout": "1000",
"reconnectOnTimeout": true,
"reconnectTimeout": "2000",
"parallelUnitIdsAllowed": true
}
]
</pre></code>
</script>