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
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GeSRTPNet = void 0;
4
+ exports.parseGeSRTPAddress = parseGeSRTPAddress;
5
+ const Core_1 = require("../core/Core");
6
+ const INetMessage_1 = require("../core/INetMessage");
7
+ const BIT_CODES = { I: 70, Q: 72, M: 76, T: 74, S: 84, G: 86 };
8
+ const BYTE_CODES = { I: 16, Q: 18, M: 22, T: 20, S: 30, G: 56 };
9
+ const SPECIAL_CODES = { SA: [78, 24], SB: [80, 26], SC: [82, 28] };
10
+ /** 解析 GE 地址。PLC 地址从 1 开始,报文内部从 0 开始。 */
11
+ function parseGeSRTPAddress(input, length, isBit) {
12
+ try {
13
+ const text = input.trim();
14
+ const match = text.match(/^([A-Za-z]+)(\d+)$/);
15
+ if (!match)
16
+ throw new Error(`地址格式错误: ${input}`);
17
+ const prefix = match[1].toUpperCase();
18
+ const number = Number(match[2]);
19
+ if (!Number.isSafeInteger(number) || number < 1 || number > 65536)
20
+ throw new Error(`地址超出范围: ${input}`);
21
+ let code;
22
+ if (prefix === 'AI' || prefix === 'AQ' || prefix === 'R') {
23
+ if (isBit)
24
+ throw new Error('AI、AQ、R 不支持位读写');
25
+ code = prefix === 'AI' ? 10 : prefix === 'AQ' ? 12 : 8;
26
+ }
27
+ else if (SPECIAL_CODES[prefix]) {
28
+ code = SPECIAL_CODES[prefix][isBit ? 0 : 1];
29
+ }
30
+ else {
31
+ code = (isBit ? BIT_CODES : BYTE_CODES)[prefix];
32
+ }
33
+ if (code === undefined)
34
+ throw new Error(`不支持的 GE 地址类型: ${input}`);
35
+ if (!Number.isInteger(length) || length < 0 || length > 65535)
36
+ throw new Error(`长度无效: ${length}`);
37
+ return Core_1.OperateResult.CreateSuccessResult({
38
+ DataCode: code,
39
+ AddressStart: number - 1,
40
+ Length: length,
41
+ IsBit: isBit
42
+ });
43
+ }
44
+ catch (e) {
45
+ return new Core_1.OperateResult(e.message);
46
+ }
47
+ }
48
+ function readCore(id, code, address, length) {
49
+ const frame = Buffer.alloc(56);
50
+ frame[0] = 2;
51
+ frame.writeUInt16LE(id & 0xffff, 2);
52
+ frame[9] = 1;
53
+ frame[17] = 1;
54
+ frame[30] = 6;
55
+ frame[31] = 0xc0;
56
+ frame[36] = 16;
57
+ frame[37] = 14;
58
+ frame[40] = 1;
59
+ frame[41] = 1;
60
+ frame[42] = 4;
61
+ frame[43] = code;
62
+ frame.writeUInt16LE(address & 0xffff, 44);
63
+ frame.writeUInt16LE(length & 0xffff, 46);
64
+ return frame;
65
+ }
66
+ function writeCore(id, code, address, length, value) {
67
+ const frame = Buffer.alloc(56 + value.length);
68
+ frame[0] = 2;
69
+ frame.writeUInt16LE(id & 0xffff, 2);
70
+ frame.writeUInt16LE(value.length, 4);
71
+ frame[9] = 2;
72
+ frame[17] = 2;
73
+ frame[30] = 9;
74
+ frame[31] = 0x80;
75
+ frame[36] = 16;
76
+ frame[37] = 14;
77
+ frame[40] = 1;
78
+ frame[41] = 1;
79
+ frame[42] = 2;
80
+ frame[48] = 1;
81
+ frame[49] = 1;
82
+ frame[50] = 7;
83
+ frame[51] = code;
84
+ frame.writeUInt16LE(address & 0xffff, 52);
85
+ frame.writeUInt16LE(length & 0xffff, 54);
86
+ value.copy(frame, 56);
87
+ return frame;
88
+ }
89
+ function responseFrame(data) {
90
+ if (data.length < 56)
91
+ throw new Error('GE 响应头不完整');
92
+ const size = data[4] | (data[5] << 8);
93
+ const total = 56 + size;
94
+ if (data.length < total)
95
+ throw new Error('GE 响应数据不完整');
96
+ return data.subarray(0, total);
97
+ }
98
+ function responseContent(frame) {
99
+ try {
100
+ if (frame.length < 56 || frame[0] !== 3)
101
+ return new Core_1.OperateResult('GE 响应格式错误');
102
+ const status = frame[42] | (frame[43] << 8);
103
+ if (frame[31] === 0xd4) {
104
+ if (status !== 0)
105
+ return new Core_1.OperateResult(`GE 操作失败: ${status}`, status);
106
+ return Core_1.OperateResult.CreateSuccessResult(frame.subarray(44, 50));
107
+ }
108
+ if (frame[31] === 0x94) {
109
+ return Core_1.OperateResult.CreateSuccessResult(frame.subarray(56));
110
+ }
111
+ return new Core_1.OperateResult('GE 响应类型错误');
112
+ }
113
+ catch (e) {
114
+ return new Core_1.OperateResult(e.message);
115
+ }
116
+ }
117
+ class GeSRTPNet extends Core_1.DeviceClient {
118
+ ByteTransform = new Core_1.ByteTransform(Core_1.DataFormat.DCBA);
119
+ messageId = 0;
120
+ initializedSocket;
121
+ constructor(ipAddress, port = 18245) {
122
+ super(ipAddress, ipAddress === undefined ? undefined : port);
123
+ this.Port = ipAddress === undefined ? 5000 : port;
124
+ this.ByteTransform = new Core_1.ByteTransform(Core_1.DataFormat.DCBA);
125
+ }
126
+ get DataFormat() {
127
+ return this.ByteTransform.DataFormat;
128
+ }
129
+ set DataFormat(value) {
130
+ this.ByteTransform.DataFormat = value;
131
+ }
132
+ GetNewNetMessage() {
133
+ return new INetMessage_1.GeSRTPMessage();
134
+ }
135
+ async ConnectServer() {
136
+ const result = await super.ConnectServer();
137
+ if (!result.IsSuccess || !this.socket)
138
+ return result;
139
+ if (this.initializedSocket === this.socket)
140
+ return result;
141
+ const handshake = await this.requestConnected(Buffer.alloc(56), data => data.length >= 56 ? data.subarray(0, 56) : (() => {
142
+ throw new Error('等待 GE 握手响应');
143
+ })());
144
+ if (!handshake.IsSuccess) {
145
+ await super.ConnectClose();
146
+ return handshake;
147
+ }
148
+ this.initializedSocket = this.socket;
149
+ return result;
150
+ }
151
+ async ConnectClose() {
152
+ this.initializedSocket = undefined;
153
+ return super.ConnectClose();
154
+ }
155
+ nextId() {
156
+ const id = this.messageId;
157
+ this.messageId = (this.messageId + 1) & 0xffff;
158
+ return id;
159
+ }
160
+ async transact(frame) {
161
+ const id = frame.readUInt16LE(2);
162
+ const result = await this.request(frame, data => {
163
+ const response = responseFrame(data);
164
+ if (response[2] !== (id & 0xff) || response[3] !== ((id >>> 8) & 0xff))
165
+ throw new Error('GE 响应消息号不匹配');
166
+ return response;
167
+ });
168
+ if (!result.IsSuccess)
169
+ return Core_1.OperateResult.CreateFailedResult(result);
170
+ return responseContent(result.Content);
171
+ }
172
+ async Read(address, length) {
173
+ const parsed = parseGeSRTPAddress(address, length, false);
174
+ if (!parsed.IsSuccess)
175
+ return Core_1.OperateResult.CreateFailedResult(parsed);
176
+ const p = parsed.Content;
177
+ // 对于R、AI、AQ寄存器,长度以字(word,2字节)为单位
178
+ // length是字节数,需要转换为字数发送给PLC
179
+ const units = p.DataCode === 8 || p.DataCode === 10 || p.DataCode === 12 ? Math.floor(length / 2) : length;
180
+ const result = await this.transact(readCore(this.nextId(), p.DataCode, p.AddressStart, units));
181
+ // 确保返回的数据长度正确(PLC返回的是实际请求的字节数)
182
+ if (result.IsSuccess && result.Content.length < length) {
183
+ // 如果返回的数据不足,用0填充(这不应该发生,但作为保护)
184
+ const padded = Buffer.alloc(length);
185
+ result.Content.copy(padded);
186
+ return Core_1.OperateResult.CreateSuccessResult(padded);
187
+ }
188
+ return result;
189
+ }
190
+ async ReadBool(address, length) {
191
+ const count = length ?? 1;
192
+ const parsed = parseGeSRTPAddress(address, count, true);
193
+ if (!parsed.IsSuccess)
194
+ return Core_1.OperateResult.CreateFailedResult(parsed);
195
+ const p = parsed.Content;
196
+ const result = await this.transact(readCore(this.nextId(), p.DataCode, p.AddressStart, count));
197
+ if (!result.IsSuccess)
198
+ return Core_1.OperateResult.CreateFailedResult(result);
199
+ // Convert bytes to bool array and extract from bit offset
200
+ const boolArray = [];
201
+ for (let i = 0; i < result.Content.length * 8; i++) {
202
+ boolArray.push((result.Content[i >> 3] & (1 << (i & 7))) !== 0);
203
+ }
204
+ const bitOffset = p.AddressStart % 8;
205
+ const values = boolArray.slice(bitOffset, bitOffset + count);
206
+ return Core_1.OperateResult.CreateSuccessResult(length === undefined ? values[0] : values);
207
+ }
208
+ async ReadByte(address) {
209
+ const p = parseGeSRTPAddress(address, 1, true);
210
+ if (!p.IsSuccess)
211
+ return Core_1.OperateResult.CreateFailedResult(p);
212
+ if (p.Content.DataCode === 8 || p.Content.DataCode === 10 || p.Content.DataCode === 12)
213
+ return new Core_1.OperateResult('AI、AQ、R 不支持字节读写');
214
+ const r = await this.Read(address, 1);
215
+ return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult(r.Content[0]) : Core_1.OperateResult.CreateFailedResult(r);
216
+ }
217
+ async typedRead(address, count, width, fn) {
218
+ const r = await this.Read(address, count * width);
219
+ if (!r.IsSuccess)
220
+ return Core_1.OperateResult.CreateFailedResult(r);
221
+ const values = Array.from({ length: count }, (_, i) => fn(r.Content, i * width));
222
+ return Core_1.OperateResult.CreateSuccessResult(count === 1 ? values[0] : values);
223
+ }
224
+ ReadInt16(a, l) {
225
+ return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransInt16(b, o));
226
+ }
227
+ ReadUInt16(a, l) {
228
+ return this.typedRead(a, l ?? 1, 2, (b, o) => this.ByteTransform.TransUInt16(b, o));
229
+ }
230
+ ReadInt32(a, l) {
231
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransInt32(b, o));
232
+ }
233
+ ReadUInt32(a, l) {
234
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransUInt32(b, o));
235
+ }
236
+ ReadFloat(a, l) {
237
+ return this.typedRead(a, l ?? 1, 4, (b, o) => this.ByteTransform.TransSingle(b, o));
238
+ }
239
+ ReadDouble(a, l) {
240
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransDouble(b, o));
241
+ }
242
+ ReadInt64(a, l) {
243
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransInt64(b, o));
244
+ }
245
+ ReadUInt64(a, l) {
246
+ return this.typedRead(a, l ?? 1, 8, (b, o) => this.ByteTransform.TransUInt64(b, o));
247
+ }
248
+ async ReadString(address, length, encoding = 'ascii') {
249
+ const r = await this.Read(address, length);
250
+ return r.IsSuccess ? Core_1.OperateResult.CreateSuccessResult(this.ByteTransform.TransString(r.Content, encoding)) : Core_1.OperateResult.CreateFailedResult(r);
251
+ }
252
+ async Write(address, value) {
253
+ const isBit = typeof value === 'boolean' || (Array.isArray(value) && (value.length === 0 || typeof value[0] === 'boolean'));
254
+ const length = isBit ? (Array.isArray(value) ? value.length : 1) : Buffer.isBuffer(value) ? value.length : typeof value === 'string' ? Buffer.byteLength(value, 'ascii') : Array.isArray(value) ? value.length * 2 : 2;
255
+ const parsed = parseGeSRTPAddress(address, length, isBit);
256
+ if (!parsed.IsSuccess)
257
+ return parsed;
258
+ const p = parsed.Content;
259
+ let data;
260
+ if (typeof value === 'boolean') {
261
+ // For single boolean, create array with proper bit offset alignment
262
+ const bitOffset = p.AddressStart % 8;
263
+ const boolArray = new Array(bitOffset + 1).fill(false);
264
+ boolArray[bitOffset] = value;
265
+ data = Buffer.alloc(Math.ceil(boolArray.length / 8));
266
+ boolArray.forEach((v, i) => {
267
+ if (v)
268
+ data[i >> 3] |= 1 << (i & 7);
269
+ });
270
+ }
271
+ else if (typeof value === 'string')
272
+ data = Buffer.from(value, 'ascii');
273
+ else if (Buffer.isBuffer(value))
274
+ data = value;
275
+ else if (Array.isArray(value) && (value.length === 0 || typeof value[0] === 'boolean')) {
276
+ // For boolean array, align with bit offset
277
+ const bitOffset = p.AddressStart % 8;
278
+ const boolArray = new Array(bitOffset + value.length).fill(false);
279
+ value.forEach((v, i) => {
280
+ boolArray[bitOffset + i] = v;
281
+ });
282
+ data = Buffer.alloc(Math.ceil(boolArray.length / 8));
283
+ boolArray.forEach((v, i) => {
284
+ if (v)
285
+ data[i >> 3] |= 1 << (i & 7);
286
+ });
287
+ }
288
+ else
289
+ data = this.ByteTransform.TransByte(value, 2);
290
+ if (!isBit && (p.DataCode === 8 || p.DataCode === 10 || p.DataCode === 12) && data.length % 2 !== 0)
291
+ return new Core_1.OperateResult('AI、AQ、R 写入长度必须为偶数');
292
+ const units = p.DataCode === 8 || p.DataCode === 10 || p.DataCode === 12 ? Math.floor(data.length / 2) : isBit ? p.Length : data.length;
293
+ return this.transact(writeCore(this.nextId(), p.DataCode, p.AddressStart, units, data));
294
+ }
295
+ WriteByte(a, v) {
296
+ const p = parseGeSRTPAddress(a, 1, true);
297
+ if (!p.IsSuccess)
298
+ return Core_1.OperateResult.CreateFailedResult(p);
299
+ if (p.Content.DataCode === 8 || p.Content.DataCode === 10 || p.Content.DataCode === 12)
300
+ return new Core_1.OperateResult('AI、AQ、R 不支持字节读写');
301
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Byte(v), 1));
302
+ }
303
+ WriteInt16(a, v) {
304
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int16(v)));
305
+ }
306
+ WriteUInt16(a, v) {
307
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt16(v)));
308
+ }
309
+ WriteInt32(a, v) {
310
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int32(v)));
311
+ }
312
+ WriteUInt32(a, v) {
313
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt32(v)));
314
+ }
315
+ WriteFloat(a, v) {
316
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Float(v)));
317
+ }
318
+ WriteDouble(a, v) {
319
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Double(v)));
320
+ }
321
+ WriteInt64(a, v) {
322
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.Int64(v)));
323
+ }
324
+ WriteUInt64(a, v) {
325
+ return this.Write(a, this.ByteTransform.TransByte(new Core_1.UInt64(v)));
326
+ }
327
+ async ConnectServerAsync() {
328
+ return this.ConnectServer();
329
+ }
330
+ async ConnectCloseAsync() {
331
+ return this.ConnectClose();
332
+ }
333
+ toString() {
334
+ return `GeSRTPNet[${this.IpAddress}:${this.Port}]`;
335
+ }
336
+ }
337
+ exports.GeSRTPNet = GeSRTPNet;
@@ -0,0 +1,8 @@
1
+ import { DeviceClient, OperateResult } from '../core/Core';
2
+ export declare class InovanceEasyNet extends DeviceClient {
3
+ constructor(ipAddress?: string, port?: number);
4
+ private AnalysisAddressBytes;
5
+ private BuildReadCommand;
6
+ Read(address: string, length: number): Promise<OperateResult<Buffer>>;
7
+ ReadInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
8
+ }
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InovanceEasyNet = void 0;
4
+ const Core_1 = require("../core/Core");
5
+ class InovanceEasyNet extends Core_1.DeviceClient {
6
+ constructor(ipAddress, port = 8000) {
7
+ super(ipAddress, port);
8
+ this.ByteTransform.DataFormat = Core_1.DataFormat.CDAB;
9
+ }
10
+ AnalysisAddressBytes(address) {
11
+ try {
12
+ const upper = address.toUpperCase();
13
+ const result = Buffer.alloc(4);
14
+ if (upper.startsWith('SM')) {
15
+ result[0] = 0x01;
16
+ result.writeUInt16LE(parseInt(upper.substring(2)), 1);
17
+ return Core_1.OperateResult.CreateSuccessResult(result);
18
+ }
19
+ if (upper.startsWith('S')) {
20
+ result[0] = 0x02;
21
+ result.writeUInt16LE(parseInt(upper.substring(1)), 1);
22
+ return Core_1.OperateResult.CreateSuccessResult(result);
23
+ }
24
+ if (upper.startsWith('X')) {
25
+ result[0] = 0x03;
26
+ result.writeUInt16LE(parseInt(upper.substring(1)), 1);
27
+ return Core_1.OperateResult.CreateSuccessResult(result);
28
+ }
29
+ if (upper.startsWith('Y')) {
30
+ result[0] = 0x04;
31
+ result.writeUInt16LE(parseInt(upper.substring(1)), 1);
32
+ return Core_1.OperateResult.CreateSuccessResult(result);
33
+ }
34
+ if (upper.startsWith('M')) {
35
+ result[0] = 0x05;
36
+ result.writeUInt16LE(parseInt(upper.substring(1)), 1);
37
+ return Core_1.OperateResult.CreateSuccessResult(result);
38
+ }
39
+ if (upper.startsWith('D')) {
40
+ result[0] = 0x06;
41
+ result.writeUInt16LE(parseInt(upper.substring(1)), 1);
42
+ return Core_1.OperateResult.CreateSuccessResult(result);
43
+ }
44
+ return new Core_1.OperateResult('Unsupported address: ' + address, -1);
45
+ }
46
+ catch (e) {
47
+ return new Core_1.OperateResult('Address parse error', -1);
48
+ }
49
+ }
50
+ BuildReadCommand(address, length) {
51
+ const addressBytes = this.AnalysisAddressBytes(address);
52
+ if (!addressBytes.IsSuccess)
53
+ return Core_1.OperateResult.CreateFailedResult(addressBytes);
54
+ const cmd = Buffer.alloc(21);
55
+ cmd[0] = 0x4B;
56
+ cmd[1] = 0x4D;
57
+ cmd[2] = 0x01;
58
+ cmd[3] = 0x00;
59
+ cmd[4] = 0x00;
60
+ cmd[5] = 0x00;
61
+ cmd[6] = 0x00;
62
+ cmd[7] = 0x01;
63
+ cmd[8] = 0x00;
64
+ cmd[9] = 0x0C;
65
+ cmd[10] = 0x00;
66
+ cmd[11] = 0x01;
67
+ cmd[12] = 0x01;
68
+ cmd[13] = 0x01;
69
+ addressBytes.Content.copy(cmd, 14);
70
+ cmd.writeUInt16LE(length * 16, 18);
71
+ cmd.writeUInt16LE(length * 16, 20);
72
+ return Core_1.OperateResult.CreateSuccessResult([cmd]);
73
+ }
74
+ async Read(address, length) {
75
+ const cmdResult = this.BuildReadCommand(address, length);
76
+ if (!cmdResult.IsSuccess)
77
+ return Core_1.OperateResult.CreateFailedResult(cmdResult);
78
+ const result = await this.request(cmdResult.Content[0], (data) => {
79
+ if (data.length < 11)
80
+ throw new Error('incomplete');
81
+ const dataLength = data.readUInt16LE(9);
82
+ if (data.length < 11 + dataLength)
83
+ throw new Error('incomplete');
84
+ return data.subarray(0, 11 + dataLength);
85
+ });
86
+ if (!result.IsSuccess)
87
+ return result;
88
+ const errorCode = result.Content.readUInt16LE(5);
89
+ if (errorCode !== 0)
90
+ return new Core_1.OperateResult('Inovance Easy error: ' + errorCode, errorCode);
91
+ return Core_1.OperateResult.CreateSuccessResult(result.Content.subarray(11));
92
+ }
93
+ async ReadInt16(address, length = 1) {
94
+ const result = await this.Read(address, length);
95
+ if (!result.IsSuccess)
96
+ return Core_1.OperateResult.CreateFailedResult(result);
97
+ const values = [];
98
+ for (let i = 0; i < length; i++)
99
+ values.push(this.ByteTransform.TransInt16(result.Content, i * 2));
100
+ return Core_1.OperateResult.CreateSuccessResult(length === 1 ? values[0] : values);
101
+ }
102
+ }
103
+ exports.InovanceEasyNet = InovanceEasyNet;
@@ -0,0 +1,55 @@
1
+ import { ModbusRtu } from '../modbus/ModbusRtu';
2
+ import { OperateResult } from '../core/Core';
3
+ import { InovanceSeries } from './InovanceTcpNet';
4
+ /**
5
+ * 汇川 PLC 串口通信客户端(基于 Modbus RTU)
6
+ * Inovance PLC serial communication client (based on Modbus RTU)
7
+ */
8
+ export declare class InovanceSerial extends ModbusRtu {
9
+ Series: InovanceSeries;
10
+ constructor(station?: number);
11
+ /**
12
+ * 地址转换:将汇川地址转换为 Modbus 地址
13
+ */
14
+ TranslateToModbusAddress(address: string, modbusCode: number): OperateResult<string>;
15
+ /**
16
+ * 读取数据
17
+ */
18
+ Read(address: string, length: number): Promise<OperateResult<Buffer>>;
19
+ /**
20
+ * 读取布尔值
21
+ */
22
+ ReadBool(address: string, length?: number): Promise<OperateResult<boolean | boolean[]>>;
23
+ /**
24
+ * 写入数据
25
+ */
26
+ Write(address: string, value: Buffer | boolean | boolean[] | number | number[]): Promise<OperateResult<void>>;
27
+ /**
28
+ * 读取 Int16
29
+ */
30
+ ReadInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
31
+ /**
32
+ * 读取 UInt16
33
+ */
34
+ ReadUInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
35
+ /**
36
+ * 读取 Int32
37
+ */
38
+ ReadInt32(address: string, length?: number): Promise<OperateResult<number | number[]>>;
39
+ /**
40
+ * 读取 Float
41
+ */
42
+ ReadFloat(address: string, length?: number): Promise<OperateResult<number | number[]>>;
43
+ /**
44
+ * 读取字节(MB 地址)
45
+ */
46
+ ReadByte(address: string): Promise<OperateResult<number>>;
47
+ /**
48
+ * 写入 Int16
49
+ */
50
+ WriteInt16(address: string, value: number): Promise<OperateResult<void>>;
51
+ /**
52
+ * 写入 Float
53
+ */
54
+ WriteFloat(address: string, value: number): Promise<OperateResult<void>>;
55
+ }
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InovanceSerial = void 0;
4
+ const ModbusRtu_1 = require("../modbus/ModbusRtu");
5
+ const Core_1 = require("../core/Core");
6
+ const InovanceTcpNet_1 = require("./InovanceTcpNet");
7
+ /**
8
+ * 汇川 PLC 串口通信客户端(基于 Modbus RTU)
9
+ * Inovance PLC serial communication client (based on Modbus RTU)
10
+ */
11
+ class InovanceSerial extends ModbusRtu_1.ModbusRtu {
12
+ Series = InovanceTcpNet_1.InovanceSeries.AM;
13
+ constructor(station = 1) {
14
+ super(station);
15
+ }
16
+ /**
17
+ * 地址转换:将汇川地址转换为 Modbus 地址
18
+ */
19
+ TranslateToModbusAddress(address, modbusCode) {
20
+ return (0, InovanceTcpNet_1.parseInovanceAddress)(this.Series, address, modbusCode);
21
+ }
22
+ /**
23
+ * 读取数据
24
+ */
25
+ async Read(address, length) {
26
+ const a = this.TranslateToModbusAddress(address, 3);
27
+ return a.IsSuccess ? super.Read(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
28
+ }
29
+ /**
30
+ * 读取布尔值
31
+ */
32
+ async ReadBool(address, length = 1) {
33
+ const a = this.TranslateToModbusAddress(address, 1);
34
+ return a.IsSuccess ? super.ReadCoil(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
35
+ }
36
+ /**
37
+ * 写入数据
38
+ */
39
+ async Write(address, value) {
40
+ // 判断是位写入还是字写入
41
+ const isBitWrite = typeof value === 'boolean' || (Array.isArray(value) && typeof value[0] === 'boolean');
42
+ const code = isBitWrite ? 5 : 6;
43
+ const a = this.TranslateToModbusAddress(address, code);
44
+ if (!a.IsSuccess)
45
+ return Core_1.OperateResult.CreateFailedResult(a);
46
+ // 布尔值写入
47
+ if (typeof value === 'boolean') {
48
+ return super.WriteCoil(a.Content, value);
49
+ }
50
+ // 布尔数组写入
51
+ if (Array.isArray(value) && typeof value[0] === 'boolean') {
52
+ return super.WriteCoils(a.Content, value);
53
+ }
54
+ // Buffer 写入
55
+ if (Buffer.isBuffer(value)) {
56
+ const length = Math.ceil(value.length / 2);
57
+ const a16 = this.TranslateToModbusAddress(address, 16);
58
+ if (!a16.IsSuccess)
59
+ return Core_1.OperateResult.CreateFailedResult(a16);
60
+ if (length === 1) {
61
+ return super.WriteRegister(a16.Content, value.readUInt16BE(0));
62
+ }
63
+ else {
64
+ const values = [];
65
+ for (let i = 0; i < length; i++) {
66
+ values.push(value.readUInt16BE(i * 2));
67
+ }
68
+ return super.WriteRegisters(a16.Content, values);
69
+ }
70
+ }
71
+ // 数字写入
72
+ if (typeof value === 'number') {
73
+ return super.WriteRegister(a.Content, value);
74
+ }
75
+ // 数字数组写入
76
+ if (Array.isArray(value) && typeof value[0] === 'number') {
77
+ return super.WriteRegisters(a.Content, value);
78
+ }
79
+ return new Core_1.OperateResult('Unsupported value type', -1);
80
+ }
81
+ /**
82
+ * 读取 Int16
83
+ */
84
+ async ReadInt16(address, length = 1) {
85
+ const a = this.TranslateToModbusAddress(address, 3);
86
+ return a.IsSuccess ? super.ReadInt16(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
87
+ }
88
+ /**
89
+ * 读取 UInt16
90
+ */
91
+ async ReadUInt16(address, length = 1) {
92
+ const a = this.TranslateToModbusAddress(address, 3);
93
+ return a.IsSuccess ? super.ReadUInt16(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
94
+ }
95
+ /**
96
+ * 读取 Int32
97
+ */
98
+ async ReadInt32(address, length = 1) {
99
+ const a = this.TranslateToModbusAddress(address, 3);
100
+ return a.IsSuccess ? super.ReadInt32(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
101
+ }
102
+ /**
103
+ * 读取 Float
104
+ */
105
+ async ReadFloat(address, length = 1) {
106
+ const a = this.TranslateToModbusAddress(address, 3);
107
+ return a.IsSuccess ? super.ReadFloat(a.Content, length) : Core_1.OperateResult.CreateFailedResult(a);
108
+ }
109
+ /**
110
+ * 读取字节(MB 地址)
111
+ */
112
+ async ReadByte(address) {
113
+ const n = Number(address.replace(/^MB?/i, ''));
114
+ const r = await this.Read(`MW${Math.floor(n / 2)}`, 1);
115
+ if (!r.IsSuccess)
116
+ return Core_1.OperateResult.CreateFailedResult(r);
117
+ // 偶数字节在高位,奇数字节在低位
118
+ return Core_1.OperateResult.CreateSuccessResult(n % 2 === 0 ? r.Content[1] : r.Content[0]);
119
+ }
120
+ /**
121
+ * 写入 Int16
122
+ */
123
+ async WriteInt16(address, value) {
124
+ const a = this.TranslateToModbusAddress(address, 6);
125
+ if (!a.IsSuccess)
126
+ return Core_1.OperateResult.CreateFailedResult(a);
127
+ const buffer = Buffer.alloc(2);
128
+ this.ByteTransform.TransByte(value);
129
+ buffer.writeInt16BE(value, 0);
130
+ return super.WriteRegister(a.Content, buffer.readUInt16BE(0));
131
+ }
132
+ /**
133
+ * 写入 Float
134
+ */
135
+ async WriteFloat(address, value) {
136
+ const a = this.TranslateToModbusAddress(address, 16);
137
+ if (!a.IsSuccess)
138
+ return Core_1.OperateResult.CreateFailedResult(a);
139
+ const buffer = Buffer.alloc(4);
140
+ buffer.writeFloatBE(value, 0);
141
+ const values = [buffer.readUInt16BE(0), buffer.readUInt16BE(2)];
142
+ return super.WriteRegisters(a.Content, values);
143
+ }
144
+ }
145
+ exports.InovanceSerial = InovanceSerial;
@@ -0,0 +1,39 @@
1
+ import { ModbusRtuOverTcp } from '../modbus/ModbusRtuOverTcp';
2
+ import { OperateResult } from '../core/Core';
3
+ import { InovanceSeries } from './InovanceTcpNet';
4
+ /**
5
+ * 汇川 PLC 串口协议 over TCP 客户端(基于 Modbus RTU over TCP)
6
+ * Inovance PLC serial protocol over TCP client (based on Modbus RTU over TCP)
7
+ */
8
+ export declare class InovanceSerialOverTcp extends ModbusRtuOverTcp {
9
+ Series: InovanceSeries;
10
+ constructor(ipAddress?: string, port?: number, station?: number);
11
+ /**
12
+ * 地址转换:将汇川地址转换为 Modbus 地址
13
+ */
14
+ TranslateToModbusAddress(address: string, modbusCode: number): OperateResult<string>;
15
+ /**
16
+ * 读取数据
17
+ */
18
+ Read(address: string, length: number): Promise<OperateResult<Buffer>>;
19
+ /**
20
+ * 读取布尔值
21
+ */
22
+ ReadBool(address: string, length?: number): Promise<OperateResult<boolean | boolean[]>>;
23
+ /**
24
+ * 写入数据
25
+ */
26
+ Write(address: string, value: Buffer | boolean | boolean[] | number | number[]): Promise<OperateResult<void>>;
27
+ /**
28
+ * 读取 Int16
29
+ */
30
+ ReadInt16(address: string, length?: number): Promise<OperateResult<number | number[]>>;
31
+ /**
32
+ * 读取 Float
33
+ */
34
+ ReadFloat(address: string, length?: number): Promise<OperateResult<number | number[]>>;
35
+ /**
36
+ * 读取字节(MB 地址)
37
+ */
38
+ ReadByte(address: string): Promise<OperateResult<number>>;
39
+ }