@fa_yoshinobu/node-red-contrib-plc-comm-slmp 0.2.1
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +295 -0
- package/docsrc/assets/README.md +10 -0
- package/docsrc/assets/node-red-slmp.png +0 -0
- package/docsrc/index.md +11 -0
- package/docsrc/maintainer/ARCHITECTURE.md +36 -0
- package/docsrc/user/USER_GUIDE.md +238 -0
- package/docsrc/user/toc.yml +2 -0
- package/docsrc/validation/reports/README.md +15 -0
- package/examples/flows/README.md +24 -0
- package/examples/flows/slmp-array-string.json +185 -0
- package/examples/flows/slmp-basic-read-write.json +185 -0
- package/examples/flows/slmp-control-error.json +211 -0
- package/examples/flows/slmp-demo.json +260 -0
- package/examples/flows/slmp-device-matrix.json +514 -0
- package/examples/flows/slmp-routing.json +118 -0
- package/examples/flows/slmp-udp-read-write.json +185 -0
- package/lib/index.js +6 -0
- package/lib/slmp/client.js +642 -0
- package/lib/slmp/constants.js +121 -0
- package/lib/slmp/core.js +406 -0
- package/lib/slmp/errors.js +21 -0
- package/lib/slmp/high-level.js +911 -0
- package/lib/slmp/index.js +10 -0
- package/nodes/slmp-connection.html +142 -0
- package/nodes/slmp-connection.js +78 -0
- package/nodes/slmp-read.html +274 -0
- package/nodes/slmp-read.js +207 -0
- package/nodes/slmp-write.html +267 -0
- package/nodes/slmp-write.js +275 -0
- package/package.json +53 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.1 - 2026-03-28
|
|
4
|
+
|
|
5
|
+
- move npm package publishing to the scoped name `@fa_yoshinobu/node-red-contrib-plc-comm-slmp`
|
|
6
|
+
- refresh README and user documentation for Flow Library submission, npm badges, and scoped install commands
|
|
7
|
+
|
|
8
|
+
## 0.2.0 - 2026-03-28
|
|
9
|
+
|
|
10
|
+
- add `slmp-connection`, `slmp-read`, and `slmp-write` nodes for binary 3E/4E over TCP and UDP
|
|
11
|
+
- add named address helpers including `,count`, string access, route overrides, and connection control messages
|
|
12
|
+
- add editor validation, example flows, README improvements, and user/maintainer documentation
|
|
13
|
+
- add local test coverage and package dry-run validation
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yoshinobu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Node-RED SLMP Nodes for Mitsubishi PLCs
|
|
2
|
+
|
|
3
|
+
[](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@fa_yoshinobu/node-red-contrib-plc-comm-slmp)
|
|
5
|
+
[](https://www.npmjs.com/package/@fa_yoshinobu/node-red-contrib-plc-comm-slmp)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
Node-RED nodes for Mitsubishi PLC communication over SLMP binary 3E/4E frames.
|
|
15
|
+
|
|
16
|
+
This package uses the same named-device foundation as the SLMP libraries, extended here with Node-RED-friendly count and string forms:
|
|
17
|
+
|
|
18
|
+
- `D100`
|
|
19
|
+
- `D100,10`
|
|
20
|
+
- `D200:F`
|
|
21
|
+
- `D200:F,4`
|
|
22
|
+
- `D300:L`
|
|
23
|
+
- `D50.3`
|
|
24
|
+
- `M1000`
|
|
25
|
+
- `M1000,8`
|
|
26
|
+
- `D100:STR,10`
|
|
27
|
+
- `DSTR100,10`
|
|
28
|
+
|
|
29
|
+
## Quick start
|
|
30
|
+
|
|
31
|
+
1. Install the package into your Node-RED user directory and restart Node-RED.
|
|
32
|
+
2. Add one `slmp-connection` config node and set `host`, `port`, `transport`, `PLC series`, and `frame type`.
|
|
33
|
+
3. Add `slmp-read` for the first smoke test, using a safe address such as `D300`, `D300,4`, or `DSTR320,10`.
|
|
34
|
+
4. When read works, add `slmp-write` and use known-safe test devices before moving to production addresses.
|
|
35
|
+
|
|
36
|
+
If you are working from this repository, import one of the ready-to-run flows under [examples/flows](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/README.md) first. The safest first choices are:
|
|
37
|
+
|
|
38
|
+
- [`slmp-basic-read-write.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-basic-read-write.json) for plain TCP scalar read/write
|
|
39
|
+
- [`slmp-array-string.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-array-string.json) for `,count` and string access
|
|
40
|
+
- [`slmp-device-matrix.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-device-matrix.json) for one-by-one high-level coverage across the matrix catalog
|
|
41
|
+
- [`slmp-udp-read-write.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-udp-read-write.json) for UDP validation
|
|
42
|
+
|
|
43
|
+
## Release information
|
|
44
|
+
|
|
45
|
+
- package name: `@fa_yoshinobu/node-red-contrib-plc-comm-slmp`
|
|
46
|
+
- package version: `0.2.1`
|
|
47
|
+
- npm package: <https://www.npmjs.com/package/@fa_yoshinobu/node-red-contrib-plc-comm-slmp>
|
|
48
|
+
- Node-RED requirement: `>=3.0.0`
|
|
49
|
+
- Node.js requirement: `>=18`
|
|
50
|
+
- changelog: <https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/CHANGELOG.md>
|
|
51
|
+
|
|
52
|
+
Install from npm:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd ~/.node-red
|
|
56
|
+
npm install @fa_yoshinobu/node-red-contrib-plc-comm-slmp
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Install from this repository:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cd ~/.node-red
|
|
63
|
+
npm install /path/to/node-red-contrib-plc-comm-slmp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Legacy note:
|
|
67
|
+
|
|
68
|
+
- the original unscoped `node-red-contrib-plc-comm-slmp@0.2.0` remains on npm, but new releases move to the scoped package name above
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
- [User Guide](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/docsrc/user/USER_GUIDE.md)
|
|
73
|
+
- [Example Flows](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/README.md)
|
|
74
|
+
- [Future Device Support](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/TODO.md)
|
|
75
|
+
- [Maintainer Notes](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/docsrc/maintainer/ARCHITECTURE.md)
|
|
76
|
+
- [Validation Reports Directory](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/tree/main/docsrc/validation/reports)
|
|
77
|
+
- [Documentation Index](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/docsrc/index.md)
|
|
78
|
+
|
|
79
|
+
## Current scope
|
|
80
|
+
|
|
81
|
+
- Binary 3E and 4E frames
|
|
82
|
+
- TCP and UDP transport
|
|
83
|
+
- Reusable `slmp-connection` config node
|
|
84
|
+
- `slmp-read` node powered by `readNamed`
|
|
85
|
+
- `slmp-write` node powered by `writeNamed`
|
|
86
|
+
- typed source selection for literal / `msg` / `flow` / `global` / `env`
|
|
87
|
+
- per-request routing via `msg.target` or configured route sources
|
|
88
|
+
- read output selection for object / array / single value
|
|
89
|
+
- metadata emission selection for `msg.slmp`: `full` / `minimal` / `off`
|
|
90
|
+
- configurable error handling with throw / `msg.error` / second output
|
|
91
|
+
- connection control via `connect` / `disconnect` / `reinitialize` messages
|
|
92
|
+
- editor-side validation for connection ranges, literal addresses, literal updates, and route JSON
|
|
93
|
+
- importable example flow under `examples/flows/`
|
|
94
|
+
- Local tests for codec and high-level helpers
|
|
95
|
+
|
|
96
|
+
Set `frame type` and `PLC series` explicitly for each connection.
|
|
97
|
+
|
|
98
|
+
Validated PLC models:
|
|
99
|
+
|
|
100
|
+
- `FX5UC-32MT/D`
|
|
101
|
+
- `Q06UDVCPU`
|
|
102
|
+
- `R08CPU`
|
|
103
|
+
|
|
104
|
+
## Supported devices
|
|
105
|
+
|
|
106
|
+
Supported bit devices:
|
|
107
|
+
|
|
108
|
+
- `SM`, `X`, `Y`, `M`, `L`, `F`, `V`, `B`
|
|
109
|
+
- `TS`, `TC`, `STS`, `STC`
|
|
110
|
+
- `CS`, `CC`
|
|
111
|
+
- `SB`, `DX`, `DY`
|
|
112
|
+
|
|
113
|
+
Supported word devices:
|
|
114
|
+
|
|
115
|
+
- `SD`, `D`, `W`
|
|
116
|
+
- `TN`, `LTN`, `STN`, `LSTN`
|
|
117
|
+
- `CN`, `LCN`
|
|
118
|
+
- `SW`
|
|
119
|
+
- `Z`
|
|
120
|
+
- `R`, `ZR`, `RD`
|
|
121
|
+
|
|
122
|
+
Address notes:
|
|
123
|
+
|
|
124
|
+
- `X`, `Y`, `B`, `W`, `SB`, `SW`, `DX`, and `DY` use hexadecimal device numbers
|
|
125
|
+
- most other devices use decimal numbers
|
|
126
|
+
- word devices support `.bit`, for example `D50.3`
|
|
127
|
+
- count and string forms work on supported devices, for example `D300,10`, `M1000,8`, and `DSTR320,10`
|
|
128
|
+
- `LTN`, `LSTN`, and `LCN` default to 32-bit current-value access in the high-level nodes
|
|
129
|
+
- future device support candidates such as `LTS`, `LTC`, `LSTS`, `LSTC`, `LCS`, `LCC`, `LZ`, `G`, and `HG` are tracked in the [Future Device Support list](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/TODO.md)
|
|
130
|
+
|
|
131
|
+
## Nodes
|
|
132
|
+
|
|
133
|
+
### `slmp-connection`
|
|
134
|
+
|
|
135
|
+
Holds the transport and SLMP profile settings:
|
|
136
|
+
|
|
137
|
+
- host / port
|
|
138
|
+
- transport: `tcp` or `udp`
|
|
139
|
+
- timeout in milliseconds
|
|
140
|
+
- PLC series: `ql` or `iqr`
|
|
141
|
+
- frame type: `3e` or `4e`
|
|
142
|
+
- target routing fields
|
|
143
|
+
|
|
144
|
+
### `slmp-read`
|
|
145
|
+
|
|
146
|
+
Reads one or more addresses and writes the result to `msg.payload`.
|
|
147
|
+
|
|
148
|
+
Configured addresses can be overridden by:
|
|
149
|
+
|
|
150
|
+
- `msg.addresses` as an array or string
|
|
151
|
+
- `msg.payload` as an array or string
|
|
152
|
+
|
|
153
|
+
Configured source modes:
|
|
154
|
+
|
|
155
|
+
- literal editor text
|
|
156
|
+
- `msg`
|
|
157
|
+
- `flow`
|
|
158
|
+
- `global`
|
|
159
|
+
- `env`
|
|
160
|
+
|
|
161
|
+
Examples:
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
D100
|
|
165
|
+
D100,10
|
|
166
|
+
D200:F
|
|
167
|
+
D200:F,4
|
|
168
|
+
D50.3
|
|
169
|
+
M1000
|
|
170
|
+
M1000,8
|
|
171
|
+
D100:STR,10
|
|
172
|
+
DSTR100,10
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Notes:
|
|
176
|
+
|
|
177
|
+
- `,count` returns an array for numeric and direct-bit reads
|
|
178
|
+
- `:STR,<length>` reads or writes a UTF-8 byte string packed two bytes per word
|
|
179
|
+
- `DSTR100,10` is accepted as a compatibility alias for `D100:STR,10`
|
|
180
|
+
- `LTN`, `LSTN`, and `LCN` use high-level 32-bit current values by default
|
|
181
|
+
- when you send multiple addresses as a string, newline-separated input is the clearest form
|
|
182
|
+
- per-request routing can be supplied as `msg.target`, `msg.slmp.target`, or a configured route source
|
|
183
|
+
- metadata mode can keep full `msg.slmp`, emit only `target` plus `itemCount`, or leave `msg.slmp` unchanged
|
|
184
|
+
- read errors can throw, attach to `msg.error`, or go to a second output
|
|
185
|
+
- output can be object, array, or single value when one address is requested
|
|
186
|
+
- send `msg.connect`, `msg.disconnect`, or `msg.reinitialize` as `true`, or use `msg.topic`, to control the shared connection
|
|
187
|
+
|
|
188
|
+
### `slmp-write`
|
|
189
|
+
|
|
190
|
+
Writes one or more addresses.
|
|
191
|
+
|
|
192
|
+
Preferred dynamic input:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"D100": 42,
|
|
197
|
+
"D100,3": [10, 11, 12],
|
|
198
|
+
"D200:F": 3.14,
|
|
199
|
+
"D200:F,2": [1.25, -2.5],
|
|
200
|
+
"D50.3": true,
|
|
201
|
+
"D100:STR,10": "HELLO"
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Accepted sources:
|
|
206
|
+
|
|
207
|
+
- `msg.updates`
|
|
208
|
+
- `msg.payload`
|
|
209
|
+
- `msg.address` + optional `msg.dtype` + `msg.value`
|
|
210
|
+
- static JSON or `address=value` lines in the editor
|
|
211
|
+
- configured `msg` / `flow` / `global` / `env` sources
|
|
212
|
+
|
|
213
|
+
Write errors can throw, attach to `msg.error`, or go to a second output.
|
|
214
|
+
Send `msg.connect`, `msg.disconnect`, or `msg.reinitialize` to control the shared connection from the write node too.
|
|
215
|
+
Route overrides use the same `target` object shape as reads.
|
|
216
|
+
Metadata mode can keep full `msg.slmp`, emit only `target` plus `itemCount`, or leave `msg.slmp` unchanged.
|
|
217
|
+
|
|
218
|
+
## Route overrides
|
|
219
|
+
|
|
220
|
+
Use a `target` object when one request needs a different route than the shared connection default:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"addresses": ["D300,4", "DSTR320,10"],
|
|
225
|
+
"target": {
|
|
226
|
+
"network": 0,
|
|
227
|
+
"station": 255,
|
|
228
|
+
"moduleIO": "03FF",
|
|
229
|
+
"multidrop": 0
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The editor validates connection ranges, literal address lists, literal update payloads, and literal route JSON before save.
|
|
235
|
+
|
|
236
|
+
## Example flows
|
|
237
|
+
|
|
238
|
+
Read:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"addresses": ["D100", "D100,3", "D200:F", "D200:F,2", "D50.3", "D100:STR,10"]
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Write:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"payload": {
|
|
251
|
+
"D100": 42,
|
|
252
|
+
"D100,3": [10, 11, 12],
|
|
253
|
+
"D50.3": true,
|
|
254
|
+
"D100:STR,10": "HELLO"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Import one of the ready-to-run flows under [examples/flows](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/README.md):
|
|
260
|
+
|
|
261
|
+
- [`slmp-demo.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-demo.json): combined demo
|
|
262
|
+
- [`slmp-basic-read-write.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-basic-read-write.json): scalar, float, and bit read/write over TCP
|
|
263
|
+
- [`slmp-array-string.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-array-string.json): array and string read/write over TCP
|
|
264
|
+
- [`slmp-control-error.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-control-error.json): control messages, `msg` source, and second-output errors
|
|
265
|
+
- [`slmp-device-matrix.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-device-matrix.json): one-by-one high-level read, write, and readback across the matrix catalog with completed-result history, run summary, and JSONL logging in `Node-RED userDir/logs/slmp-device-matrix-<session>.jsonl`
|
|
266
|
+
- [`slmp-routing.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-routing.json): per-request routing with `msg.target`
|
|
267
|
+
- [`slmp-udp-read-write.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-udp-read-write.json): basic UDP read/write
|
|
268
|
+
|
|
269
|
+
Recommended first import:
|
|
270
|
+
|
|
271
|
+
- start with [`slmp-basic-read-write.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-basic-read-write.json) if you only need to confirm a single PLC over TCP
|
|
272
|
+
- use [`slmp-array-string.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-array-string.json) when you want to validate `,count` and string handling immediately
|
|
273
|
+
- use [`slmp-device-matrix.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-device-matrix.json) when you need to step through the matrix catalog one by one from the high-level nodes and keep a persistent verification log
|
|
274
|
+
- use [`slmp-control-error.json`](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/examples/flows/slmp-control-error.json) when you need `msg`-driven addresses, control messages, or second-output error routing
|
|
275
|
+
|
|
276
|
+
## Known limitations
|
|
277
|
+
|
|
278
|
+
- Set `frame type` and `PLC series` explicitly for each connection
|
|
279
|
+
- `.bit,count` is not supported
|
|
280
|
+
- A single client connection keeps requests serialized by default
|
|
281
|
+
- Future high-level device support candidates are tracked in the [Future Device Support list](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/TODO.md)
|
|
282
|
+
|
|
283
|
+
## Development
|
|
284
|
+
|
|
285
|
+
Run the local test suite:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
cmd /c npm.cmd test
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Notes
|
|
292
|
+
|
|
293
|
+
- `.bit` notation is only valid for word devices such as `D50.3`
|
|
294
|
+
- Direct bit devices should be addressed directly as `M1000`, `X1F`, `Y20`
|
|
295
|
+
- Random read batching follows the Python helper layer for batchable word devices
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Assets
|
|
2
|
+
|
|
3
|
+
See also:
|
|
4
|
+
|
|
5
|
+
- [Project README](../../README.md)
|
|
6
|
+
- [Documentation Index](../index.md)
|
|
7
|
+
|
|
8
|
+
Place shared documentation assets for `@fa_yoshinobu/node-red-contrib-plc-comm-slmp` here.
|
|
9
|
+
|
|
10
|
+
- `node-red-slmp.png`: README hero image for the Node-RED SLMP package
|
|
Binary file
|
package/docsrc/index.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Documentation Index
|
|
2
|
+
|
|
3
|
+
Documentation landing page for `@fa_yoshinobu/node-red-contrib-plc-comm-slmp`.
|
|
4
|
+
|
|
5
|
+
- [Project README](../README.md)
|
|
6
|
+
- [Changelog](../CHANGELOG.md)
|
|
7
|
+
- [Future Device Support](../TODO.md)
|
|
8
|
+
- [User Guide](user/USER_GUIDE.md)
|
|
9
|
+
- [Example Flows](../examples/flows/README.md)
|
|
10
|
+
- [Maintainer Notes](maintainer/ARCHITECTURE.md)
|
|
11
|
+
- [Validation Reports](validation/reports/README.md)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Node-RED SLMP Architecture
|
|
2
|
+
|
|
3
|
+
See also:
|
|
4
|
+
|
|
5
|
+
- [Project README](../../README.md)
|
|
6
|
+
- [User Guide](../user/USER_GUIDE.md)
|
|
7
|
+
- [Changelog](../../CHANGELOG.md)
|
|
8
|
+
- [Documentation Index](../index.md)
|
|
9
|
+
|
|
10
|
+
This package has three layers:
|
|
11
|
+
|
|
12
|
+
1. `lib/slmp/core.js`
|
|
13
|
+
Encodes and decodes SLMP frames, devices, and response payloads.
|
|
14
|
+
|
|
15
|
+
2. `lib/slmp/client.js` and `lib/slmp/high-level.js`
|
|
16
|
+
Provide the transport client plus the high-level named read/write helpers used by the nodes.
|
|
17
|
+
|
|
18
|
+
3. `nodes/*.js` and `nodes/*.html`
|
|
19
|
+
Expose the Node-RED config, read, and write nodes.
|
|
20
|
+
|
|
21
|
+
## Request policy
|
|
22
|
+
|
|
23
|
+
Requests are serialized by default on a single client connection, including 4E.
|
|
24
|
+
This matches the behavior observed on the current validation PLC more reliably than assuming multiple in-flight requests on one socket.
|
|
25
|
+
|
|
26
|
+
## High-level behavior
|
|
27
|
+
|
|
28
|
+
- contiguous words and bits are coalesced into block reads when practical
|
|
29
|
+
- sparse word and dword reads use random read
|
|
30
|
+
- writes are batched where the protocol path supports it
|
|
31
|
+
|
|
32
|
+
## Runtime structure
|
|
33
|
+
|
|
34
|
+
- `slmp-connection` owns the reusable client instance
|
|
35
|
+
- `slmp-read` resolves addresses and writes results to `msg.payload`
|
|
36
|
+
- `slmp-write` resolves updates and applies them through `writeNamed`
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# User Guide
|
|
2
|
+
|
|
3
|
+
See also:
|
|
4
|
+
|
|
5
|
+
- [Project README](../../README.md)
|
|
6
|
+
- [Changelog](../../CHANGELOG.md)
|
|
7
|
+
- [Future Device Support](https://github.com/fa-yoshinobu/node-red-contrib-plc-comm-slmp/blob/main/TODO.md)
|
|
8
|
+
- [Documentation Index](../index.md)
|
|
9
|
+
- [Example Flows](../../examples/flows/README.md)
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
`@fa_yoshinobu/node-red-contrib-plc-comm-slmp` provides Node-RED nodes for Mitsubishi PLC communication over binary SLMP 3E/4E.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
1. Install the package into your Node-RED user directory and restart Node-RED.
|
|
18
|
+
2. Create one `slmp-connection` and set `host`, `port`, `transport`, `PLC series`, and `frame type`.
|
|
19
|
+
3. Drop in `slmp-read` and try a safe address such as `D300`, `D300,4`, or `DSTR320,10`.
|
|
20
|
+
4. Once reads work, add `slmp-write` and verify with known-safe test devices.
|
|
21
|
+
|
|
22
|
+
npm package:
|
|
23
|
+
|
|
24
|
+
- <https://www.npmjs.com/package/@fa_yoshinobu/node-red-contrib-plc-comm-slmp>
|
|
25
|
+
|
|
26
|
+
If you are starting from the example flows in this repository, import these in this order:
|
|
27
|
+
|
|
28
|
+
- [`slmp-basic-read-write.json`](../../examples/flows/slmp-basic-read-write.json)
|
|
29
|
+
- [`slmp-array-string.json`](../../examples/flows/slmp-array-string.json)
|
|
30
|
+
- [`slmp-device-matrix.json`](../../examples/flows/slmp-device-matrix.json)
|
|
31
|
+
- [`slmp-control-error.json`](../../examples/flows/slmp-control-error.json)
|
|
32
|
+
- [`slmp-udp-read-write.json`](../../examples/flows/slmp-udp-read-write.json)
|
|
33
|
+
|
|
34
|
+
## Available nodes
|
|
35
|
+
|
|
36
|
+
- `slmp-connection`
|
|
37
|
+
- `slmp-read`
|
|
38
|
+
- `slmp-write`
|
|
39
|
+
|
|
40
|
+
The package also ships importable example flows:
|
|
41
|
+
|
|
42
|
+
- [`slmp-demo.json`](../../examples/flows/slmp-demo.json)
|
|
43
|
+
- [`slmp-basic-read-write.json`](../../examples/flows/slmp-basic-read-write.json)
|
|
44
|
+
- [`slmp-array-string.json`](../../examples/flows/slmp-array-string.json)
|
|
45
|
+
- [`slmp-control-error.json`](../../examples/flows/slmp-control-error.json)
|
|
46
|
+
- [`slmp-device-matrix.json`](../../examples/flows/slmp-device-matrix.json)
|
|
47
|
+
- [`slmp-routing.json`](../../examples/flows/slmp-routing.json)
|
|
48
|
+
- [`slmp-udp-read-write.json`](../../examples/flows/slmp-udp-read-write.json)
|
|
49
|
+
|
|
50
|
+
## Connection settings
|
|
51
|
+
|
|
52
|
+
Configure these explicitly on the connection node:
|
|
53
|
+
|
|
54
|
+
- host
|
|
55
|
+
- port
|
|
56
|
+
- transport: `tcp` or `udp`
|
|
57
|
+
- PLC series: `ql` or `iqr`
|
|
58
|
+
- frame type: `3e` or `4e`
|
|
59
|
+
- route fields: network, station, module I/O, multidrop
|
|
60
|
+
|
|
61
|
+
Validated PLC models:
|
|
62
|
+
|
|
63
|
+
- `FX5UC-32MT/D`
|
|
64
|
+
- `Q06UDVCPU`
|
|
65
|
+
- `R08CPU`
|
|
66
|
+
|
|
67
|
+
## Supported devices
|
|
68
|
+
|
|
69
|
+
Supported bit devices:
|
|
70
|
+
|
|
71
|
+
- `SM`, `X`, `Y`, `M`, `L`, `F`, `V`, `B`
|
|
72
|
+
- `TS`, `TC`, `STS`, `STC`
|
|
73
|
+
- `CS`, `CC`
|
|
74
|
+
- `SB`, `DX`, `DY`
|
|
75
|
+
|
|
76
|
+
Supported word devices:
|
|
77
|
+
|
|
78
|
+
- `SD`, `D`, `W`
|
|
79
|
+
- `TN`, `LTN`, `STN`, `LSTN`
|
|
80
|
+
- `CN`, `LCN`
|
|
81
|
+
- `SW`
|
|
82
|
+
- `Z`
|
|
83
|
+
- `R`, `ZR`, `RD`
|
|
84
|
+
|
|
85
|
+
Address notes:
|
|
86
|
+
|
|
87
|
+
- `X`, `Y`, `B`, `W`, `SB`, `SW`, `DX`, and `DY` use hexadecimal numbering
|
|
88
|
+
- most other devices use decimal numbering
|
|
89
|
+
- word devices support `.bit`, for example `D50.3`
|
|
90
|
+
- count and string forms work on supported devices, for example `D300,10`, `M1000,8`, and `DSTR320,10`
|
|
91
|
+
- `LTN`, `LSTN`, and `LCN` default to 32-bit current-value access in the high-level nodes
|
|
92
|
+
- future device support candidates such as `LTS`, `LTC`, `LSTS`, `LSTC`, `LCS`, `LCC`, `LZ`, `G`, and `HG` are tracked in [`TODO.md`](../../TODO.md)
|
|
93
|
+
|
|
94
|
+
## Address model
|
|
95
|
+
|
|
96
|
+
The high-level address grammar keeps the same named-device foundation as the SLMP Python and .NET libraries, then extends it for Node-RED count and string inputs:
|
|
97
|
+
|
|
98
|
+
- `D100`
|
|
99
|
+
- `D100,10`
|
|
100
|
+
- `D200:F`
|
|
101
|
+
- `D200:F,4`
|
|
102
|
+
- `D300:L`
|
|
103
|
+
- `D50.3`
|
|
104
|
+
- `M1000`
|
|
105
|
+
- `M1000,8`
|
|
106
|
+
- `D100:STR,10`
|
|
107
|
+
- `DSTR100,10`
|
|
108
|
+
|
|
109
|
+
Rules:
|
|
110
|
+
|
|
111
|
+
- `,count` returns an array for direct-bit, word, and DWord reads
|
|
112
|
+
- `:STR,<length>` reads or writes a UTF-8 byte string packed two bytes per word
|
|
113
|
+
- `DSTR100,10` is accepted as a compatibility alias for `D100:STR,10`
|
|
114
|
+
- `.bit` stays scalar-only, so `.bit,count` is not supported
|
|
115
|
+
- `LTN`, `LSTN`, and `LCN` use high-level 32-bit current values by default
|
|
116
|
+
|
|
117
|
+
## Dynamic inputs
|
|
118
|
+
|
|
119
|
+
Read accepts:
|
|
120
|
+
|
|
121
|
+
- `msg.addresses`
|
|
122
|
+
- `msg.payload`
|
|
123
|
+
- `msg.target` or `msg.slmp.target` for per-request routing
|
|
124
|
+
|
|
125
|
+
Configured source modes:
|
|
126
|
+
|
|
127
|
+
- literal editor text
|
|
128
|
+
- `msg`
|
|
129
|
+
- `flow`
|
|
130
|
+
- `global`
|
|
131
|
+
- `env`
|
|
132
|
+
|
|
133
|
+
When a read input is a string, newline-separated addresses are the clearest form:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
D100
|
|
137
|
+
D100,10
|
|
138
|
+
D200:F,4
|
|
139
|
+
D100:STR,10
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Write accepts:
|
|
143
|
+
|
|
144
|
+
- `msg.updates`
|
|
145
|
+
- `msg.payload`
|
|
146
|
+
- `msg.address` with optional `msg.dtype` and `msg.value`
|
|
147
|
+
- `msg.target` or `msg.slmp.target` for per-request routing
|
|
148
|
+
- configured `msg` / `flow` / `global` / `env` sources
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"D100": 42,
|
|
155
|
+
"D100,3": [10, 11, 12],
|
|
156
|
+
"D200:F,2": [1.25, -2.5],
|
|
157
|
+
"M1000,4": [true, false, true, false],
|
|
158
|
+
"D100:STR,10": "HELLO"
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Output and errors
|
|
163
|
+
|
|
164
|
+
Read output modes:
|
|
165
|
+
|
|
166
|
+
- `object`
|
|
167
|
+
- `array`
|
|
168
|
+
- `value` when exactly one address is requested
|
|
169
|
+
|
|
170
|
+
Metadata modes:
|
|
171
|
+
|
|
172
|
+
- `full`: emit `addresses` or `updates`, connection profile, and effective target in `msg.slmp`
|
|
173
|
+
- `minimal`: emit only the effective `target`, `itemCount`, and `metadataMode` in `msg.slmp`
|
|
174
|
+
- `off`: leave `msg.slmp` unchanged
|
|
175
|
+
|
|
176
|
+
Read and write error modes:
|
|
177
|
+
|
|
178
|
+
- throw
|
|
179
|
+
- attach the error to `msg.error`
|
|
180
|
+
- emit the failed message on the second output
|
|
181
|
+
|
|
182
|
+
## Per-request routing
|
|
183
|
+
|
|
184
|
+
Use a `target` object when one read or write must override the connection node route:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"target": {
|
|
189
|
+
"network": 0,
|
|
190
|
+
"station": 255,
|
|
191
|
+
"moduleIO": "03FF",
|
|
192
|
+
"multidrop": 0
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
You can supply that object through:
|
|
198
|
+
|
|
199
|
+
- `msg.target`
|
|
200
|
+
- `msg.slmp.target`
|
|
201
|
+
- a configured route source using literal JSON, `msg`, `flow`, `global`, or `env`
|
|
202
|
+
|
|
203
|
+
## Connection control
|
|
204
|
+
|
|
205
|
+
Send any of these to `slmp-read` or `slmp-write`:
|
|
206
|
+
|
|
207
|
+
- `msg.connect = true`
|
|
208
|
+
- `msg.disconnect = true`
|
|
209
|
+
- `msg.reinitialize = true`
|
|
210
|
+
- or `msg.topic = "connect" | "disconnect" | "reinitialize"`
|
|
211
|
+
|
|
212
|
+
## Example flows
|
|
213
|
+
|
|
214
|
+
Import one of these into Node-RED, then update the connection host, port, transport, and safe device addresses before deploy:
|
|
215
|
+
|
|
216
|
+
- [`slmp-demo.json`](../../examples/flows/slmp-demo.json): combined demo
|
|
217
|
+
- [`slmp-basic-read-write.json`](../../examples/flows/slmp-basic-read-write.json): scalar, float, and bit read/write over TCP
|
|
218
|
+
- [`slmp-array-string.json`](../../examples/flows/slmp-array-string.json): array and string read/write over TCP
|
|
219
|
+
- [`slmp-control-error.json`](../../examples/flows/slmp-control-error.json): control messages, configured `msg` source, and second-output errors
|
|
220
|
+
- [`slmp-device-matrix.json`](../../examples/flows/slmp-device-matrix.json): one-by-one high-level read, write, and readback across the matrix catalog with completed-result history, run summary, and JSONL logging under `Node-RED userDir/logs/slmp-device-matrix-<session>.jsonl`
|
|
221
|
+
- [`slmp-routing.json`](../../examples/flows/slmp-routing.json): per-request routing with `msg.target`
|
|
222
|
+
- [`slmp-udp-read-write.json`](../../examples/flows/slmp-udp-read-write.json): basic UDP read/write
|
|
223
|
+
|
|
224
|
+
Recommended first import:
|
|
225
|
+
|
|
226
|
+
- start with [`slmp-basic-read-write.json`](../../examples/flows/slmp-basic-read-write.json) for plain TCP smoke testing
|
|
227
|
+
- move to [`slmp-array-string.json`](../../examples/flows/slmp-array-string.json) when you want to validate `,count` and string access
|
|
228
|
+
- move to [`slmp-device-matrix.json`](../../examples/flows/slmp-device-matrix.json) when you want one-by-one high-level coverage across the matrix catalog and a persistent verification log
|
|
229
|
+
- use [`slmp-control-error.json`](../../examples/flows/slmp-control-error.json) for `msg`-driven addresses, control messages, and second-output error routing
|
|
230
|
+
|
|
231
|
+
## Notes
|
|
232
|
+
|
|
233
|
+
- `.bit` notation is only valid on word devices such as `D50.3`
|
|
234
|
+
- `.bit,count` is not supported
|
|
235
|
+
- direct bit devices should be addressed directly as `M1000`, `X1F`, or `Y20`
|
|
236
|
+
- a single client connection keeps requests serialized by default
|
|
237
|
+
- read/write errors can throw, attach to `msg.error`, or go to a second output
|
|
238
|
+
- the editor validates connection ranges, literal address lists, literal update payloads, and literal route JSON before save
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Validation Reports
|
|
2
|
+
|
|
3
|
+
See also:
|
|
4
|
+
|
|
5
|
+
- [Project README](../../../README.md)
|
|
6
|
+
- [User Guide](../../user/USER_GUIDE.md)
|
|
7
|
+
- [Documentation Index](../../index.md)
|
|
8
|
+
|
|
9
|
+
Place captured validation reports for `@fa_yoshinobu/node-red-contrib-plc-comm-slmp` in this directory.
|
|
10
|
+
|
|
11
|
+
Typical content:
|
|
12
|
+
|
|
13
|
+
- hardware verification notes
|
|
14
|
+
- benchmark summaries
|
|
15
|
+
- regression validation results
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Example Flows
|
|
2
|
+
|
|
3
|
+
See also:
|
|
4
|
+
|
|
5
|
+
- [Project README](../../README.md)
|
|
6
|
+
- [User Guide](../../docsrc/user/USER_GUIDE.md)
|
|
7
|
+
- [Documentation Index](../../docsrc/index.md)
|
|
8
|
+
|
|
9
|
+
Import one of these files into Node-RED, then update the connection host, port, transport, and safe device addresses for the target PLC before deploy.
|
|
10
|
+
|
|
11
|
+
Start here:
|
|
12
|
+
|
|
13
|
+
- [`slmp-basic-read-write.json`](slmp-basic-read-write.json) for the first TCP smoke test
|
|
14
|
+
- [`slmp-array-string.json`](slmp-array-string.json) when you want to check `,count` and `DSTR`
|
|
15
|
+
- [`slmp-device-matrix.json`](slmp-device-matrix.json) when you want one-by-one high-level coverage across the matrix catalog with persistent JSONL logging, pending tracking, and timeout detection
|
|
16
|
+
- [`slmp-udp-read-write.json`](slmp-udp-read-write.json) when you need UDP first
|
|
17
|
+
|
|
18
|
+
- [`slmp-demo.json`](slmp-demo.json): combined demo with control messages, array read, string read, and error second output
|
|
19
|
+
- [`slmp-basic-read-write.json`](slmp-basic-read-write.json): basic TCP read and write with scalar, float, and word-bit examples
|
|
20
|
+
- [`slmp-array-string.json`](slmp-array-string.json): TCP array and string read/write examples using `,count` and `DSTR`
|
|
21
|
+
- [`slmp-control-error.json`](slmp-control-error.json): connection control, configured `msg` source, and second-output error routing
|
|
22
|
+
- [`slmp-device-matrix.json`](slmp-device-matrix.json): one-by-one high-level read, write, and readback across the matrix catalog with completed-result history, run summary, and `logs/slmp-device-matrix-<session>.jsonl`
|
|
23
|
+
- [`slmp-routing.json`](slmp-routing.json): per-request routing using `msg.lookup` and `msg.target`
|
|
24
|
+
- [`slmp-udp-read-write.json`](slmp-udp-read-write.json): basic UDP read and write example
|