node-zserial 1.0.3 → 1.0.4

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/README.md CHANGED
@@ -63,14 +63,14 @@ node-zserialport
63
63
 
64
64
  要控制通信,向控制节点发送 **msg.payload**。
65
65
 
66
- {
66
+ {
67
67
  "serialport": "/dev/ttyUSB0",
68
68
  "serialbaud": 115200,
69
69
  "databits": 8,
70
70
  "parity": "none",
71
71
  "stopbits": 1,
72
72
  "enabled": true
73
- }
73
+ }
74
74
 
75
75
  可以动态更改串口及其配置。
76
76
 
@@ -96,3 +96,18 @@ node-zserialport
96
96
 
97
97
  任何输入消息都会导致节点输出当前端口配置。
98
98
 
99
+ ### MAC
100
+
101
+ mac 模拟串口
102
+
103
+ ***
104
+ socat -d -d pty,raw,echo=0 pty,raw,echo=0
105
+
106
+ socat -d -d pty,raw,echo=0 pty,raw,echo=0 | socat -d -d -d -d pty,raw,echo=0
107
+ ***
108
+
109
+ 连接串口
110
+
111
+ ***
112
+ screen /dev/ttys003 9600
113
+ ***
@@ -2,7 +2,7 @@
2
2
  {
3
3
  "id": "ac7bf7ec36d6a989",
4
4
  "type": "function",
5
- "z": "6c5cb5c635f82b56",
5
+ "z": "d83ba3a0e79165f6",
6
6
  "name": "发送内容",
7
7
  "func": "msg.serialConfig=msg.serialPorts;\nmsg.payload=msg.serialConfig.serialport+\"\\n\";\nreturn msg;",
8
8
  "outputs": 1,
@@ -11,11 +11,10 @@
11
11
  "initialize": "",
12
12
  "finalize": "",
13
13
  "libs": [],
14
- "x": 680,
15
- "y": 160,
14
+ "x": 580,
15
+ "y": 240,
16
16
  "wires": [
17
17
  [
18
- "1bbc5a3a00e0c543",
19
18
  "cc85519d5a973bd6"
20
19
  ]
21
20
  ]
@@ -23,7 +22,7 @@
23
22
  {
24
23
  "id": "1b8e7a8fee300657",
25
24
  "type": "inject",
26
- "z": "6c5cb5c635f82b56",
25
+ "z": "d83ba3a0e79165f6",
27
26
  "name": "",
28
27
  "props": [],
29
28
  "repeat": "",
@@ -31,8 +30,8 @@
31
30
  "once": false,
32
31
  "onceDelay": 0.1,
33
32
  "topic": "",
34
- "x": 310,
35
- "y": 100,
33
+ "x": 210,
34
+ "y": 180,
36
35
  "wires": [
37
36
  [
38
37
  "fcaaa0d1d662e5c5"
@@ -42,7 +41,7 @@
42
41
  {
43
42
  "id": "c5b2a60e99954c23",
44
43
  "type": "debug",
45
- "z": "6c5cb5c635f82b56",
44
+ "z": "d83ba3a0e79165f6",
46
45
  "name": "=========调试 6",
47
46
  "active": true,
48
47
  "tosidebar": true,
@@ -52,14 +51,14 @@
52
51
  "targetType": "full",
53
52
  "statusVal": "",
54
53
  "statusType": "auto",
55
- "x": 1050,
56
- "y": 200,
54
+ "x": 950,
55
+ "y": 240,
57
56
  "wires": []
58
57
  },
59
58
  {
60
59
  "id": "2e52a7d5dcba1731",
61
60
  "type": "split",
62
- "z": "6c5cb5c635f82b56",
61
+ "z": "d83ba3a0e79165f6",
63
62
  "name": "",
64
63
  "splt": "\\n",
65
64
  "spltType": "str",
@@ -68,28 +67,29 @@
68
67
  "stream": false,
69
68
  "addname": "",
70
69
  "property": "serialPorts",
71
- "x": 670,
72
- "y": 100,
70
+ "x": 570,
71
+ "y": 180,
73
72
  "wires": [
74
73
  [
75
- "ac7bf7ec36d6a989"
74
+ "ac7bf7ec36d6a989",
75
+ "de1ba17b88689674"
76
76
  ]
77
77
  ]
78
78
  },
79
79
  {
80
80
  "id": "fcaaa0d1d662e5c5",
81
81
  "type": "function",
82
- "z": "6c5cb5c635f82b56",
82
+ "z": "d83ba3a0e79165f6",
83
83
  "name": "窗口配置数组",
84
- "func": "let serialPorts = [\n {\n serialport: '/dev/ttys018',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1\n },\n {\n serialport:'/dev/ttys021',\n baud:9600,\n databits:8,\n parity:'NONE',\n stopbits:1\n }\n];\nmsg.serialPorts=serialPorts;\nreturn msg;",
84
+ "func": "let serialPorts = [\n {\n serialport:'/dev/ttys027',\n baud:9600,\n databits:8,\n parity:'NONE',\n stopbits:1,\n responsetimeout:3\n },\n {\n serialport: '/dev/ttys018',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1,\n responsetimeout:5\n },\n \n];\nmsg.serialPorts=serialPorts;\nreturn msg;",
85
85
  "outputs": 1,
86
86
  "timeout": 0,
87
87
  "noerr": 0,
88
88
  "initialize": "",
89
89
  "finalize": "",
90
90
  "libs": [],
91
- "x": 500,
92
- "y": 100,
91
+ "x": 400,
92
+ "y": 180,
93
93
  "wires": [
94
94
  [
95
95
  "2e52a7d5dcba1731"
@@ -99,7 +99,7 @@
99
99
  {
100
100
  "id": "fd3f7169e7cc20e8",
101
101
  "type": "inject",
102
- "z": "6c5cb5c635f82b56",
102
+ "z": "d83ba3a0e79165f6",
103
103
  "name": "",
104
104
  "props": [],
105
105
  "repeat": "",
@@ -107,8 +107,8 @@
107
107
  "once": false,
108
108
  "onceDelay": 0.1,
109
109
  "topic": "",
110
- "x": 310,
111
- "y": 160,
110
+ "x": 210,
111
+ "y": 240,
112
112
  "wires": [
113
113
  [
114
114
  "9b1c32cc48ea5751"
@@ -118,7 +118,7 @@
118
118
  {
119
119
  "id": "9b1c32cc48ea5751",
120
120
  "type": "function",
121
- "z": "6c5cb5c635f82b56",
121
+ "z": "d83ba3a0e79165f6",
122
122
  "name": "单独配置",
123
123
  "func": "\nmsg.serialPorts = {\n serialport: '/dev/ttys021',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1\n};\nmsg.queueSend = false;\nreturn msg;",
124
124
  "outputs": 1,
@@ -127,8 +127,8 @@
127
127
  "initialize": "",
128
128
  "finalize": "",
129
129
  "libs": [],
130
- "x": 480,
131
- "y": 160,
130
+ "x": 380,
131
+ "y": 240,
132
132
  "wires": [
133
133
  [
134
134
  "ac7bf7ec36d6a989"
@@ -136,39 +136,33 @@
136
136
  ]
137
137
  },
138
138
  {
139
- "id": "b55e31e41cb990b1",
140
- "type": "zserial in",
141
- "z": "6c5cb5c635f82b56",
142
- "name": "统一接收通道",
143
- "x": 500,
139
+ "id": "cc85519d5a973bd6",
140
+ "type": "zserial request",
141
+ "z": "d83ba3a0e79165f6",
142
+ "name": "发收通道",
143
+ "x": 740,
144
144
  "y": 240,
145
145
  "wires": [
146
146
  [
147
- "a4725e6909264fb5"
147
+ "c5b2a60e99954c23"
148
148
  ]
149
149
  ]
150
150
  },
151
151
  {
152
- "id": "a4725e6909264fb5",
153
- "type": "debug",
154
- "z": "6c5cb5c635f82b56",
155
- "name": "调试 1",
156
- "active": true,
157
- "tosidebar": true,
158
- "console": false,
159
- "tostatus": false,
160
- "complete": "true",
161
- "targetType": "full",
162
- "statusVal": "",
163
- "statusType": "auto",
164
- "x": 670,
165
- "y": 240,
166
- "wires": []
152
+ "id": "0e4c242820dcc156",
153
+ "type": "zserial closeAll",
154
+ "z": "d83ba3a0e79165f6",
155
+ "name": "全部关闭",
156
+ "x": 380,
157
+ "y": 480,
158
+ "wires": [
159
+ []
160
+ ]
167
161
  },
168
162
  {
169
- "id": "a6efadadceca633c",
163
+ "id": "052eea87f99970b0",
170
164
  "type": "inject",
171
- "z": "6c5cb5c635f82b56",
165
+ "z": "d83ba3a0e79165f6",
172
166
  "name": "",
173
167
  "props": [],
174
168
  "repeat": "",
@@ -176,51 +170,29 @@
176
170
  "once": false,
177
171
  "onceDelay": "1",
178
172
  "topic": "",
179
- "x": 310,
180
- "y": 240,
181
- "wires": [
182
- [
183
- "b55e31e41cb990b1"
184
- ]
185
- ]
186
- },
187
- {
188
- "id": "1bbc5a3a00e0c543",
189
- "type": "zserial out",
190
- "z": "6c5cb5c635f82b56",
191
- "name": "统一发送通道",
192
- "x": 860,
193
- "y": 140,
194
- "wires": []
195
- },
196
- {
197
- "id": "cc85519d5a973bd6",
198
- "type": "zserial request",
199
- "z": "6c5cb5c635f82b56",
200
- "name": "发收通道",
201
- "x": 840,
202
- "y": 200,
173
+ "x": 210,
174
+ "y": 480,
203
175
  "wires": [
204
176
  [
205
- "c5b2a60e99954c23"
177
+ "0e4c242820dcc156"
206
178
  ]
207
179
  ]
208
180
  },
209
181
  {
210
- "id": "0e4c242820dcc156",
182
+ "id": "ef3b251330bafa25",
211
183
  "type": "zserial closeAll",
212
- "z": "6c5cb5c635f82b56",
213
- "name": "全部关闭",
214
- "x": 480,
215
- "y": 340,
184
+ "z": "d83ba3a0e79165f6",
185
+ "name": "单独关闭",
186
+ "x": 540,
187
+ "y": 540,
216
188
  "wires": [
217
189
  []
218
190
  ]
219
191
  },
220
192
  {
221
- "id": "052eea87f99970b0",
193
+ "id": "98f8acd5d825b6dd",
222
194
  "type": "inject",
223
- "z": "6c5cb5c635f82b56",
195
+ "z": "d83ba3a0e79165f6",
224
196
  "name": "",
225
197
  "props": [],
226
198
  "repeat": "",
@@ -228,61 +200,206 @@
228
200
  "once": false,
229
201
  "onceDelay": "1",
230
202
  "topic": "",
231
- "x": 310,
232
- "y": 340,
203
+ "x": 210,
204
+ "y": 540,
233
205
  "wires": [
234
206
  [
235
- "0e4c242820dcc156"
207
+ "48f42e1d3e51dd37"
236
208
  ]
237
209
  ]
238
210
  },
239
211
  {
240
- "id": "ef3b251330bafa25",
241
- "type": "zserial closeAll",
242
- "z": "6c5cb5c635f82b56",
243
- "name": "单独关闭",
244
- "x": 640,
212
+ "id": "48f42e1d3e51dd37",
213
+ "type": "function",
214
+ "z": "d83ba3a0e79165f6",
215
+ "name": "单独配置",
216
+ "func": "\nmsg.serialConfig = {\n serialport: '/dev/ttys021',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1\n};\nreturn msg;",
217
+ "outputs": 1,
218
+ "timeout": 0,
219
+ "noerr": 0,
220
+ "initialize": "",
221
+ "finalize": "",
222
+ "libs": [],
223
+ "x": 380,
224
+ "y": 540,
225
+ "wires": [
226
+ [
227
+ "ef3b251330bafa25"
228
+ ]
229
+ ]
230
+ },
231
+ {
232
+ "id": "de1ba17b88689674",
233
+ "type": "debug",
234
+ "z": "d83ba3a0e79165f6",
235
+ "name": "调试 4",
236
+ "active": true,
237
+ "tosidebar": true,
238
+ "console": false,
239
+ "tostatus": false,
240
+ "complete": "true",
241
+ "targetType": "full",
242
+ "statusVal": "",
243
+ "statusType": "auto",
244
+ "x": 730,
245
+ "y": 180,
246
+ "wires": []
247
+ },
248
+ {
249
+ "id": "e2a9ce8197332b37",
250
+ "type": "zserial batch",
251
+ "z": "d83ba3a0e79165f6",
252
+ "name": "批量发收",
253
+ "x": 580,
245
254
  "y": 400,
246
255
  "wires": [
247
- []
256
+ [
257
+ "4bb8ea3e0f7356c4"
258
+ ],
259
+ [
260
+ "fb3429149bdb670e"
261
+ ],
262
+ [
263
+ "0b7d2e09c81f4b21"
264
+ ]
248
265
  ]
249
266
  },
250
267
  {
251
- "id": "98f8acd5d825b6dd",
268
+ "id": "24569a0782518192",
252
269
  "type": "inject",
253
- "z": "6c5cb5c635f82b56",
270
+ "z": "d83ba3a0e79165f6",
254
271
  "name": "",
255
272
  "props": [],
256
273
  "repeat": "",
257
274
  "crontab": "",
258
275
  "once": false,
259
- "onceDelay": "1",
276
+ "onceDelay": 0.1,
260
277
  "topic": "",
261
- "x": 310,
278
+ "x": 210,
262
279
  "y": 400,
263
280
  "wires": [
264
281
  [
265
- "48f42e1d3e51dd37"
282
+ "8cc9a6e4d6656909"
266
283
  ]
267
284
  ]
268
285
  },
269
286
  {
270
- "id": "48f42e1d3e51dd37",
287
+ "id": "8cc9a6e4d6656909",
271
288
  "type": "function",
272
- "z": "6c5cb5c635f82b56",
273
- "name": "单独配置",
274
- "func": "\nmsg.serialConfig = {\n serialport: '/dev/ttys021',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1\n};\nreturn msg;",
289
+ "z": "d83ba3a0e79165f6",
290
+ "name": "窗口配置数组",
291
+ "func": "let serialPorts = [\n {\n serialport:'/dev/ttys022',\n baud:9600,\n databits:8,\n parity:'NONE',\n stopbits:1,\n responsetimeout:12000,\n payload:'ttys022\\n'\n },\n {\n serialport: '/dev/ttys026',\n baud: 9600,\n databits: 8,\n parity: 'NONE',\n stopbits: 1,\n responsetimeout:15000,\n payload:'ttys026\\n'\n },\n \n];\nmsg.flush=false;\nmsg.serialConfigs=serialPorts;\nreturn msg;",
275
292
  "outputs": 1,
276
293
  "timeout": 0,
277
294
  "noerr": 0,
278
295
  "initialize": "",
279
296
  "finalize": "",
280
297
  "libs": [],
281
- "x": 480,
298
+ "x": 400,
282
299
  "y": 400,
283
300
  "wires": [
284
301
  [
285
- "ef3b251330bafa25"
302
+ "e2a9ce8197332b37"
303
+ ]
304
+ ]
305
+ },
306
+ {
307
+ "id": "4bb8ea3e0f7356c4",
308
+ "type": "debug",
309
+ "z": "d83ba3a0e79165f6",
310
+ "name": "////////////调试 8",
311
+ "active": true,
312
+ "tosidebar": true,
313
+ "console": false,
314
+ "tostatus": false,
315
+ "complete": "true",
316
+ "targetType": "full",
317
+ "statusVal": "",
318
+ "statusType": "auto",
319
+ "x": 840,
320
+ "y": 360,
321
+ "wires": []
322
+ },
323
+ {
324
+ "id": "fb3429149bdb670e",
325
+ "type": "debug",
326
+ "z": "d83ba3a0e79165f6",
327
+ "name": "调试 8",
328
+ "active": true,
329
+ "tosidebar": true,
330
+ "console": false,
331
+ "tostatus": false,
332
+ "complete": "true",
333
+ "targetType": "full",
334
+ "statusVal": "",
335
+ "statusType": "auto",
336
+ "x": 830,
337
+ "y": 400,
338
+ "wires": []
339
+ },
340
+ {
341
+ "id": "0b7d2e09c81f4b21",
342
+ "type": "debug",
343
+ "z": "d83ba3a0e79165f6",
344
+ "name": "++++++调试 9",
345
+ "active": true,
346
+ "tosidebar": true,
347
+ "console": false,
348
+ "tostatus": false,
349
+ "complete": "true",
350
+ "targetType": "full",
351
+ "statusVal": "",
352
+ "statusType": "auto",
353
+ "x": 840,
354
+ "y": 440,
355
+ "wires": []
356
+ },
357
+ {
358
+ "id": "ce72b12d1101e66b",
359
+ "type": "zserial in",
360
+ "z": "d83ba3a0e79165f6",
361
+ "name": "统一接收通道",
362
+ "x": 400,
363
+ "y": 300,
364
+ "wires": [
365
+ [
366
+ "3e8f4e282ee7f980"
367
+ ]
368
+ ]
369
+ },
370
+ {
371
+ "id": "3e8f4e282ee7f980",
372
+ "type": "debug",
373
+ "z": "d83ba3a0e79165f6",
374
+ "name": "调试 9",
375
+ "active": true,
376
+ "tosidebar": true,
377
+ "console": false,
378
+ "tostatus": false,
379
+ "complete": "true",
380
+ "targetType": "full",
381
+ "statusVal": "",
382
+ "statusType": "auto",
383
+ "x": 570,
384
+ "y": 300,
385
+ "wires": []
386
+ },
387
+ {
388
+ "id": "0215791db4d97215",
389
+ "type": "inject",
390
+ "z": "d83ba3a0e79165f6",
391
+ "name": "",
392
+ "props": [],
393
+ "repeat": "",
394
+ "crontab": "",
395
+ "once": false,
396
+ "onceDelay": "1",
397
+ "topic": "",
398
+ "x": 210,
399
+ "y": 300,
400
+ "wires": [
401
+ [
402
+ "ce72b12d1101e66b"
286
403
  ]
287
404
  ]
288
405
  }
package/images/demo.png CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-zserial",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Node-RED nodes to talk to serial ports",
5
5
  "dependencies": {
6
6
  "serialport": "^12.0.0"
package/zserial.html CHANGED
@@ -22,6 +22,29 @@
22
22
  });
23
23
  </script>
24
24
 
25
+ <script type="text/html" data-template-name="zserial batch">
26
+ <div class="form-row">
27
+ <label for="node-inputoutput-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
28
+ <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
29
+ </div>
30
+ </script>
31
+
32
+ <script type="text/javascript">
33
+ RED.nodes.registerType('zserial batch',{
34
+ category: 'zutils',
35
+ defaults: {
36
+ name: {name:""}
37
+ },
38
+ color:"BurlyWood",
39
+ inputs:1,
40
+ outputs:3,
41
+ icon: "serial.png",
42
+ align: "left",
43
+ label: function() {
44
+ return this.name || "zserial batch";
45
+ }
46
+ });
47
+ </script>
25
48
 
26
49
 
27
50
  <script type="text/html" data-template-name="zserial in">
package/zserial.js CHANGED
@@ -129,7 +129,7 @@ module.exports = function (RED) {
129
129
  onMsg(msg, send, done);
130
130
  })
131
131
 
132
- function getConnection() {
132
+ function getConnection() {
133
133
  let conns = serialPool.curConnections();
134
134
  let connKeys = Object.keys(conns) || [];
135
135
  return { conns, connKeys }
@@ -230,14 +230,15 @@ module.exports = function (RED) {
230
230
  }
231
231
  if (msg.hasOwnProperty("flush") && msg.flush === true) { curPort.serial.flush(); }
232
232
  let statusText = `waiting:${curPort.serial.path}`
233
- node.status({ fill: "yellow", shape: "dot", text: "serial.status.waiting:" + curPort.serial.path });
233
+ node.status({ fill: "yellow", shape: "dot", text: statusText });
234
+
235
+ setCallback(msg, done);
236
+
234
237
  curPort.enqueue(msg, node, function (err, res) {
235
238
  if (err) {
236
239
  node.error(err)
237
240
  }
238
241
  });
239
-
240
- setCallback(msg, done);
241
242
  }
242
243
  function setCallback(msg, done) {
243
244
  let curPort = serialPool.get(msg.serialConfig);
@@ -253,7 +254,7 @@ module.exports = function (RED) {
253
254
  // node.warn("对象绑定::"+ node == sender);
254
255
  // serial request will only process incoming data pertaining to its own request (i.e. when it's at the head of the queue)
255
256
  if (sender !== node) { return; }
256
- node.status({ fill: "green", shape: "dot", text: "node-red:common.status.ok" });
257
+ node.status({ fill: "green", shape: "dot", text: "ok:::" + curPort.serial.path });
257
258
  msgout.status = "OK";
258
259
  node.send(msgout);
259
260
  // if (done) done();
@@ -261,18 +262,18 @@ module.exports = function (RED) {
261
262
  curPort.on('timeout', function (msgout, sender) {
262
263
  if (sender !== node) { return; }
263
264
  msgout.status = "ERR_TIMEOUT";
264
- node.status({ fill: "red", shape: "ring", text: "serial.status.timeout" });
265
+ node.status({ fill: "red", shape: "ring", text: "timeout:::" + curPort.serial.path });
265
266
  node.send(msgout);
266
267
  // if (done) done();
267
268
  });
268
269
  curPort.on('ready', function () {
269
- node.status({ fill: "green", shape: "dot", text: "node-red:common.status.connected" });
270
+ node.status({ fill: "green", shape: "dot", text: "connected:::" + curPort.serial.path });
270
271
  });
271
272
  curPort.on('closed', function () {
272
- node.status({ fill: "red", shape: "ring", text: "node-red:common.status.not-connected" });
273
+ node.status({ fill: "red", shape: "ring", text: "not-connected:::" + curPort.serial.path });
273
274
  });
274
275
  curPort.on('stopped', function () {
275
- node.status({ fill: "grey", shape: "ring", text: "serial.status.stopped" });
276
+ node.status({ fill: "grey", shape: "ring", text: "stopped:::" + curPort.serial.path });
276
277
  });
277
278
  }
278
279
 
@@ -291,6 +292,216 @@ module.exports = function (RED) {
291
292
  }
292
293
  RED.nodes.registerType("zserial request", SerialRequestNode);
293
294
 
295
+ function SerialBatchRequest(n) {
296
+ RED.nodes.createNode(this, n);
297
+ var node = this;
298
+ node.totallenth = 0;
299
+ node.totalMsg = {};
300
+ node.successMsg = {};
301
+ node.errorMsg = {};
302
+ function zsend(msg, err, alldone, port) {
303
+
304
+ if (msg) {
305
+ node.successMsg[port] = {
306
+ msg: msg,
307
+ }
308
+ }
309
+ if (err) {
310
+ node.errorMsg[port] = {
311
+ err: err,
312
+ }
313
+ }
314
+ if (node.totalMsg[port]) {
315
+ node.totalMsg[port] = Object.assign(node.totalMsg[port], {
316
+ msg: msg || err,
317
+ })
318
+ } else {
319
+ node.totalMsg[port] = {
320
+ msg: msg || err,
321
+ }
322
+ }
323
+
324
+ node.send([msg, err, alldone]);
325
+ sendAll();
326
+
327
+ }
328
+ function onMsg(msg, send, done) {
329
+ if (!msg.serialConfigs) {
330
+ node.error("需要配置批量配置:msg.serialConfigs");
331
+ // zsend(msg, null, null)
332
+ done();
333
+ return;
334
+ }
335
+ node.totallenth = msg.serialConfigs.length;
336
+ for (var i = 0; i < msg.serialConfigs.length; i++) {
337
+ var serialConfig = msg.serialConfigs[i];
338
+ serialConfig._msgid = msg._msgid + "_" + i;
339
+ // totalMsg[serialConfig.serialport] = {
340
+ // serialConfig: serialConfig,
341
+ // };
342
+ getSerialServer(msg, serialConfig);
343
+ }
344
+ }
345
+
346
+ function sendAll() {
347
+ try {
348
+ let len = Object.keys(node.totalMsg).length;
349
+ if (len == node.totallenth) {
350
+ node.send([null, null, {
351
+ totalMsg: node.totalMsg,
352
+ successMsg: node.successMsg,
353
+ errorMsg: node.errorMsg,
354
+ }]);
355
+ }
356
+ } catch (error) {
357
+ node.error(error);
358
+ }
359
+
360
+ }
361
+ function getSerialServer(msg, serialConfig) {
362
+ let curPort = serialPool.get(serialConfig);
363
+
364
+ if (msg.hasOwnProperty("baudrate")) {
365
+ var baud = parseInt(msg.baudrate);
366
+ if (isNaN(baud)) {
367
+ // node.error(RED._("serial.errors.badbaudrate"), msg);
368
+ zsend(null, {
369
+ msg: msg,
370
+ text: RED._("serial.errors.badbaudrate")
371
+ }, null, curPort.serial.path)
372
+ } else {
373
+ curPort.update({ baudRate: baud }, function (err, res) {
374
+ if (err) {
375
+ // node.error(err);
376
+ zsend(null, {
377
+ msg: msg,
378
+ status: "ERR_UPDATE",
379
+ error: err,
380
+ text: "更新波特率失败"
381
+ }, null, curPort.serial.path)
382
+ }
383
+ });
384
+ }
385
+ }
386
+ if (!serialConfig.hasOwnProperty("payload")) {
387
+ zsend(null, {
388
+ msg: msg,
389
+ text: "No payload"
390
+ }, null, curPort.serial.path)
391
+ return;
392
+ } // do nothing unless we have a payload
393
+ if (msg.hasOwnProperty("count") && (typeof msg.count === "number") && (serialConfig.out === "count")) {
394
+ serialConfig.newline = msg.count;
395
+ }
396
+ if (msg.hasOwnProperty("flush") && msg.flush === true) { curPort.serial.flush(); }
397
+
398
+ setCallback(msg, serialConfig, function (err, res) {
399
+
400
+ });
401
+ // msg.payload = serialConfig.payload;
402
+ setTimeout(function () {
403
+ try {
404
+ // node.warn(`当前:${curPort.serial.path}打开状态,${curPort.isopen}`);
405
+ if (curPort.isopen) {
406
+ curPort.enqueue(serialConfig, node, function (err, res) {
407
+ // node.warn("加入队列::" + curPort.serial.path);
408
+ // node.warn(curPort.queue);
409
+ // node.warn(res);
410
+ if (err) {
411
+ node.error(err)
412
+ }
413
+ }, function (queue) {
414
+ // node.warn("队列开始发送::");
415
+ // node.warn(queue);
416
+ });
417
+ } else {
418
+ curPort._retryNum = 0
419
+ zsend(null, {
420
+ status: "ERR_IN_QUEUE",
421
+ msg: '串口未打开,加入消息队列失败',
422
+ port: curPort.serial.path
423
+ }, null, curPort.serial.path);
424
+ }
425
+ } catch (error) {
426
+ node.error(error);
427
+ }
428
+
429
+ }, 100);
430
+
431
+
432
+ }
433
+
434
+ function setCallback(msg, serialConfig, done) {
435
+ let curPort = serialPool.get(serialConfig);
436
+ // 确保只绑定一次事件
437
+ if (curPort._isBindEventInit) {
438
+ return;
439
+ }
440
+ // node.warn("setCallback called for " + curPort.serial.path);
441
+ curPort._isBindEventInit = true;
442
+
443
+ curPort.on('data', function (msgout, sender) {
444
+ if (sender !== node) { return; }
445
+ msgout.status = "OK";
446
+ zsend(msgout, null, null, curPort.serial.path);
447
+ });
448
+ curPort.on('timeout', function (msgout, sender) {
449
+ if (sender !== node) { return; }
450
+ msgout.status = "ERR_TIMEOUT";
451
+ node.status({ fill: "red", shape: "ring", text: "timeout:::" + curPort.serial.path });
452
+ zsend(null, {
453
+ status: "ERR_TIMEOUT",
454
+ msg: msgout,
455
+ port: curPort.serial.path
456
+ }, null, curPort.serial.path);
457
+ });
458
+
459
+ curPort.on('initerror', function (port, retryNum, olderr) {
460
+ zsend(null, {
461
+ status: "ERR_INIT",
462
+ text: `请检查端口是否打开,重试次数${retryNum}`,
463
+ error: olderr,
464
+ port: port
465
+ }, null, curPort.serial.path);
466
+ });
467
+
468
+
469
+ curPort.on('retryerror', function (port, retryNum) {
470
+ curPort._retryNum = 0;
471
+ zsend(null, {
472
+ status: "ERR_retry",
473
+ text: `重试${retryNum}失败`,
474
+ port: port
475
+ }, null, curPort.serial.path);
476
+ });
477
+
478
+ curPort.on('closed', function (port) {
479
+ // node.warn(`串口已关闭:${port}`);
480
+ });
481
+ curPort.on('ready', function (port) {
482
+ // node.warn(`串口已准备好:${port}`);
483
+ });
484
+ }
485
+
486
+ this.on("input", function (msg, send, done) {
487
+ onMsg(msg, send, done);
488
+ })
489
+ this.on("close", function (done) {
490
+ node.totalMsg = null;
491
+ node.successMsg = null;
492
+ node.errorMsg = null;
493
+ try {
494
+ serialPool.closeAll(done, node);
495
+ } catch (error) {
496
+ done();
497
+ }
498
+
499
+ });
500
+ }
501
+ RED.nodes.registerType("zserial batch", SerialBatchRequest);
502
+
503
+
504
+
294
505
  var serialPool = (function () {
295
506
  var connections = {};
296
507
  var _zemitter = new events.EventEmitter();
@@ -315,7 +526,8 @@ module.exports = function (RED) {
315
526
  waitfor = serialConfig.waitfor || '',
316
527
  binoutput = serialConfig.bin || 'false',
317
528
  addchar = serialConfig.addchar || '',
318
- responsetimeout = serialConfig.responsetimeout || 10000;
529
+ responsetimeout = serialConfig.responsetimeout || 10000,
530
+ retryNum = serialConfig.retryNum || 3;
319
531
  var id = port;
320
532
  // just return the connection object if already have one
321
533
  // key is the port (file path)
@@ -356,6 +568,8 @@ module.exports = function (RED) {
356
568
  _isBindEventInit: false,
357
569
  serial: null,
358
570
  _closing: false,
571
+ isopen: false,
572
+ _retryNum: 0,
359
573
  tout: null,
360
574
  queue: [],
361
575
  on: function (a, b) { this._emitter.on(a, b); },
@@ -380,7 +594,7 @@ module.exports = function (RED) {
380
594
  },
381
595
  write: function (m, cb) { this.serial.write(m, cb); },
382
596
  update: function (m, cb) { this.serial.update(m, cb); },
383
- enqueue: function (msg, sender, cb) {
597
+ enqueue: function (msg, sender, cb, encb) {
384
598
  var payload = this.encodePayload(msg.payload);
385
599
  var qobj = {
386
600
  sender: sender,
@@ -392,9 +606,13 @@ module.exports = function (RED) {
392
606
 
393
607
  // If we're enqueing the first message in line,
394
608
  // we shall send it right away
609
+ if (encb) {
610
+ encb(this.queue)
611
+ }
395
612
  if (this.queue.length === 1) {
396
613
  this.writehead();
397
614
  }
615
+
398
616
  },
399
617
  writehead: function () {
400
618
  if (!this.queue.length) { return; }
@@ -405,7 +623,7 @@ module.exports = function (RED) {
405
623
  this.tout = setTimeout(function () {
406
624
  this.tout = null;
407
625
  var msgout = obj.dequeue() || {};
408
- msgout.port = port;
626
+ msgout.port = id;
409
627
  // if we have some leftover stuff, just send it
410
628
  if (i !== 0) {
411
629
  var m = buf.slice(0, i);
@@ -441,6 +659,13 @@ module.exports = function (RED) {
441
659
  obj._emitter.setMaxListeners(50);
442
660
  var olderr = "";
443
661
  var setupSerial = function () {
662
+ obj._retryNum++;
663
+ RED.log.info(obj._retryNum)
664
+ if (obj._retryNum > retryNum) {
665
+ serialPool.zlog("已经重试" + retryNum + "次,请检查串口是否正常!", {});
666
+ obj._emitter.emit('retryerror', id, retryNum);
667
+ return;
668
+ }
444
669
  obj.serial = new SerialPort({
445
670
  path: port,
446
671
  baudRate: baud,
@@ -451,44 +676,48 @@ module.exports = function (RED) {
451
676
  autoOpen: true
452
677
  }, function (err, results) {
453
678
  if (err) {
679
+ obj._emitter.emit('initerror', id, obj._retryNum, err);
454
680
  if (err.toString() !== olderr) {
455
681
  olderr = err.toString();
456
- RED.log.error("Err1:[serialconfig:" + serialConfig.id + "] " + RED._("serial.errors.error", { port: port, error: olderr }), {});
682
+ // RED.log.error("Err1:[serialconfig:" + id + "] " + RED._("serial.errors.error", { port: port, error: olderr }), {});
457
683
  }
458
684
  obj.tout = setTimeout(function () {
459
685
  setupSerial();
460
686
  }, serialReconnectTime);
687
+ } else {
688
+ obj.isopen = true;
461
689
  }
462
- // RED.log.error("init:::::::::::::::::connNumChange");
463
690
  _zemitter.emit('connNumChange', Object.keys(connections).length)
464
691
  });
465
692
  obj.serial.on('error', function (err) {
466
- RED.log.error("Err2:[serialconfig:" + serialConfig.id + "] " + RED._("serial.errors.error", { port: port, error: err.toString() }), {});
467
- obj._emitter.emit('closed');
693
+ obj.isopen = false;
694
+ serialPool.zlog("Err2:[serialconfig:" + id + "] " + RED._("serial.errors.error", { port: port, error: err.toString() }), {});
695
+ obj._emitter.emit('closed', id);
468
696
  if (obj.tout) { clearTimeout(obj.tout); }
469
697
  obj.tout = setTimeout(function () {
470
698
  setupSerial();
471
699
  }, serialReconnectTime);
472
700
  });
473
701
  obj.serial.on('close', function () {
702
+ obj.isopen = false;
474
703
  if (!obj._closing) {
475
704
  if (olderr !== "unexpected") {
476
705
  olderr = "unexpected";
477
- RED.log.error("Err3:[serialconfig:" + serialConfig.id + "] " + RED._("serial.errors.unexpected-close", { port: port }), {});
706
+ serialPool.zlog("Err3:[serialconfig:" + id + "] " + RED._("serial.errors.unexpected-close", { port: port }), {});
478
707
  }
479
- obj._emitter.emit('closed');
708
+ obj._emitter.emit('closed', id);
480
709
  if (obj.tout) { clearTimeout(obj.tout); }
481
710
  obj.tout = setTimeout(function () {
482
711
  setupSerial();
483
712
  }, serialReconnectTime);
484
713
  }
485
714
  else {
486
- obj._emitter.emit('stopped');
715
+ obj._emitter.emit('stopped', id);
487
716
  }
488
717
  });
489
718
  obj.serial.on('open', function () {
490
719
  olderr = "";
491
- RED.log.info("[serialconfig:" + serialConfig.id + "] " + RED._("serial.onopen", { port: port, baud: baud, config: databits + "" + parity.charAt(0).toUpperCase() + stopbits }));
720
+ serialPool.zlog("[serialconfig:" + serialConfig.id + "] " + RED._("serial.onopen", { port: port, baud: baud, config: databits + "" + parity.charAt(0).toUpperCase() + stopbits }));
492
721
  // Set flow control pins if necessary. Must be set all in same command.
493
722
  var flags = {};
494
723
  if (dtr != "none") { flags.dtr = (dtr != "low"); }
@@ -498,11 +727,12 @@ module.exports = function (RED) {
498
727
  if (dtr != "none" || rts != "none" || cts != "none" || dsr != "none") { obj.serial.set(flags); }
499
728
  if (obj.tout) { clearTimeout(obj.tout); obj.tout = null; }
500
729
  //obj.serial.flush();
501
- obj._emitter.emit('ready');
730
+ obj.isopen = true;
731
+ obj._emitter.emit('ready', id);
502
732
  });
503
733
 
504
734
  obj.serial.on('data', function (d) {
505
- RED.log.info("data::::" + d);
735
+ // RED.log.info("data::::" + d);
506
736
  function emitData(data) {
507
737
 
508
738
  if (active === true) {
@@ -583,6 +813,7 @@ module.exports = function (RED) {
583
813
  clearTimeout(connections[port].tout);
584
814
  }
585
815
  connections[port]._closing = true;
816
+ connections[port]._retryNum = 0;
586
817
  connections[port]._isBindOnOutEventInit = false;
587
818
  connections[port]._isBindOnInEventInit = false;
588
819
  connections[port]._isBindEventInit = false;