ts-communication 1.0.0 → 1.1.0

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.
Files changed (65) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +246 -14
  3. package/dist/Invt/InvtModbusTcp.d.ts +88 -0
  4. package/dist/Invt/InvtModbusTcp.js +255 -0
  5. package/dist/XCommunication.d.ts +18 -0
  6. package/dist/XCommunication.js +29 -0
  7. package/dist/ab/AbEtherNetIp.d.ts +1 -0
  8. package/dist/ab/AbEtherNetIp.js +2 -0
  9. package/dist/core/CommunicationLock.d.ts +88 -0
  10. package/dist/core/CommunicationLock.js +156 -0
  11. package/dist/core/Core.d.ts +27 -1
  12. package/dist/core/Core.js +375 -71
  13. package/dist/core/DeviceSerialPort.d.ts +64 -0
  14. package/dist/core/DeviceSerialPort.js +283 -0
  15. package/dist/core/DeviceUdpNet.d.ts +56 -0
  16. package/dist/core/DeviceUdpNet.js +307 -0
  17. package/dist/core/INetMessage.d.ts +145 -0
  18. package/dist/core/INetMessage.js +240 -0
  19. package/dist/debug/PingTest.d.ts +11 -0
  20. package/dist/debug/PingTest.js +59 -0
  21. package/dist/debug/tcpClient.d.ts +11 -0
  22. package/dist/debug/tcpClient.js +116 -0
  23. package/dist/debug/tcpServer.d.ts +12 -0
  24. package/dist/debug/tcpServer.js +102 -0
  25. package/dist/delta/DeltaTcpNet.d.ts +65 -0
  26. package/dist/delta/DeltaTcpNet.js +346 -0
  27. package/dist/ge/GeSRTPNet.d.ts +49 -0
  28. package/dist/ge/GeSRTPNet.js +337 -0
  29. package/dist/inovance/InovanceEasyNet.d.ts +8 -0
  30. package/dist/inovance/InovanceEasyNet.js +103 -0
  31. package/dist/inovance/InovanceSerial.d.ts +55 -0
  32. package/dist/inovance/InovanceSerial.js +145 -0
  33. package/dist/inovance/InovanceSerialOverTcp.d.ts +39 -0
  34. package/dist/inovance/InovanceSerialOverTcp.js +172 -0
  35. package/dist/inovance/InovanceTcpNet.d.ts +2 -4
  36. package/dist/inovance/InovanceTcpNet.js +40 -13
  37. package/dist/melsec/MelsecMcAsciiNet.d.ts +49 -0
  38. package/dist/melsec/MelsecMcAsciiNet.js +196 -0
  39. package/dist/melsec/MelsecMcAsciiUdp.d.ts +54 -0
  40. package/dist/melsec/MelsecMcAsciiUdp.js +204 -0
  41. package/dist/melsec/MelsecMcNet.d.ts +1 -8
  42. package/dist/melsec/MelsecMcNet.js +4 -14
  43. package/dist/melsec/MelsecMcUdp.d.ts +52 -0
  44. package/dist/melsec/MelsecMcUdp.js +191 -0
  45. package/dist/modbus/ModbusAscii.d.ts +24 -3
  46. package/dist/modbus/ModbusAscii.js +109 -3
  47. package/dist/modbus/ModbusAsciiOverTcp.d.ts +21 -3
  48. package/dist/modbus/ModbusAsciiOverTcp.js +67 -3
  49. package/dist/modbus/ModbusRtu.d.ts +101 -13
  50. package/dist/modbus/ModbusRtu.js +355 -21
  51. package/dist/modbus/ModbusRtuOverTcp.d.ts +23 -3
  52. package/dist/modbus/ModbusRtuOverTcp.js +68 -3
  53. package/dist/modbus/ModbusTcpNet.d.ts +16 -3
  54. package/dist/modbus/ModbusTcpNet.js +192 -60
  55. package/dist/modbus/ModbusUdpNet.d.ts +26 -3
  56. package/dist/modbus/ModbusUdpNet.js +125 -2
  57. package/dist/omron/OmronFinsNet.d.ts +1 -2
  58. package/dist/omron/OmronFinsNet.js +210 -69
  59. package/dist/omron/OmronFinsUdp.d.ts +41 -0
  60. package/dist/omron/OmronFinsUdp.js +146 -0
  61. package/dist/siemens/SiemensS7Net.d.ts +6 -0
  62. package/dist/siemens/SiemensS7Net.js +45 -6
  63. package/dist/xinjie/XinJETcpNet.d.ts +18 -0
  64. package/dist/xinjie/XinJETcpNet.js +106 -0
  65. package/package.json +16 -3
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OmronFinsUdp = exports.OmronFinsNet = exports.OmronPlcType = void 0;
3
+ exports.OmronFinsNet = exports.OmronPlcType = void 0;
4
4
  exports.parseOmronAddress = parseOmronAddress;
