node-zserial 1.0.3 → 1.0.5
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 +22 -4
- package/examples/demo.json +216 -99
- package/images/image.png +0 -0
- package/package.json +1 -1
- package/zserial.html +23 -0
- package/zserial.js +253 -22
- package/images/demo.png +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
node-
|
|
1
|
+
node-zserial port
|
|
2
2
|
========================
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
|
|
4
6
|
<a href="http://nodered.org" target="noderedinfo">Node-RED</a> 节点,用于与硬件串口通信。
|
|
5
|
-
|
|
7
|
+
|
|
8
|
+

|
|
6
9
|
|
|
7
10
|
## 安装
|
|
8
11
|
|
|
@@ -63,14 +66,14 @@ node-zserialport
|
|
|
63
66
|
|
|
64
67
|
要控制通信,向控制节点发送 **msg.payload**。
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
{
|
|
67
70
|
"serialport": "/dev/ttyUSB0",
|
|
68
71
|
"serialbaud": 115200,
|
|
69
72
|
"databits": 8,
|
|
70
73
|
"parity": "none",
|
|
71
74
|
"stopbits": 1,
|
|
72
75
|
"enabled": true
|
|
73
|
-
|
|
76
|
+
}
|
|
74
77
|
|
|
75
78
|
可以动态更改串口及其配置。
|
|
76
79
|
|
|
@@ -96,3 +99,18 @@ node-zserialport
|
|
|
96
99
|
|
|
97
100
|
任何输入消息都会导致节点输出当前端口配置。
|
|
98
101
|
|
|
102
|
+
### MAC
|
|
103
|
+
|
|
104
|
+
mac 模拟串口
|
|
105
|
+
|
|
106
|
+
***
|
|
107
|
+
socat -d -d pty,raw,echo=0 pty,raw,echo=0
|
|
108
|
+
|
|
109
|
+
socat -d -d pty,raw,echo=0 pty,raw,echo=0 | socat -d -d -d -d pty,raw,echo=0
|
|
110
|
+
***
|
|
111
|
+
|
|
112
|
+
连接串口
|
|
113
|
+
|
|
114
|
+
***
|
|
115
|
+
screen /dev/ttys003 9600
|
|
116
|
+
***
|
package/examples/demo.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{
|
|
3
3
|
"id": "ac7bf7ec36d6a989",
|
|
4
4
|
"type": "function",
|
|
5
|
-
"z": "
|
|
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":
|
|
15
|
-
"y":
|
|
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": "
|
|
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":
|
|
35
|
-
"y":
|
|
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": "
|
|
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":
|
|
56
|
-
"y":
|
|
54
|
+
"x": 950,
|
|
55
|
+
"y": 240,
|
|
57
56
|
"wires": []
|
|
58
57
|
},
|
|
59
58
|
{
|
|
60
59
|
"id": "2e52a7d5dcba1731",
|
|
61
60
|
"type": "split",
|
|
62
|
-
"z": "
|
|
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":
|
|
72
|
-
"y":
|
|
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": "
|
|
82
|
+
"z": "d83ba3a0e79165f6",
|
|
83
83
|
"name": "窗口配置数组",
|
|
84
|
-
"func": "let serialPorts = [\n {\n serialport:
|
|
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":
|
|
92
|
-
"y":
|
|
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": "
|
|
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":
|
|
111
|
-
"y":
|
|
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": "
|
|
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":
|
|
131
|
-
"y":
|
|
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": "
|
|
140
|
-
"type": "zserial
|
|
141
|
-
"z": "
|
|
142
|
-
"name": "
|
|
143
|
-
"x":
|
|
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
|
-
"
|
|
147
|
+
"c5b2a60e99954c23"
|
|
148
148
|
]
|
|
149
149
|
]
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
|
-
"id": "
|
|
153
|
-
"type": "
|
|
154
|
-
"z": "
|
|
155
|
-
"name": "
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
|
|
160
|
-
|
|
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": "
|
|
163
|
+
"id": "052eea87f99970b0",
|
|
170
164
|
"type": "inject",
|
|
171
|
-
"z": "
|
|
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":
|
|
180
|
-
"y":
|
|
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
|
-
"
|
|
177
|
+
"0e4c242820dcc156"
|
|
206
178
|
]
|
|
207
179
|
]
|
|
208
180
|
},
|
|
209
181
|
{
|
|
210
|
-
"id": "
|
|
182
|
+
"id": "ef3b251330bafa25",
|
|
211
183
|
"type": "zserial closeAll",
|
|
212
|
-
"z": "
|
|
213
|
-
"name": "
|
|
214
|
-
"x":
|
|
215
|
-
"y":
|
|
184
|
+
"z": "d83ba3a0e79165f6",
|
|
185
|
+
"name": "单独关闭",
|
|
186
|
+
"x": 540,
|
|
187
|
+
"y": 540,
|
|
216
188
|
"wires": [
|
|
217
189
|
[]
|
|
218
190
|
]
|
|
219
191
|
},
|
|
220
192
|
{
|
|
221
|
-
"id": "
|
|
193
|
+
"id": "98f8acd5d825b6dd",
|
|
222
194
|
"type": "inject",
|
|
223
|
-
"z": "
|
|
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":
|
|
232
|
-
"y":
|
|
203
|
+
"x": 210,
|
|
204
|
+
"y": 540,
|
|
233
205
|
"wires": [
|
|
234
206
|
[
|
|
235
|
-
"
|
|
207
|
+
"48f42e1d3e51dd37"
|
|
236
208
|
]
|
|
237
209
|
]
|
|
238
210
|
},
|
|
239
211
|
{
|
|
240
|
-
"id": "
|
|
241
|
-
"type": "
|
|
242
|
-
"z": "
|
|
243
|
-
"name": "
|
|
244
|
-
"
|
|
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": "
|
|
268
|
+
"id": "24569a0782518192",
|
|
252
269
|
"type": "inject",
|
|
253
|
-
"z": "
|
|
270
|
+
"z": "d83ba3a0e79165f6",
|
|
254
271
|
"name": "",
|
|
255
272
|
"props": [],
|
|
256
273
|
"repeat": "",
|
|
257
274
|
"crontab": "",
|
|
258
275
|
"once": false,
|
|
259
|
-
"onceDelay":
|
|
276
|
+
"onceDelay": 0.1,
|
|
260
277
|
"topic": "",
|
|
261
|
-
"x":
|
|
278
|
+
"x": 210,
|
|
262
279
|
"y": 400,
|
|
263
280
|
"wires": [
|
|
264
281
|
[
|
|
265
|
-
"
|
|
282
|
+
"8cc9a6e4d6656909"
|
|
266
283
|
]
|
|
267
284
|
]
|
|
268
285
|
},
|
|
269
286
|
{
|
|
270
|
-
"id": "
|
|
287
|
+
"id": "8cc9a6e4d6656909",
|
|
271
288
|
"type": "function",
|
|
272
|
-
"z": "
|
|
273
|
-
"name": "
|
|
274
|
-
"func": "
|
|
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":
|
|
298
|
+
"x": 400,
|
|
282
299
|
"y": 400,
|
|
283
300
|
"wires": [
|
|
284
301
|
[
|
|
285
|
-
"
|
|
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/image.png
ADDED
|
Binary file
|
package/package.json
CHANGED
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:
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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 =
|
|
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:" +
|
|
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
|
-
|
|
467
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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;
|
package/images/demo.png
DELETED
|
Binary file
|