node-red-contrib-modbus-rtu 1.1.28 → 1.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/modbus_rtu.html +38 -8
- package/modbus_rtu.js +62 -3
- package/package.json +1 -1
package/modbus_rtu.html
CHANGED
|
@@ -8,20 +8,25 @@
|
|
|
8
8
|
fn : { value: "0" },
|
|
9
9
|
addr : { value: "" },
|
|
10
10
|
count : { value: "" },
|
|
11
|
+
lamtron : { value: "3" },
|
|
11
12
|
},
|
|
12
13
|
inputs: 1,
|
|
13
|
-
outputs:
|
|
14
|
+
outputs: 2,
|
|
14
15
|
icon: 'bridge.png',
|
|
15
16
|
label: function() {
|
|
16
17
|
if(this.ten != ""){
|
|
17
18
|
return this.ten;
|
|
18
19
|
}
|
|
19
20
|
if (this.fn == "-1") {
|
|
20
|
-
return "
|
|
21
|
+
return "DYNAMIC";
|
|
21
22
|
} else if (this.fn == "-2") {
|
|
22
23
|
return "CHECK CRC";
|
|
23
|
-
}
|
|
24
|
-
return "
|
|
24
|
+
}else if (this.fn == "-3") {
|
|
25
|
+
return "FLOATs ABCD";
|
|
26
|
+
}else if (this.fn == "-4") {
|
|
27
|
+
return "FLOATs CDAB";
|
|
28
|
+
}else if (this.fn == "0") {
|
|
29
|
+
return "ADD CRC";
|
|
25
30
|
} else {
|
|
26
31
|
return `ModbusRTU fn=${this.fn}`;
|
|
27
32
|
}
|
|
@@ -35,21 +40,31 @@
|
|
|
35
40
|
$(".modbus-dynamic").hide();
|
|
36
41
|
$(".modbus-crc").show(); //show crc only
|
|
37
42
|
$(".modbus-check-crc").hide();
|
|
43
|
+
$(".modbus-float").hide();
|
|
38
44
|
} else if (fnValue == "-1") {
|
|
39
45
|
$(".modbus-fields").hide();
|
|
40
46
|
$(".modbus-dynamic").show(); //show dynamic only
|
|
41
47
|
$(".modbus-crc").hide();
|
|
42
48
|
$(".modbus-check-crc").hide();
|
|
49
|
+
$(".modbus-float").hide();
|
|
43
50
|
} else if (fnValue == "-2") {
|
|
44
51
|
$(".modbus-fields").hide();
|
|
45
52
|
$(".modbus-dynamic").hide();
|
|
46
53
|
$(".modbus-crc").hide();
|
|
47
54
|
$(".modbus-check-crc").show(); //show check crc
|
|
48
|
-
|
|
55
|
+
$(".modbus-float").hide();
|
|
56
|
+
} else if (fnValue == "-3" || fnValue == "-4") {
|
|
57
|
+
$(".modbus-fields").hide();
|
|
58
|
+
$(".modbus-dynamic").hide();
|
|
59
|
+
$(".modbus-crc").hide();
|
|
60
|
+
$(".modbus-check-crc").hide();
|
|
61
|
+
$(".modbus-float").show();
|
|
62
|
+
}else {
|
|
49
63
|
$(".modbus-fields").show(); //show gui input fields
|
|
50
64
|
$(".modbus-dynamic").hide();
|
|
51
65
|
$(".modbus-crc").hide();
|
|
52
66
|
$(".modbus-check-crc").hide();
|
|
67
|
+
$(".modbus-float").hide();
|
|
53
68
|
}
|
|
54
69
|
}
|
|
55
70
|
|
|
@@ -75,9 +90,11 @@
|
|
|
75
90
|
<div class="form-row">
|
|
76
91
|
<label for="node-input-fn"><i class="fa fa-tag"></i> Function</label>
|
|
77
92
|
<select id="node-input-fn" style="width:70%">
|
|
78
|
-
<option value=0>CRC ONLY</option>
|
|
79
|
-
<option value=-2>CHECK CRC</option>
|
|
93
|
+
<option value=0>ADD 2 byte CRC ONLY</option>
|
|
94
|
+
<option value=-2>CHECK CRC == 0</option>
|
|
80
95
|
<option value=-1>DYNAMIC by msg.payload.fn</option>
|
|
96
|
+
<option value=-3>FLOATs ABCD</option>
|
|
97
|
+
<option value=-4>FLOATs CDAB</option>
|
|
81
98
|
<option value=1>01 Read Coils (0x)</option>
|
|
82
99
|
<option value=2>02 Read Discrete Inputs [1x]</option>
|
|
83
100
|
<option value=3 selected>03 Read Holding Registers (4x)</option>
|
|
@@ -104,6 +121,10 @@
|
|
|
104
121
|
<input type="text" value="1" id="node-input-count" placeholder="Quantity">
|
|
105
122
|
</div>
|
|
106
123
|
</div>
|
|
124
|
+
<div class="modbus-float">
|
|
125
|
+
<label for="node-input-lamtron"><i class="fa fa-tag"></i> Decimal</label>
|
|
126
|
+
<input type="text" value="3" id="node-input-lamtron" placeholder="Number decimal make round after dot">
|
|
127
|
+
</div>
|
|
107
128
|
<hr>
|
|
108
129
|
<i class="fa fa-bomb"></i> Algorithm
|
|
109
130
|
<pre class="modbus-fields">//Modbus RTU: không phụ thuộc payload đầu vào
|
|
@@ -121,7 +142,10 @@ msg.payload = add_crc16(data);</pre>
|
|
|
121
142
|
const data = msg.payload;
|
|
122
143
|
const _payload = add_crc16(data, out_crc);
|
|
123
144
|
msg.crc = out_crc
|
|
124
|
-
if(out_crc==0)
|
|
145
|
+
if(out_crc==0)
|
|
146
|
+
return [msg, null]; /*output 1 when crc ok*/
|
|
147
|
+
else
|
|
148
|
+
return [null, msg]; /*output 2 when crc error*/</pre>
|
|
125
149
|
<pre class="modbus-dynamic">//DYNAMIC:
|
|
126
150
|
//input (pre node): phụ thuộc vào payload của node trước ở dạng json
|
|
127
151
|
msg.payload = {id:2,fn:3,addr:4,count:5}
|
|
@@ -132,6 +156,12 @@ const addr=msg.payload.addr;
|
|
|
132
156
|
const count=msg.payload.count;
|
|
133
157
|
const data = ModbusMsg(id, fn, addr, count);
|
|
134
158
|
msg.payload = add_crc16(data);</pre>
|
|
159
|
+
<pre class="modbus-float">//FLOAT:
|
|
160
|
+
//input (pre node): msg.payload is data with CRC OK
|
|
161
|
+
//id fn data0 data1... dataN crc1 crc2
|
|
162
|
+
//output: array floats value from byte data0,data1,...,dataN
|
|
163
|
+
//1 float == 4 byte data = Math.round (float, number_decimal)
|
|
164
|
+
</pre>
|
|
135
165
|
<hr>
|
|
136
166
|
Code by Do Duy Cop
|
|
137
167
|
</script>
|
package/modbus_rtu.js
CHANGED
|
@@ -34,6 +34,49 @@ module.exports = function (RED) {
|
|
|
34
34
|
var newPayload = Buffer.concat([payload, crcBuffer]);
|
|
35
35
|
return newPayload;
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
function get_float_abcd(array, indexfrom) {
|
|
39
|
+
var A = array[indexfrom + 0];
|
|
40
|
+
var B = array[indexfrom + 1];
|
|
41
|
+
var C = array[indexfrom + 2];
|
|
42
|
+
var D = array[indexfrom + 3];
|
|
43
|
+
var data = [A, B, C, D];
|
|
44
|
+
var buf = new ArrayBuffer(4);
|
|
45
|
+
var view = new DataView(buf);
|
|
46
|
+
data.forEach(function (b, i) {
|
|
47
|
+
view.setUint8(i, b);
|
|
48
|
+
});
|
|
49
|
+
return view.getFloat32(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function get_float_cdab(array, indexfrom) {
|
|
53
|
+
var A = array[indexfrom + 0];
|
|
54
|
+
var B = array[indexfrom + 1];
|
|
55
|
+
var C = array[indexfrom + 2];
|
|
56
|
+
var D = array[indexfrom + 3];
|
|
57
|
+
var data = [C, D, A, B];
|
|
58
|
+
var buf = new ArrayBuffer(4);
|
|
59
|
+
var view = new DataView(buf);
|
|
60
|
+
data.forEach(function (b, i) {
|
|
61
|
+
view.setUint8(i, b);
|
|
62
|
+
});
|
|
63
|
+
return view.getFloat32(0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function get_float(payload, fn, k){
|
|
67
|
+
const n = payload.length - 2;
|
|
68
|
+
var data = [];
|
|
69
|
+
for (var i = 3; i < n; i += 4) {
|
|
70
|
+
var value = 0;
|
|
71
|
+
if(fn==-3)
|
|
72
|
+
value = get_float_abcd(payload, i);
|
|
73
|
+
else if(fn==-4)
|
|
74
|
+
value = get_float_cdab(payload, i);
|
|
75
|
+
value = Math.round(value * k) / k;
|
|
76
|
+
data.push(value);
|
|
77
|
+
}
|
|
78
|
+
return data;
|
|
79
|
+
}
|
|
37
80
|
|
|
38
81
|
node.on('input', function (msg) {
|
|
39
82
|
var id, fn, addr, count, data = [], out_crc = { crc: " " };
|
|
@@ -50,10 +93,14 @@ module.exports = function (RED) {
|
|
|
50
93
|
var _payload = add_crc(data, out_crc);
|
|
51
94
|
msg.crc = out_crc.crc;
|
|
52
95
|
if(out_crc.crc == 0){
|
|
53
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
54
|
-
node.send(msg);
|
|
96
|
+
node.status({ fill: "green", shape: "dot", text: `${data.length} bytes: CRC == 0`});
|
|
97
|
+
node.send([msg, null]);
|
|
55
98
|
}else{
|
|
56
|
-
|
|
99
|
+
var id=msg.payload[0];
|
|
100
|
+
var fn=msg.payload[1];
|
|
101
|
+
var txt = `id:${id} fn:${fn} CRC:0x${out_crc.crc.toString(16)}`;
|
|
102
|
+
node.status({ fill: "red", shape: "ring", text: txt});
|
|
103
|
+
node.send([null, msg]);
|
|
57
104
|
}
|
|
58
105
|
return;
|
|
59
106
|
} else if (fn == -1) { //dynamic
|
|
@@ -61,6 +108,18 @@ module.exports = function (RED) {
|
|
|
61
108
|
id = parseInt(msg.payload.id);
|
|
62
109
|
addr = parseInt(msg.payload.addr);
|
|
63
110
|
count = parseInt(msg.payload.count);
|
|
111
|
+
} else if (fn == -3 || fn == -4 ) { //float
|
|
112
|
+
const lamtron = parseInt(config.lamtron);
|
|
113
|
+
if(lamtron<0)lamtron=0;
|
|
114
|
+
if(lamtron>9)lamtron=9;
|
|
115
|
+
const Ke=[1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9];
|
|
116
|
+
const k=Ke[lamtron];
|
|
117
|
+
const data = get_float(msg.payload, fn, k);
|
|
118
|
+
msg.payload = data;
|
|
119
|
+
node.send(msg);
|
|
120
|
+
var dem = data.length;
|
|
121
|
+
node.status({ fill: "green", shape: "dot", text: `${dem} floats` });
|
|
122
|
+
return;
|
|
64
123
|
} else if (fn > 0) { // GUI
|
|
65
124
|
id = parseInt(config.slave_id);
|
|
66
125
|
addr = parseInt(config.addr);
|