5
5
  const Core_1 = require("../core/Core");
6
6
  var OmronPlcType;
@@ -8,23 +8,40 @@ var OmronPlcType;
8
8
  OmronPlcType[OmronPlcType["CSCJ"] = 1] = "CSCJ";
9
9
  OmronPlcType[OmronPlcType["CV"] = 2] = "CV";
10
10
  })(OmronPlcType || (exports.OmronPlcType = OmronPlcType = {}));
11
- const area = { D: [0x02, 0x82], DM: [0x02, 0x82], C: [0x30, 0xB0], CIO: [0x30, 0xB0], W: [0x31, 0xB1], WR: [0x31, 0xB1], H: [0x32, 0xB2], HR: [0x32, 0xB2], A: [0x33, 0xB3], AR: [0x33, 0xB3], E: [0x20, 0xA0], EM: [0x20, 0xA0], TIM: [0x09, 0x89], CNT: [0x09, 0x89] };
12
- function parseOmronAddress(input) { try {
13
- const m = input.trim().match(/^([A-Za-z]+)([0-9A-Fa-f]+)(?:\.([0-9]+))?$/);
14
- if (!m)
15
- throw new Error(`Invalid Omron address: ${input}`);
16
- const key = m[1].toUpperCase(), a = area[key];
17
- if (!a)
18
- throw new Error(`Unsupported Omron address: ${input}`);
19
- const word = Number.parseInt(m[2], key === 'E' || key === 'EM' ? 16 : 10);
20
- const bit = Number(m[3] ?? 0);
21
- if (bit < 0 || bit > 15)
22
- throw new Error('Invalid bit index');
23
- return Core_1.OperateResult.CreateSuccessResult({ BitCode: a[0], WordCode: a[1], AddressStart: word * 16 + bit });
11
+ const area = {
12
+ D: [0x02, 0x82],
13
+ DM: [0x02, 0x82],
14
+ C: [0x30, 0xB0],
15
+ CIO: [0x30, 0xB0],
16
+ W: [0x31, 0xB1],
17
+ WR: [0x31, 0xB1],
18
+ H: [0x32, 0xB2],
19
+ HR: [0x32, 0xB2],
20
+ A: [0x33, 0xB3],
21
+ AR: [0x33, 0xB3],
22
+ E: [0x20, 0xA0],
23
+ EM: [0x20, 0xA0],
24
+ TIM: [0x09, 0x89],
25
+ CNT: [0x09, 0x89]
26
+ };
27
+ function parseOmronAddress(input) {
28
+ try {
29
+ const m = input.trim().match(/^([A-Za-z]+)([0-9A-Fa-f]+)(?:\.([0-9]+))?$/);
30
+ if (!m)
31
+ throw new Error(`Invalid Omron address: ${input}`);
32
+ const key = m[1].toUpperCase(), a = area[key];
33
+ if (!a)
34
+ throw new Error(`Unsupported Omron address: ${input}`);
35
+ const word = Number.parseInt(m[2], key === 'E' || key === 'EM' ? 16 : 10);
36
+ const bit = Number(m[3] ?? 0);
37
+ if (bit < 0 || bit > 15)
38
+ throw new Error('Invalid bit index');
39
+ return Core_1.OperateResult.CreateSuccessResult({ BitCode: a[0], WordCode: a[1], AddressStart: word * 16 + bit });
40
+ }
41
+ catch (e) {
42
+ return new Core_1.OperateResult(e.message);
43
+ }
24
44
  }
25
- catch (e) {
26
- return new Core_1.OperateResult(e.message);
27
- } }
28
45
  class OmronFinsNet extends Core_1.DeviceClient {
29
46
  ICF = 0x80;
30
47
  RSV = 0;
@@ -39,57 +56,181 @@ class OmronFinsNet extends Core_1.DeviceClient {
39
56
  ReadSplits = 500;
40
57
  PlcType = OmronPlcType.CSCJ;
41
58
  ReceiveUntilEmpty = false;
42
- constructor(ipAddress, port = 9600) { super(ipAddress, ipAddress === undefined ? undefined : port); this.Port = ipAddress === undefined ? 5000 : port; this.ByteTransform = new Core_1.ByteTransform(Core_1.DataFormat.CDAB); this.ByteTransform.IsStringReverseByteWord = true; }
43
- pack(core) { const h = Buffer.alloc(26 + core.length); Buffer.from('FINS').copy(h); h.writeUInt32BE(18 + core.length, 4); h[11] = 2; h[16] = this.ICF; h[17] = this.RSV; h[18] = this.GCT; h[19] = this.DNA; h[20] = this.DA1; h[21] = this.DA2; h[22] = this.SNA; h[23] = this.SA1; h[24] = this.SA2; this.SID = (this.SID + 1) & 255; h[25] = this.SID; core.copy(h, 26); return h; }
44
- async transact(core) { const frame = this.pack(core); const r = await this.request(frame, data => { if (data.length < 30)
45
- throw new Error('incomplete FINS response'); const n = data.readUInt32BE(4); if (data.length < 8 + n)
46
- throw new Error('incomplete FINS response'); return data.subarray(0, 8 + n); }); if (!r.IsSuccess)
47
- return r; const b = r.Content; const status = b.readUInt32BE(12); if (status !== 0)
48
- return new Core_1.OperateResult(`FINS TCP error ${status}`, status); const end = b.length; return Core_1.OperateResult.CreateSuccessResult(b.subarray(30, end)); }
49
- command(address, length, isBit = false, write) { const a = parseOmronAddress(address); if (!a.IsSuccess)
50
- return Core_1.OperateResult.CreateFailedResult(a); const d = a.Content; const c = Buffer.alloc(8 + (write?.length ?? 0)); c[0] = 1; c[1] = write ? 2 : 1; c[2] = isBit ? d.BitCode : d.WordCode; c[3] = (d.AddressStart >> 16) & 255; c[4] = (d.AddressStart >> 8) & 255; c[5] = d.AddressStart & 255; c[6] = (length >> 8) & 255; c[7] = length & 255; if (write)
51
- write.copy(c, 8); return Core_1.OperateResult.CreateSuccessResult(c); }
52
- async Read(address, length) { const c = this.command(address, length, false); if (!c.IsSuccess)
53
- return c; return this.transact(c.Content); }
54
- async ReadBool(address, length) { const n = length ?? 1, c = this.command(address, n, true); if (!c.IsSuccess)
55
- return Core_1.OperateResult.CreateFailedResult(c); const r = await this.transact(c.Content); if (!r.IsSuccess)
56
- return Core_1.OperateResult.CreateFailedResult(r); const vals = Array.from(r.Content, x => x !== 0).slice(0, n); return Core_1.OperateResult.CreateSuccessResult(length === undefined ? vals[0] : vals); }
57
- async typedRead(address, length, width, fn) { const r = await this.Read(address, length * width / 2); if (!r.IsSuccess)
58
- return Core_1.OperateResult.CreateFailedResult(r); const vals = Array.from({ length }, (_, i) => fn(r.Content, i * width)); return Core_1.OperateResult.CreateSuccessResult(length === 1 ? vals[0] : vals); }
59
- async ReadInt16(a, l) { return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransInt16(b, o)); }
60
- async ReadUInt16(a, l) { return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransUInt16(b, o)); }
61
- async ReadInt32(a, l) { return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransInt32(b, o)); }
62
- async ReadUInt32(a, l) { return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransUInt32(b, o)); }
63
- async ReadFloat(a, l) { return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransSingle(b, o)); }
64
- async ReadDouble(a, l) { return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransDouble(b, o)); }
65
- async ReadInt64(a, l) { return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransInt64(b, o)); }
66
- async ReadUInt64(a, l) { return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransUInt64(b, o)); }
67
- async Write(address, value) { const isBit = typeof value === 'boolean' || (Array.isArray(value) && typeof value[0] === 'boolean'); let data; if (typeof value === 'boolean')
68
- data = Buffer.from([value ? 1 : 0]);
69
- else if (typeof value === 'string')
70
- data = Buffer.from(value);
71
- else if (Buffer.isBuffer(value))
72
- data = value;
73
- else if (Array.isArray(value) && typeof value[0] === 'boolean')
74
- data = Buffer.from(value.map(x => x ? 1 : 0));
75
- else
76
- data = this.ByteTransform.TransByte(value, 2); const c = this.command(address, isBit ? data.length : data.length / 2, isBit, data); if (!c.IsSuccess)
77
- return c; const r = await this.transact(c.Content); return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r; }
78
- WriteByte(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Byte(v))); }
79
- WriteInt16(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int16(v))); }
80
- WriteUInt16(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt16(v))); }
81
- WriteInt32(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int32(v))); }
82
- WriteUInt32(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt32(v))); }
83
- WriteFloat(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Float(v))); }
84
- WriteDouble(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Double(v))); }
85
- WriteInt64(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int64(v))); }
86
- WriteUInt64(a, v) { return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt64(v))); }
87
- async Run() { const r = await this.transact(Buffer.from([4, 1, 255, 255, 4])); return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r; }
88
- async Stop() { const r = await this.transact(Buffer.from([4, 2, 255, 255])); return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r; }
89
- async ConnectServerAsync() { return this.ConnectServer(); }
90
- async ConnectCloseAsync() { return this.ConnectClose(); }
59
+ constructor(ipAddress, port = 9600) {
60
+ super(ipAddress, ipAddress === undefined ? undefined : port);
61
+ this.Port = ipAddress === undefined ? 5000 : port;
62
+ this.ByteTransform = new Core_1.ByteTransform(Core_1.DataFormat.CDAB);
63
+ this.ByteTransform.IsStringReverseByteWord = true;
64
+ }
65
+ pack(core) {
66
+ const h = Buffer.alloc(26 + core.length);
67
+ Buffer.from('FINS').copy(h);
68
+ h.writeUInt32BE(18 + core.length, 4);
69
+ h[11] = 2;
70
+ h[16] = this.ICF;
71
+ h[17] = this.RSV;
72
+ h[18] = this.GCT;
73
+ h[19] = this.DNA;
74
+ h[20] = this.DA1;
75
+ h[21] = this.DA2;
76
+ h[22] = this.SNA;
77
+ h[23] = this.SA1;
78
+ h[24] = this.SA2;
79
+ this.SID = (this.SID + 1) & 255;
80
+ h[25] = this.SID;
81
+ core.copy(h, 26);
82
+ return h;
83
+ }
84
+ async transact(core) {
85
+ const frame = this.pack(core);
86
+ const r = await this.request(frame, data => {
87
+ if (data.length < 30)
88
+ throw new Error('incomplete FINS response');
89
+ const n = data.readUInt32BE(4);
90
+ if (data.length < 8 + n)
91
+ throw new Error('incomplete FINS response');
92
+ return data.subarray(0, 8 + n);
93
+ });
94
+ if (!r.IsSuccess)
95
+ return r;
96
+ const b = r.Content;
97
+ const status = b.readUInt32BE(12);
98
+ if (status !== 0)
99
+ return new Core_1.OperateResult(`FINS TCP error ${status}`, status);
100
+ const end = b.length;
101
+ return Core_1.OperateResult.CreateSuccessResult(b.subarray(30, end));
102
+ }
103
+ command(address, length, isBit = false, write) {
104
+ const a = parseOmronAddress(address);
105
+ if (!a.IsSuccess)
106
+ return Core_1.OperateResult.CreateFailedResult(a);
107
+ const d = a.Content;
108
+ const c = Buffer.alloc(8 + (write?.length ?? 0));
109
+ c[0] = 1;
110
+ c[1] = write ? 2 : 1;
111
+ c[2] = isBit ? d.BitCode : d.WordCode;
112
+ c[3] = (d.AddressStart >> 16) & 255;
113
+ c[4] = (d.AddressStart >> 8) & 255;
114
+ c[5] = d.AddressStart & 255;
115
+ c[6] = (length >> 8) & 255;
116
+ c[7] = length & 255;
117
+ if (write)
118
+ write.copy(c, 8);
119
+ return Core_1.OperateResult.CreateSuccessResult(c);
120
+ }
121
+ async Read(address, length) {
122
+ const c = this.command(address, length, false);
123
+ if (!c.IsSuccess)
124
+ return c;
125
+ return this.transact(c.Content);
126
+ }
127
+ // FINS 字符串默认使用 UTF-8 编码。
128
+ async ReadString(address, length, encoding = 'utf8') {
129
+ const result = await this.Read(address, length);
130
+ return result.IsSuccess
131
+ ? Core_1.OperateResult.CreateSuccessResult(this.ByteTransform.TransString(result.Content, encoding))
132
+ : Core_1.OperateResult.CreateFailedResult(result);
133
+ }
134
+ async ReadBool(address, length) {
135
+ const n = length ?? 1, c = this.command(address, n, true);
136
+ if (!c.IsSuccess)
137
+ return Core_1.OperateResult.CreateFailedResult(c);
138
+ const r = await this.transact(c.Content);
139
+ if (!r.IsSuccess)
140
+ return Core_1.OperateResult.CreateFailedResult(r);
141
+ const vals = Array.from(r.Content, x => x !== 0).slice(0, n);
142
+ return Core_1.OperateResult.CreateSuccessResult(length === undefined ? vals[0] : vals);
143
+ }
144
+ async typedRead(address, length, width, fn) {
145
+ const r = await this.Read(address, length * width / 2);
146
+ if (!r.IsSuccess)
147
+ return Core_1.OperateResult.CreateFailedResult(r);
148
+ const vals = Array.from({ length }, (_, i) => fn(r.Content, i * width));
149
+ return Core_1.OperateResult.CreateSuccessResult(length === 1 ? vals[0] : vals);
150
+ }
151
+ async ReadInt16(a, l) {
152
+ return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransInt16(b, o));
153
+ }
154
+ async ReadUInt16(a, l) {
155
+ return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransUInt16(b, o));
156
+ }
157
+ async ReadInt32(a, l) {
158
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransInt32(b, o));
159
+ }
160
+ async ReadUInt32(a, l) {
161
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransUInt32(b, o));
162
+ }
163
+ async ReadFloat(a, l) {
164
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransSingle(b, o));
165
+ }
166
+ async ReadDouble(a, l) {
167
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransDouble(b, o));
168
+ }
169
+ async ReadInt64(a, l) {
170
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransInt64(b, o));
171
+ }
172
+ async ReadUInt64(a, l) {
173
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransUInt64(b, o));
174
+ }
175
+ async Write(address, value) {
176
+ const isBit = typeof value === 'boolean' || (Array.isArray(value) && typeof value[0] === 'boolean');
177
+ let data;
178
+ if (typeof value === 'boolean')
179
+ data = Buffer.from([value ? 1 : 0]);
180
+ else if (typeof value === 'string')
181
+ data = Buffer.from(value);
182
+ else if (Buffer.isBuffer(value))
183
+ data = value;
184
+ else if (Array.isArray(value) && typeof value[0] === 'boolean')
185
+ data = Buffer.from(value.map(x => x ? 1 : 0));
186
+ else
187
+ data = this.ByteTransform.TransByte(value, 2);
188
+ const c = this.command(address, isBit ? data.length : data.length / 2, isBit, data);
189
+ if (!c.IsSuccess)
190
+ return c;
191
+ const r = await this.transact(c.Content);
192
+ return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r;
193
+ }
194
+ WriteByte(a, v) {
195
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Byte(v)));
196
+ }
197
+ WriteInt16(a, v) {
198
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int16(v)));
199
+ }
200
+ WriteUInt16(a, v) {
201
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt16(v)));
202
+ }
203
+ WriteInt32(a, v) {
204
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int32(v)));
205
+ }
206
+ WriteUInt32(a, v) {
207
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt32(v)));
208
+ }
209
+ WriteFloat(a, v) {
210
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Float(v)));
211
+ }
212
+ WriteDouble(a, v) {
213
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Double(v)));
214
+ }
215
+ WriteInt64(a, v) {
216
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int64(v)));
217
+ }
218
+ WriteUInt64(a, v) {
219
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt64(v)));
220
+ }
221
+ async Run() {
222
+ const r = await this.transact(Buffer.from([4, 1, 255, 255, 4]));
223
+ return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r;
224
+ }
225
+ async Stop() {
226
+ const r = await this.transact(Buffer.from([4, 2, 255, 255]));
227
+ return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult() : r;
228
+ }
229
+ async ConnectServerAsync() {
230
+ return this.ConnectServer();
231
+ }
232
+ async ConnectCloseAsync() {
233
+ return this.ConnectClose();
234
+ }
91
235
  }
