node-zserial 1.0.2 → 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.2",
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,11 +129,14 @@ module.exports = function (RED) {
129
129
  onMsg(msg, send, done);
130
130
  })
131
131
 
132
-
133
-
134
- function setCallback() {
132
+ function getConnection() {
135
133
  let conns = serialPool.curConnections();
136
134
  let connKeys = Object.keys(conns) || [];
135
+ return { conns, connKeys }
136
+ }
137
+
138
+ function setCallback() {
139
+ let { conns, connKeys } = getConnection();
137
140
  // node.warn(connKeys);
138
141
  node.status({ fill: "green", shape: "dot", text: "当前连接数:" + connKeys.length });
139
142
 
@@ -152,16 +155,19 @@ module.exports = function (RED) {
152
155
  node.send(msgout);
153
156
  });
154
157
  curPort.on('ready', function () {
158
+ let { conns, connKeys } = getConnection();
155
159
  //node.status({ fill: "green", shape: "dot", text: "node-red:common.status.connected" });
156
160
  node.status({ fill: "green", shape: "dot", text: "当前连接数:" + connKeys.length });
157
161
 
158
162
  });
159
163
  curPort.on('closed', function () {
164
+ let { conns, connKeys } = getConnection();
160
165
  //node.status({ fill: "red", shape: "ring", text: "node-red:common.status.not-connected" });
161
166
  node.status({ fill: "green", shape: "dot", text: "当前连接数:" + connKeys.length });
162
167
 
163
168
  });
164
169
  curPort.on('stopped', function () {
170
+ let { conns, connKeys } = getConnection();
165
171
  //node.status({ fill: "grey", shape: "ring", text: "serial.status.stopped" });
166
172
  node.status({ fill: "green", shape: "dot", text: "当前连接数:" + connKeys.length });
167
173
 
@@ -224,14 +230,15 @@ module.exports = function (RED) {
224
230
  }
225
231
  if (msg.hasOwnProperty("flush") && msg.flush === true) { curPort.serial.flush(); }
226
232
  let statusText = `waiting:${curPort.serial.path}`
227
- 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
+
228
237
  curPort.enqueue(msg, node, function (err, res) {
229
238
  if (err) {
230
239
  node.error(err)
231
240
  }
232
241
  });
233
-
234
- setCallback(msg, done);
235
242
  }
236
243
  function setCallback(msg, done) {
237
244
  let curPort = serialPool.get(msg.serialConfig);
@@ -247,7 +254,7 @@ module.exports = function (RED) {
247
254
  // node.warn("对象绑定::"+ node == sender);
248
255
  // serial request will only process incoming data pertaining to its own request (i.e. when it's at the head of the queue)
249
256
  if (sender !== node) { return; }
250
- node.status({ fill: "green", shape: "dot", text: "node-red:common.status.ok" });
257
+ node.status({ fill: "green", shape: "dot", text: "ok:::" + curPort.serial.path });
251
258
  msgout.status = "OK";
252
259
  node.send(msgout);
253
260
  // if (done) done();
@@ -255,18 +262,18 @@ module.exports = function (RED) {
255
262
  curPort.on('timeout', function (msgout, sender) {
256
263
  if (sender !== node) { return; }
257
264
  msgout.status = "ERR_TIMEOUT";
258
- node.status({ fill: "red", shape: "ring", text: "serial.status.timeout" });
265
+ node.status({ fill: "red", shape: "ring", text: "timeout:::" + curPort.serial.path });
259
266
  node.send(msgout);
260
267
  // if (done) done();
261
268
  });
262
269
  curPort.on('ready', function () {
263
- node.status({ fill: "green", shape: "dot", text: "node-red:common.status.connected" });
270
+ node.status({ fill: "green", shape: "dot", text: "connected:::" + curPort.serial.path });
264
271
  });
265
272
  curPort.on('closed', function () {
266
- 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 });
267
274
  });
268
275
  curPort.on('stopped', function () {
269
- node.status({ fill: "grey", shape: "ring", text: "serial.status.stopped" });
276
+ node.status({ fill: "grey", shape: "ring", text: "stopped:::" + curPort.serial.path });
270
277
  });
271
278
  }
272
279
 
@@ -285,6 +292,216 @@ module.exports = function (RED) {
285
292
  }
286
293
  RED.nodes.registerType("zserial request", SerialRequestNode);
287
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
+
288
505
  var serialPool = (function () {
289
506
  var connections = {};
290
507
  var _zemitter = new events.EventEmitter();
@@ -309,7 +526,8 @@ module.exports = function (RED) {
309
526
  waitfor = serialConfig.waitfor || '',
310
527
  binoutput = serialConfig.bin || 'false',
311
528
  addchar = serialConfig.addchar || '',
312
- responsetimeout = serialConfig.responsetimeout || 10000;
529
+ responsetimeout = serialConfig.responsetimeout || 10000,
530
+ retryNum = serialConfig.retryNum || 3;
313
531
  var id = port;
314
532
  // just return the connection object if already have one
315
533
  // key is the port (file path)
@@ -350,6 +568,8 @@ module.exports = function (RED) {
350
568
  _isBindEventInit: false,
351
569
  serial: null,
352
570
  _closing: false,
571
+ isopen: false,
572
+ _retryNum: 0,
353
573
  tout: null,
354
574
  queue: [],
355
575
  on: function (a, b) { this._emitter.on(a, b); },
@@ -374,7 +594,7 @@ module.exports = function (RED) {
374
594
  },
375
595
  write: function (m, cb) { this.serial.write(m, cb); },
376
596
  update: function (m, cb) { this.serial.update(m, cb); },
377
- enqueue: function (msg, sender, cb) {
597
+ enqueue: function (msg, sender, cb, encb) {
378
598
  var payload = this.encodePayload(msg.payload);
379
599
  var qobj = {
380
600
  sender: sender,
@@ -386,9 +606,13 @@ module.exports = function (RED) {
386
606
 
387
607
  // If we're enqueing the first message in line,
388
608
  // we shall send it right away
609
+ if (encb) {
610
+ encb(this.queue)
611
+ }
389
612
  if (this.queue.length === 1) {
390
613
  this.writehead();
391
614
  }
615
+
392
616
  },
393
617
  writehead: function () {
394
618
  if (!this.queue.length) { return; }
@@ -399,7 +623,7 @@ module.exports = function (RED) {
399
623
  this.tout = setTimeout(function () {
400
624
  this.tout = null;
401
625
  var msgout = obj.dequeue() || {};
402
- msgout.port = port;
626
+ msgout.port = id;
403
627
  // if we have some leftover stuff, just send it
404
628
  if (i !== 0) {
405
629
  var m = buf.slice(0, i);
@@ -435,6 +659,13 @@ module.exports = function (RED) {
435
659
  obj._emitter.setMaxListeners(50);
436
660
  var olderr = "";
437
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
+ }
438
669
  obj.serial = new SerialPort({
439
670
  path: port,
440
671
  baudRate: baud,
@@ -445,44 +676,48 @@ module.exports = function (RED) {
445
676
  autoOpen: true
446
677
  }, function (err, results) {
447
678
  if (err) {
679
+ obj._emitter.emit('initerror', id, obj._retryNum, err);
448
680
  if (err.toString() !== olderr) {
449
681
  olderr = err.toString();
450
- 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 }), {});
451
683
  }
452
684
  obj.tout = setTimeout(function () {
453
685
  setupSerial();
454
686
  }, serialReconnectTime);
687
+ } else {
688
+ obj.isopen = true;
455
689
  }
456
- // RED.log.error("init:::::::::::::::::connNumChange");
457
690
  _zemitter.emit('connNumChange', Object.keys(connections).length)
458
691
  });
459
692
  obj.serial.on('error', function (err) {
460
- RED.log.error("Err2:[serialconfig:" + serialConfig.id + "] " + RED._("serial.errors.error", { port: port, error: err.toString() }), {});
461
- 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);
462
696
  if (obj.tout) { clearTimeout(obj.tout); }
463
697
  obj.tout = setTimeout(function () {
464
698
  setupSerial();
465
699
  }, serialReconnectTime);
466
700
  });
467
701
  obj.serial.on('close', function () {
702
+ obj.isopen = false;
468
703
  if (!obj._closing) {
469
704
  if (olderr !== "unexpected") {
470
705
  olderr = "unexpected";
471
- 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 }), {});
472
707
  }
473
- obj._emitter.emit('closed');
708
+ obj._emitter.emit('closed', id);
474
709
  if (obj.tout) { clearTimeout(obj.tout); }
475
710
  obj.tout = setTimeout(function () {
476
711
  setupSerial();
477
712
  }, serialReconnectTime);
478
713
  }
479
714
  else {
480
- obj._emitter.emit('stopped');
715
+ obj._emitter.emit('stopped', id);
481
716
  }
482
717
  });
483
718
  obj.serial.on('open', function () {
484
719
  olderr = "";
485
- 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 }));
486
721
  // Set flow control pins if necessary. Must be set all in same command.
487
722
  var flags = {};
488
723
  if (dtr != "none") { flags.dtr = (dtr != "low"); }
@@ -492,11 +727,12 @@ module.exports = function (RED) {
492
727
  if (dtr != "none" || rts != "none" || cts != "none" || dsr != "none") { obj.serial.set(flags); }
493
728
  if (obj.tout) { clearTimeout(obj.tout); obj.tout = null; }
494
729
  //obj.serial.flush();
495
- obj._emitter.emit('ready');
730
+ obj.isopen = true;
731
+ obj._emitter.emit('ready', id);
496
732
  });
497
733
 
498
734
  obj.serial.on('data', function (d) {
499
- RED.log.info("data::::" + d);
735
+ // RED.log.info("data::::" + d);
500
736
  function emitData(data) {
501
737
 
502
738
  if (active === true) {
@@ -577,6 +813,7 @@ module.exports = function (RED) {
577
813
  clearTimeout(connections[port].tout);
578
814
  }
579
815
  connections[port]._closing = true;
816
+ connections[port]._retryNum = 0;
580
817
  connections[port]._isBindOnOutEventInit = false;
581
818
  connections[port]._isBindOnInEventInit = false;
582
819
  connections[port]._isBindEventInit = false;