92
236
  exports.OmronFinsNet = OmronFinsNet;
93
- class OmronFinsUdp extends OmronFinsNet {
94
- }
95
- exports.OmronFinsUdp = OmronFinsUdp;
@@ -0,0 +1,41 @@
1
+ import { DeviceUdpNet } from '../core/DeviceUdpNet';
2
+ import { OperateResult } from '../core/Core';
3
+ import { INetMessage } from '../core/INetMessage';
4
+ /**
5
+ * Omron FINS UDP 客户端
6
+ * 用于通过 FINS/UDP 与设备通信。
7
+ */
8
+ export declare class OmronFinsUdp extends DeviceUdpNet {
9
+ DA1: number;
10
+ DA2: number;
11
+ SA1: number;
12
+ SA2: number;
13
+ SID: number;
14
+ constructor(ipAddress?: string, port?: number);
15
+ protected GetNewNetMessage(): INetMessage;
16
+ /**
17
+ * 构建 FINS 命令帧
18
+ */
19
+ private buildFinsCommand;
20
+ /**
21
+ * 读取数据区
22
+ */
23
+ Read(address: string, length: number): Promise<OperateResult<Buffer>>;
24
+ ReadString(address: string, length: number, encoding?: BufferEncoding): Promise<OperateResult<string>>;
25
+ /**
26
+ * 读取 UInt16
27
+ */
28
+ ReadUInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
29
+ /**
30
+ * 读取 Int16
31
+ */
32
+ ReadInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
33
+ /**
34
+ * 读取 Float
35
+ */
36
+ ReadFloat(address: string, length?: number): Promise<OperateResult<number | number[]>>;
37
+ /**
38
+ * 写入数据区
39
+ */
40
+ Write(address: string, data: Buffer): Promise<OperateResult<void>>;
41
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OmronFinsUdp = void 0;
4
+ const DeviceUdpNet_1 = require("../core/DeviceUdpNet");
5
+ const Core_1 = require("../core/Core");
6
+ const INetMessage_1 = require("../core/INetMessage");
7
+ /**
8
+ * Omron FINS UDP 客户端
9
+ * 用于通过 FINS/UDP 与设备通信。
10
+ */
11
+ class OmronFinsUdp extends DeviceUdpNet_1.DeviceUdpNet {
12
+ DA1 = 0; // 目标网络地址
13
+ DA2 = 0; // 目标节点地址
14
+ SA1 = 0; // 源网络地址
15
+ SA2 = 0; // 源节点地址
16
+ SID = 0; // 服务 ID
17
+ constructor(ipAddress, port = 9600) {
18
+ super(ipAddress, port);
19
+ this.ByteTransform.DataFormat = Core_1.DataFormat.CDAB;
20
+ }
21
+ GetNewNetMessage() {
22
+ return new INetMessage_1.FinsUdpMessage();
23
+ }
24
+ /**
25
+ * 构建 FINS 命令帧
26
+ */
27
+ buildFinsCommand(command) {
28
+ const header = Buffer.alloc(10);
29
+ // FINS 头部
30
+ header[0] = 0x80; // ICF
31
+ header[1] = 0x00; // RSV
32
+ header[2] = 0x02; // GCT
33
+ header[3] = this.DA1; // DNA
34
+ header[4] = this.DA2; // DA1
35
+ header[5] = 0x00; // DA2
36
+ header[6] = this.SA1; // SNA
37
+ header[7] = this.SA2; // SA1
38
+ header[8] = 0x00; // SA2
39
+ header[9] = this.SID++; // SID
40
+ return Buffer.concat([header, command]);
41
+ }
42
+ /**
43
+ * 读取数据区
44
+ */
45
+ async Read(address, length) {
46
+ // 解析地址(简化实现,实际应该更复杂)
47
+ const addr = parseInt(address);
48
+ const cmd = Buffer.alloc(8);
49
+ cmd[0] = 0x01; // MRC: 读取命令
50
+ cmd[1] = 0x01; // SRC: 读取子命令
51
+ cmd[2] = 0x82; // 存储区代码(DM区)
52
+ cmd.writeUInt16BE(addr, 3); // 起始地址
53
+ cmd[5] = 0x00; // bit
54
+ cmd.writeUInt16BE(length, 6); // 长度
55
+ const frame = this.buildFinsCommand(cmd);
56
+ const result = await this.request(frame);
57
+ if (!result.IsSuccess)
58
+ return result;
59
+ const response = result.Content;
60
+ if (response.length < 12) {
61
+ return new Core_1.OperateResult('Invalid FINS response length', -1);
62
+ }
63
+ // 检查响应码
64
+ const endCode = response.readUInt16BE(10);
65
+ if (endCode !== 0) {
66
+ return new Core_1.OperateResult(`FINS error code: ${endCode}`, endCode);
67
+ }
68
+ // 提取数据
69
+ return Core_1.OperateResult.CreateSuccessResult(response.subarray(12));
70
+ }
71
+ // FINS 字符串默认使用 UTF-8 编码。
72
+ async ReadString(address, length, encoding = 'utf8') {
73
+ const result = await this.Read(address, length);
74
+ return result.IsSuccess
75
+ ? Core_1.OperateResult.CreateSuccessResult(this.ByteTransform.TransString(result.Content, encoding))
76
+ : Core_1.OperateResult.CreateFailedResult(result);
77
+ }
78
+ /**
79
+ * 读取 UInt16
80
+ */
81
+ async ReadUInt16(address, length = 1) {
82
+ const result = await this.Read(address, length);
83
+ if (!result.IsSuccess)
84
+ return Core_1.OperateResult.CreateFailedResult(result);
85
+ const values = [];
86
+ for (let i = 0; i < length; i++) {
87
+ values.push(this.ByteTransform.TransUInt16(result.Content, i * 2));
88
+ }
89
+ return Core_1.OperateResult.CreateSuccessResult(length === 1 ? values[0] : values);
90
+ }
91
+ /**
92
+ * 读取 Int16
93
+ */
94
+ async ReadInt16(address, length = 1) {
95
+ const result = await this.Read(address, length);
96
+ if (!result.IsSuccess)
97
+ return Core_1.OperateResult.CreateFailedResult(result);
98
+ const values = [];
99
+ for (let i = 0; i < length; i++) {
100
+ values.push(this.ByteTransform.TransInt16(result.Content, i * 2));
101
+ }
102
+ return Core_1.OperateResult.CreateSuccessResult(length === 1 ? values[0] : values);
103
+ }
104
+ /**
105
+ * 读取 Float
106
+ */
107
+ async ReadFloat(address, length = 1) {
108
+ const result = await this.Read(address, length * 2);
109
+ if (!result.IsSuccess)
110
+ return Core_1.OperateResult.CreateFailedResult(result);
111
+ const values = [];
112
+ for (let i = 0; i < length; i++) {
113
+ values.push(this.ByteTransform.TransSingle(result.Content, i * 4));
114
+ }
115
+ return Core_1.OperateResult.CreateSuccessResult(length === 1 ? values[0] : values);
116
+ }
117
+ /**
118
+ * 写入数据区
119
+ */
120
+ async Write(address, data) {
121
+ const addr = parseInt(address);
122
+ const length = Math.ceil(data.length / 2);
123
+ const cmd = Buffer.alloc(8 + data.length);
124
+ cmd[0] = 0x01; // MRC: 写入命令
125
+ cmd[1] = 0x02; // SRC: 写入子命令
126
+ cmd[2] = 0x82; // 存储区代码(DM区)
127
+ cmd.writeUInt16BE(addr, 3);
128
+ cmd[5] = 0x00;
129
+ cmd.writeUInt16BE(length, 6);
130
+ data.copy(cmd, 8);
131
+ const frame = this.buildFinsCommand(cmd);
132
+ const result = await this.request(frame);
133
+ if (!result.IsSuccess)
134
+ return Core_1.OperateResult.CreateFailedResult(result);
135
+ const response = result.Content;
136
+ if (response.length < 12) {
137
+ return new Core_1.OperateResult('Invalid FINS response length', -1);
138
+ }
139
+ const endCode = response.readUInt16BE(10);
140
+ if (endCode !== 0) {
141
+ return new Core_1.OperateResult(`FINS error code: ${endCode}`, endCode);
142
+ }
143
+ return Core_1.OperateResult.CreateSuccessResult();
144
+ }
145
+ }
146
+ exports.OmronFinsUdp = OmronFinsUdp;
@@ -48,6 +48,12 @@ export declare class SiemensS7Net extends DeviceClient {
48
48
  ReadInt64(a: string, l?: number): Promise<OperateResult<any>>;
49
49
  ReadUInt64(a: string, l?: number): Promise<OperateResult<any>>;
50
50
  ReadString(address: string, length?: number, encoding?: BufferEncoding): Promise<OperateResult<string>>;
51
+ /**
52
+ * 读取西门子专用 S7 字符串。前几个字节保存字符串元数据,
53
+ * 因此需要先读取长度,再读取实际字符串内容。S200 Smart 只有当前长度字节,
54
+ * 其他 S7 CPU 保存最大长度和当前长度两个字节。
55
+ */
56
+ ReadS7String(address: string, encoding?: BufferEncoding): Promise<OperateResult<string>>;
51
57
  Write(address: string, value: Buffer | number | boolean | string | number[] | boolean[]): Promise<OperateResult<any>>;
52
58
  WriteByte(a: string, v: number): Promise<OperateResult<any>>;
53
59
  WriteInt16(a: string, v: number): Promise<OperateResult<any>>;
@@ -64,7 +64,7 @@ class SiemensS7Net extends Core_1.DeviceClient {
64
64
  super(ipAddress, ipAddress === undefined ? undefined : 102);
65
65
  this.Port = port ?? 102;
66
66
  this.PlcType = siemens;
67
- // S7 values are transmitted most-significant byte first.
67
+ // S7 数据按高字节在前的顺序传输。
68
68
  this.ByteTransform = new Core_1.ByteTransform(Core_1.DataFormat.ABCD);
69
69
  }
70
70
  static parseTpkt(data) {
@@ -111,7 +111,11 @@ class SiemensS7Net extends Core_1.DeviceClient {
111
111
  return tpkt;
112
112
  }
113
113
  messageId = 1;
114
- nextMessageId() { const id = this.messageId; this.messageId = (this.messageId + 1) & 0xffff; return id; }
114
+ nextMessageId() {
115
+ const id = this.messageId;
116
+ this.messageId = (this.messageId + 1) & 0xffff;
117
+ return id;
118
+ }
115
119
  async ConnectServer() {
116
120
  const connected = await super.ConnectServer();
117
121
  if (!connected.IsSuccess || this.initialized)
@@ -127,10 +131,16 @@ class SiemensS7Net extends Core_1.DeviceClient {
127
131
  return second;
128
132
  this.initialized = true;
129
133
  return Core_1.OperateResult.CreateSuccessResult();
130
- })().finally(() => { this.initializing = undefined; });
134
+ })().finally(() => {
135
+ this.initializing = undefined;
136
+ });
131
137
  return this.initializing;
132
138
  }
133
- async ConnectClose() { this.initialized = false; this.initializing = undefined; return super.ConnectClose(); }
139
+ async ConnectClose() {
140
+ this.initialized = false;
141
+ this.initializing = undefined;
142
+ return super.ConnectClose();
143
+ }
134
144
  connectionSetupPacket() {
135
145
  const packet = Buffer.from([3, 0, 0, 22, 0x11, 0xe0, 0, 0, 0, 1, 0, 0xc0, 1, 10, 0xc1, 2, 1, 2, 0xc2, 2, 1, 0]);
136
146
  packet[20] = this.ConnectionType;
@@ -199,10 +209,39 @@ class SiemensS7Net extends Core_1.DeviceClient {
199
209
  async ReadUInt64(a, l) {
200
210
  return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransUInt64(b, o));
201
211
  }
202
- async ReadString(address, length, encoding = 'utf8') {
212
+ async ReadString(address, length, encoding = 'ascii') {
203
213
  const r = await this.Read(address, length ?? 254);
204
214
  return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult(this.ByteTransform.TransString(r.Content, encoding)) : Core_1.OperateResult.CreateFailedResult(r);
205
215
  }
216
+ /**
217
+ * 读取西门子专用 S7 字符串。前几个字节保存字符串元数据,
218
+ * 因此需要先读取长度,再读取实际字符串内容。S200 Smart 只有当前长度字节,
219
+ * 其他 S7 CPU 保存最大长度和当前长度两个字节。
220
+ */
221
+ async ReadS7String(address, encoding = 'ascii') {
222
+ if (this.PlcType === SiemensPLCS.S200Smart) {
223
+ const header = await this.Read(address, 1);
224
+ if (!header.IsSuccess)
225
+ return Core_1.OperateResult.CreateFailedResult(header);
226
+ const length = header.Content[0];
227
+ const data = await this.Read(address, length + 1);
228
+ if (!data.IsSuccess)
229
+ return Core_1.OperateResult.CreateFailedResult(data);
230
+ return Core_1.OperateResult.CreateSuccessResult(Buffer.from(data.Content.subarray(1, 1 + length)).toString(encoding));
231
+ }
232
+ const header = await this.Read(address, 2);
233
+ if (!header.IsSuccess)
234
+ return Core_1.OperateResult.CreateFailedResult(header);
235
+ const maxLength = header.Content[0];
236
+ const length = header.Content[1];
237
+ if (maxLength === 0 || maxLength === 0xff || length > maxLength) {
238
+ return new Core_1.OperateResult('Value in plc is not string type');
239
+ }
240
+ const data = await this.Read(address, length + 2);
241
+ if (!data.IsSuccess)
242
+ return Core_1.OperateResult.CreateFailedResult(data);
243
+ return Core_1.OperateResult.CreateSuccessResult(Buffer.from(data.Content.subarray(2, 2 + length)).toString(encoding));
244
+ }
206
245
  async Write(address, value) {
207
246
  const a = parseS7Address(address);
208
247
  if (!a.IsSuccess)
@@ -211,7 +250,7 @@ class SiemensS7Net extends Core_1.DeviceClient {
211
250
  if (typeof value === 'boolean')
212
251
  data = Buffer.from([value ? 1 : 0]);
213
252
  else if (typeof value === 'string')
214
- data = Buffer.from(value);
253
+ data = Buffer.from(value, 'ascii');
215
254
  else if (Buffer.isBuffer(value))
216
255
  data = value;
217
256
  else if (Array.isArray(value) && typeof value[0] === 'boolean')
@@ -0,0 +1,18 @@
1
+ import { ModbusTcpNet } from '../modbus/ModbusTcpNet';
2
+ import { OperateResult } from '../core/Core';
3
+ export declare enum XinJESeries {
4
+ XC = "XC",
5
+ XD = "XD",
6
+ XL = "XL"
7
+ }
8
+ export declare class XinJETcpNet extends ModbusTcpNet {
9
+ Series: XinJESeries;
10
+ constructor(ipAddress?: string, port?: number, series?: XinJESeries);
11
+ private CalculateXinJEStartAddress;
12
+ private TranslateToModbusAddress;
13
+ private ParseXCAddress;
14
+ private ParseXDXLAddress;
15
+ Read(address: string, length: number): Promise<OperateResult<Buffer>>;
16
+ ReadBool(address: string, length?: number): Promise<OperateResult<boolean | boolean[]>>;
17
+ ReadInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
18
+ }