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.
- package/LICENSE +15 -0
- package/README.md +246 -14
- package/dist/Invt/InvtModbusTcp.d.ts +88 -0
- package/dist/Invt/InvtModbusTcp.js +255 -0
- package/dist/XCommunication.d.ts +18 -0
- package/dist/XCommunication.js +29 -0
- package/dist/ab/AbEtherNetIp.d.ts +1 -0
- package/dist/ab/AbEtherNetIp.js +2 -0
- package/dist/core/CommunicationLock.d.ts +88 -0
- package/dist/core/CommunicationLock.js +156 -0
- package/dist/core/Core.d.ts +27 -1
- package/dist/core/Core.js +375 -71
- package/dist/core/DeviceSerialPort.d.ts +64 -0
- package/dist/core/DeviceSerialPort.js +283 -0
- package/dist/core/DeviceUdpNet.d.ts +56 -0
- package/dist/core/DeviceUdpNet.js +307 -0
- package/dist/core/INetMessage.d.ts +145 -0
- package/dist/core/INetMessage.js +240 -0
- package/dist/debug/PingTest.d.ts +11 -0
- package/dist/debug/PingTest.js +59 -0
- package/dist/debug/tcpClient.d.ts +11 -0
- package/dist/debug/tcpClient.js +116 -0
- package/dist/debug/tcpServer.d.ts +12 -0
- package/dist/debug/tcpServer.js +102 -0
- package/dist/delta/DeltaTcpNet.d.ts +65 -0
- package/dist/delta/DeltaTcpNet.js +346 -0
- package/dist/ge/GeSRTPNet.d.ts +49 -0
- package/dist/ge/GeSRTPNet.js +337 -0
- package/dist/inovance/InovanceEasyNet.d.ts +8 -0
- package/dist/inovance/InovanceEasyNet.js +103 -0
- package/dist/inovance/InovanceSerial.d.ts +55 -0
- package/dist/inovance/InovanceSerial.js +145 -0
- package/dist/inovance/InovanceSerialOverTcp.d.ts +39 -0
- package/dist/inovance/InovanceSerialOverTcp.js +172 -0
- package/dist/inovance/InovanceTcpNet.d.ts +2 -4
- package/dist/inovance/InovanceTcpNet.js +40 -13
- package/dist/melsec/MelsecMcAsciiNet.d.ts +49 -0
- package/dist/melsec/MelsecMcAsciiNet.js +196 -0
- package/dist/melsec/MelsecMcAsciiUdp.d.ts +54 -0
- package/dist/melsec/MelsecMcAsciiUdp.js +204 -0
- package/dist/melsec/MelsecMcNet.d.ts +1 -8
- package/dist/melsec/MelsecMcNet.js +4 -14
- package/dist/melsec/MelsecMcUdp.d.ts +52 -0
- package/dist/melsec/MelsecMcUdp.js +191 -0
- package/dist/modbus/ModbusAscii.d.ts +24 -3
- package/dist/modbus/ModbusAscii.js +109 -3
- package/dist/modbus/ModbusAsciiOverTcp.d.ts +21 -3
- package/dist/modbus/ModbusAsciiOverTcp.js +67 -3
- package/dist/modbus/ModbusRtu.d.ts +101 -13
- package/dist/modbus/ModbusRtu.js +355 -21
- package/dist/modbus/ModbusRtuOverTcp.d.ts +23 -3
- package/dist/modbus/ModbusRtuOverTcp.js +68 -3
- package/dist/modbus/ModbusTcpNet.d.ts +16 -3
- package/dist/modbus/ModbusTcpNet.js +192 -60
- package/dist/modbus/ModbusUdpNet.d.ts +26 -3
- package/dist/modbus/ModbusUdpNet.js +125 -2
- package/dist/omron/OmronFinsNet.d.ts +1 -2
- package/dist/omron/OmronFinsNet.js +210 -69
- package/dist/omron/OmronFinsUdp.d.ts +41 -0
- package/dist/omron/OmronFinsUdp.js +146 -0
- package/dist/siemens/SiemensS7Net.d.ts +6 -0
- package/dist/siemens/SiemensS7Net.js +45 -6
- package/dist/xinjie/XinJETcpNet.d.ts +18 -0
- package/dist/xinjie/XinJETcpNet.js +106 -0
- package/package.json +16 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TcpServer = void 0;
|
|
37
|
+
const net = __importStar(require("node:net"));
|
|
38
|
+
class TcpServer {
|
|
39
|
+
server;
|
|
40
|
+
clients = new Set();
|
|
41
|
+
port;
|
|
42
|
+
host;
|
|
43
|
+
constructor(port = 5000, host = '0.0.0.0') {
|
|
44
|
+
this.port = port;
|
|
45
|
+
this.host = host;
|
|
46
|
+
}
|
|
47
|
+
async start() {
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
this.server = net.createServer((socket) => {
|
|
50
|
+
this.handleConnection(socket);
|
|
51
|
+
});
|
|
52
|
+
this.server.on('error', (err) => {
|
|
53
|
+
console.error('[TcpServer] Server error:', err.message);
|
|
54
|
+
resolve(false);
|
|
55
|
+
});
|
|
56
|
+
this.server.listen(this.port, this.host, () => {
|
|
57
|
+
console.log('[TcpServer] Server listening on ' + this.host + ':' + this.port);
|
|
58
|
+
resolve(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
handleConnection(socket) {
|
|
63
|
+
const clientId = socket.remoteAddress + ':' + socket.remotePort;
|
|
64
|
+
console.log('[TcpServer] Client connected: ' + clientId);
|
|
65
|
+
this.clients.add(socket);
|
|
66
|
+
socket.on('data', (data) => {
|
|
67
|
+
console.log('[TcpServer] Received: ' + data.length + ' bytes');
|
|
68
|
+
socket.write(data);
|
|
69
|
+
});
|
|
70
|
+
socket.on('close', () => {
|
|
71
|
+
console.log('[TcpServer] Client disconnected: ' + clientId);
|
|
72
|
+
this.clients.delete(socket);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
broadcast(data) {
|
|
76
|
+
console.log('[TcpServer] Broadcasting to ' + this.clients.size + ' clients');
|
|
77
|
+
for (const client of this.clients) {
|
|
78
|
+
if (!client.destroyed)
|
|
79
|
+
client.write(data);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
getClientCount() {
|
|
83
|
+
return this.clients.size;
|
|
84
|
+
}
|
|
85
|
+
async stop() {
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
for (const client of this.clients)
|
|
88
|
+
client.destroy();
|
|
89
|
+
this.clients.clear();
|
|
90
|
+
if (this.server) {
|
|
91
|
+
this.server.close(() => {
|
|
92
|
+
console.log('[TcpServer] Server stopped');
|
|
93
|
+
resolve();
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
resolve();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.TcpServer = TcpServer;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ModbusTcpNet, ModbusAddress } from '../modbus/ModbusTcpNet';
|
|
2
|
+
import { OperateResult } from '../core/Core';
|
|
3
|
+
/**
|
|
4
|
+
* 台达PLC系列枚举
|
|
5
|
+
*/
|
|
6
|
+
export declare enum DeltaSeries {
|
|
7
|
+
/** DVP系列 */
|
|
8
|
+
Dvp = 1,
|
|
9
|
+
/** AS300系列 */
|
|
10
|
+
AS = 2
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 台达PLC的网口通讯类,基于Modbus-Tcp协议开发,按照台达的地址进行实现
|
|
14
|
+
*
|
|
15
|
+
* 适用于DVP-ES/EX/EC/SS型号,DVP-SA/SC/SX/EH型号以及AS300型号
|
|
16
|
+
*
|
|
17
|
+
* 地址示例:
|
|
18
|
+
* - S0-S999: 状态寄存器
|
|
19
|
+
* - X0-X377(八进制): 输入继电器
|
|
20
|
+
* - Y0-Y377(八进制): 输出继电器
|
|
21
|
+
* - T0-T255: 定时器
|
|
22
|
+
* - C0-C255: 计数器
|
|
23
|
+
* - M0-M4095: 内部继电器
|
|
24
|
+
* - D0-D9999: 数据寄存器
|
|
25
|
+
*
|
|
26
|
+
* 地址可以携带站号信息,例如:[s=2;D100], [s=3;M100]
|
|
27
|
+
*/
|
|
28
|
+
export declare class DeltaTcpNet extends ModbusTcpNet {
|
|
29
|
+
/** 台达PLC系列,默认为DVP系列 */
|
|
30
|
+
Series: DeltaSeries;
|
|
31
|
+
constructor(ipAddress?: string, port?: number, station?: number);
|
|
32
|
+
/**
|
|
33
|
+
* 将台达D寄存器地址转换为Modbus地址
|
|
34
|
+
*/
|
|
35
|
+
private transDAddressToModbusAddress;
|
|
36
|
+
/**
|
|
37
|
+
* 解析AS系列位地址(带小数点的)
|
|
38
|
+
*/
|
|
39
|
+
private parseDeltaBitAddress;
|
|
40
|
+
/**
|
|
41
|
+
* 重写地址解析方法,将台达地址转换为Modbus地址
|
|
42
|
+
*/
|
|
43
|
+
protected addr(input: string, code: number): OperateResult<ModbusAddress>;
|
|
44
|
+
/**
|
|
45
|
+
* DVP系列地址解析
|
|
46
|
+
*/
|
|
47
|
+
private parseDvpAddress;
|
|
48
|
+
/**
|
|
49
|
+
* AS300系列地址解析
|
|
50
|
+
*/
|
|
51
|
+
private parseASAddress;
|
|
52
|
+
/**
|
|
53
|
+
* 读取bool数组,针对DVP系列M地址跨1536的情况进行特殊处理
|
|
54
|
+
*/
|
|
55
|
+
ReadBool(address: string, length?: number): Promise<OperateResult<boolean | boolean[]>>;
|
|
56
|
+
/**
|
|
57
|
+
* 写入bool数组,针对DVP系列M地址跨1536的情况进行特殊处理
|
|
58
|
+
*/
|
|
59
|
+
Write(address: string, value: boolean | boolean[] | number | number[] | Buffer | string): Promise<OperateResult<any>>;
|
|
60
|
+
/**
|
|
61
|
+
* 读取数据,针对DVP系列D地址跨4096的情况进行特殊处理
|
|
62
|
+
*/
|
|
63
|
+
Read(address: string, length: number): Promise<OperateResult<Buffer>>;
|
|
64
|
+
toString(): string;
|
|
65
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeltaTcpNet = exports.DeltaSeries = void 0;
|
|
4
|
+
const ModbusTcpNet_1 = require("../modbus/ModbusTcpNet");
|
|
5
|
+
const Core_1 = require("../core/Core");
|
|
6
|
+
/**
|
|
7
|
+
* 台达PLC系列枚举
|
|
8
|
+
*/
|
|
9
|
+
var DeltaSeries;
|
|
10
|
+
(function (DeltaSeries) {
|
|
11
|
+
/** DVP系列 */
|
|
12
|
+
DeltaSeries[DeltaSeries["Dvp"] = 1] = "Dvp";
|
|
13
|
+
/** AS300系列 */
|
|
14
|
+
DeltaSeries[DeltaSeries["AS"] = 2] = "AS";
|
|
15
|
+
})(DeltaSeries || (exports.DeltaSeries = DeltaSeries = {}));
|
|
16
|
+
/**
|
|
17
|
+
* 台达PLC的网口通讯类,基于Modbus-Tcp协议开发,按照台达的地址进行实现
|
|
18
|
+
*
|
|
19
|
+
* 适用于DVP-ES/EX/EC/SS型号,DVP-SA/SC/SX/EH型号以及AS300型号
|
|
20
|
+
*
|
|
21
|
+
* 地址示例:
|
|
22
|
+
* - S0-S999: 状态寄存器
|
|
23
|
+
* - X0-X377(八进制): 输入继电器
|
|
24
|
+
* - Y0-Y377(八进制): 输出继电器
|
|
25
|
+
* - T0-T255: 定时器
|
|
26
|
+
* - C0-C255: 计数器
|
|
27
|
+
* - M0-M4095: 内部继电器
|
|
28
|
+
* - D0-D9999: 数据寄存器
|
|
29
|
+
*
|
|
30
|
+
* 地址可以携带站号信息,例如:[s=2;D100], [s=3;M100]
|
|
31
|
+
*/
|
|
32
|
+
class DeltaTcpNet extends ModbusTcpNet_1.ModbusTcpNet {
|
|
33
|
+
/** 台达PLC系列,默认为DVP系列 */
|
|
34
|
+
Series = DeltaSeries.Dvp;
|
|
35
|
+
constructor(ipAddress, port = 502, station = 1) {
|
|
36
|
+
super(ipAddress, port, station);
|
|
37
|
+
console.log('[DeltaTcpNet] Constructor called, Series:', this.Series);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 将台达D寄存器地址转换为Modbus地址
|
|
41
|
+
*/
|
|
42
|
+
transDAddressToModbusAddress(address) {
|
|
43
|
+
if (address >= 4096) {
|
|
44
|
+
return address - 4096 + 36864;
|
|
45
|
+
}
|
|
46
|
+
return address + 4096;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 解析AS系列位地址(带小数点的)
|
|
50
|
+
*/
|
|
51
|
+
parseDeltaBitAddress(address) {
|
|
52
|
+
const dotIndex = address.indexOf('.');
|
|
53
|
+
if (dotIndex > 0) {
|
|
54
|
+
const base = parseInt(address.substring(0, dotIndex));
|
|
55
|
+
const bit = parseInt(address.substring(dotIndex + 1));
|
|
56
|
+
return base * 16 + bit;
|
|
57
|
+
}
|
|
58
|
+
return parseInt(address) * 16;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 重写地址解析方法,将台达地址转换为Modbus地址
|
|
62
|
+
*/
|
|
63
|
+
addr(input, code) {
|
|
64
|
+
console.log('[DeltaTcpNet] addr called with:', input, 'code:', code, 'Series:', this.Series);
|
|
65
|
+
try {
|
|
66
|
+
let text = input.trim();
|
|
67
|
+
let station = this.Station;
|
|
68
|
+
// 提取站号参数 s=2;D100
|
|
69
|
+
const stationMatch = text.match(/^s=(\d+);(.+)$/i);
|
|
70
|
+
if (stationMatch) {
|
|
71
|
+
station = parseInt(stationMatch[1]);
|
|
72
|
+
text = stationMatch[2];
|
|
73
|
+
}
|
|
74
|
+
if (this.Series === DeltaSeries.Dvp) {
|
|
75
|
+
return this.parseDvpAddress(text, station, code);
|
|
76
|
+
}
|
|
77
|
+
else if (this.Series === DeltaSeries.AS) {
|
|
78
|
+
return this.parseASAddress(text, station, code);
|
|
79
|
+
}
|
|
80
|
+
return new Core_1.OperateResult('不支持的PLC系列');
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
console.log('[DeltaTcpNet] Error parsing address:', e.message);
|
|
84
|
+
return new Core_1.OperateResult(e.message);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* DVP系列地址解析
|
|
89
|
+
*/
|
|
90
|
+
parseDvpAddress(text, station, code) {
|
|
91
|
+
// 位操作码:读线圈(01)、写单个线圈(05)、写多个线圈(15)
|
|
92
|
+
if (code === 0x01 || code === 0x05 || code === 0x0F) {
|
|
93
|
+
if (text.match(/^S\d+$/i)) {
|
|
94
|
+
// S0-S999
|
|
95
|
+
const num = parseInt(text.substring(1));
|
|
96
|
+
const result = { station, code: 0x01, address: num, writeCode: 0x0F };
|
|
97
|
+
console.log('[DeltaTcpNet DVP] S register converted to:', result);
|
|
98
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
99
|
+
}
|
|
100
|
+
if (text.match(/^X[0-7]+$/i)) {
|
|
101
|
+
// X输入,八进制
|
|
102
|
+
const num = parseInt(text.substring(1), 8);
|
|
103
|
+
const result = { station, code: 0x02, address: num + 1024 };
|
|
104
|
+
console.log('[DeltaTcpNet DVP] X register converted to:', result);
|
|
105
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
106
|
+
}
|
|
107
|
+
if (text.match(/^Y[0-7]+$/i)) {
|
|
108
|
+
// Y输出,八进制
|
|
109
|
+
const num = parseInt(text.substring(1), 8);
|
|
110
|
+
const result = { station, code: 0x01, address: num + 1280, writeCode: 0x0F };
|
|
111
|
+
console.log('[DeltaTcpNet DVP] Y register converted to:', result);
|
|
112
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
113
|
+
}
|
|
114
|
+
if (text.match(/^T\d+$/i)) {
|
|
115
|
+
// 定时器
|
|
116
|
+
const num = parseInt(text.substring(1));
|
|
117
|
+
const result = { station, code: 0x01, address: num + 1536, writeCode: 0x0F };
|
|
118
|
+
console.log('[DeltaTcpNet DVP] T register converted to:', result);
|
|
119
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
120
|
+
}
|
|
121
|
+
if (text.match(/^C\d+$/i)) {
|
|
122
|
+
// 计数器
|
|
123
|
+
const num = parseInt(text.substring(1));
|
|
124
|
+
const result = { station, code: 0x01, address: num + 3584, writeCode: 0x0F };
|
|
125
|
+
console.log('[DeltaTcpNet DVP] C register converted to:', result);
|
|
126
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
127
|
+
}
|
|
128
|
+
if (text.match(/^M\d+$/i)) {
|
|
129
|
+
// M内部继电器
|
|
130
|
+
const num = parseInt(text.substring(1));
|
|
131
|
+
if (num >= 1536) {
|
|
132
|
+
const result = { station, code: 0x01, address: num - 1536 + 45056, writeCode: 0x0F };
|
|
133
|
+
console.log('[DeltaTcpNet DVP] M register (>=1536) converted to:', result);
|
|
134
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
135
|
+
}
|
|
136
|
+
const result = { station, code: 0x01, address: num + 2048, writeCode: 0x0F };
|
|
137
|
+
console.log('[DeltaTcpNet DVP] M register converted to:', result);
|
|
138
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// 字操作码:读保持寄存器(03)、写单个寄存器(06)、写多个寄存器(16)
|
|
143
|
+
if (text.match(/^D\d+$/i)) {
|
|
144
|
+
// D数据寄存器
|
|
145
|
+
const num = parseInt(text.substring(1));
|
|
146
|
+
const modbusAddr = this.transDAddressToModbusAddress(num);
|
|
147
|
+
const result = { station, code: 0x03, address: modbusAddr, writeCode: 0x10 };
|
|
148
|
+
console.log('[DeltaTcpNet DVP] D' + num + ' converted to modbus address:', modbusAddr, 'result:', result);
|
|
149
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
150
|
+
}
|
|
151
|
+
if (text.match(/^C\d+$/i)) {
|
|
152
|
+
// 计数器当前值
|
|
153
|
+
const num = parseInt(text.substring(1));
|
|
154
|
+
if (num >= 200) {
|
|
155
|
+
const result = { station, code: 0x03, address: num - 200 + 3784, writeCode: 0x10 };
|
|
156
|
+
console.log('[DeltaTcpNet DVP] C register (>=200) converted to:', result);
|
|
157
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
158
|
+
}
|
|
159
|
+
const result = { station, code: 0x03, address: num + 3584, writeCode: 0x10 };
|
|
160
|
+
console.log('[DeltaTcpNet DVP] C register converted to:', result);
|
|
161
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
162
|
+
}
|
|
163
|
+
if (text.match(/^T\d+$/i)) {
|
|
164
|
+
// 定时器当前值
|
|
165
|
+
const num = parseInt(text.substring(1));
|
|
166
|
+
const result = { station, code: 0x03, address: num + 1536, writeCode: 0x10 };
|
|
167
|
+
console.log('[DeltaTcpNet DVP] T register converted to:', result);
|
|
168
|
+
return Core_1.OperateResult.CreateSuccessResult(result);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
console.log('[DeltaTcpNet DVP] Unsupported address type:', text);
|
|
172
|
+
return new Core_1.OperateResult('不支持的地址类型: ' + text);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* AS300系列地址解析
|
|
176
|
+
*/
|
|
177
|
+
parseASAddress(text, station, code) {
|
|
178
|
+
// 位操作码
|
|
179
|
+
if (code === 0x01 || code === 0x05 || code === 0x0F) {
|
|
180
|
+
if (text.match(/^SM\d+$/i)) {
|
|
181
|
+
const num = parseInt(text.substring(2));
|
|
182
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num + 16384, writeCode: 0x0F });
|
|
183
|
+
}
|
|
184
|
+
if (text.match(/^HC\d+$/i)) {
|
|
185
|
+
const num = parseInt(text.substring(2));
|
|
186
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num + 64512, writeCode: 0x0F });
|
|
187
|
+
}
|
|
188
|
+
if (text.match(/^S\d+$/i)) {
|
|
189
|
+
const num = parseInt(text.substring(1));
|
|
190
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num + 20480, writeCode: 0x0F });
|
|
191
|
+
}
|
|
192
|
+
if (text.match(/^X[\d.]+$/i)) {
|
|
193
|
+
const bitAddr = this.parseDeltaBitAddress(text.substring(1));
|
|
194
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x02, address: bitAddr + 24576 });
|
|
195
|
+
}
|
|
196
|
+
if (text.match(/^Y[\d.]+$/i)) {
|
|
197
|
+
const bitAddr = this.parseDeltaBitAddress(text.substring(1));
|
|
198
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: bitAddr + 40960, writeCode: 0x0F });
|
|
199
|
+
}
|
|
200
|
+
if (text.match(/^T\d+$/i)) {
|
|
201
|
+
const num = parseInt(text.substring(1));
|
|
202
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num + 57344, writeCode: 0x0F });
|
|
203
|
+
}
|
|
204
|
+
if (text.match(/^C\d+$/i)) {
|
|
205
|
+
const num = parseInt(text.substring(1));
|
|
206
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num + 61440, writeCode: 0x0F });
|
|
207
|
+
}
|
|
208
|
+
if (text.match(/^M\d+$/i)) {
|
|
209
|
+
const num = parseInt(text.substring(1));
|
|
210
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: num, writeCode: 0x0F });
|
|
211
|
+
}
|
|
212
|
+
if (text.match(/^D\d+\.\d+$/i)) {
|
|
213
|
+
// D寄存器位地址,直接传递
|
|
214
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x01, address: 0, writeCode: 0x0F });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// 字操作码
|
|
219
|
+
if (text.match(/^SR\d+$/i)) {
|
|
220
|
+
const num = parseInt(text.substring(2));
|
|
221
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num + 49152, writeCode: 0x10 });
|
|
222
|
+
}
|
|
223
|
+
if (text.match(/^HC\d+$/i)) {
|
|
224
|
+
const num = parseInt(text.substring(2));
|
|
225
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num + 64512, writeCode: 0x10 });
|
|
226
|
+
}
|
|
227
|
+
if (text.match(/^D\d+$/i)) {
|
|
228
|
+
const num = parseInt(text.substring(1));
|
|
229
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num, writeCode: 0x10 });
|
|
230
|
+
}
|
|
231
|
+
if (text.match(/^X\d+$/i)) {
|
|
232
|
+
const num = parseInt(text.substring(1));
|
|
233
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x04, address: num + 32768 });
|
|
234
|
+
}
|
|
235
|
+
if (text.match(/^Y\d+$/i)) {
|
|
236
|
+
const num = parseInt(text.substring(1));
|
|
237
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num + 40960, writeCode: 0x10 });
|
|
238
|
+
}
|
|
239
|
+
if (text.match(/^C\d+$/i)) {
|
|
240
|
+
const num = parseInt(text.substring(1));
|
|
241
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num + 61440, writeCode: 0x10 });
|
|
242
|
+
}
|
|
243
|
+
if (text.match(/^T\d+$/i)) {
|
|
244
|
+
const num = parseInt(text.substring(1));
|
|
245
|
+
return Core_1.OperateResult.CreateSuccessResult({ station, code: 0x03, address: num + 57344, writeCode: 0x10 });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return new Core_1.OperateResult('不支持的地址类型: ' + text);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 读取bool数组,针对DVP系列M地址跨1536的情况进行特殊处理
|
|
252
|
+
*/
|
|
253
|
+
async ReadBool(address, length) {
|
|
254
|
+
const count = length ?? 1;
|
|
255
|
+
if (this.Series === DeltaSeries.Dvp) {
|
|
256
|
+
// 提取站号
|
|
257
|
+
let cleanAddress = address;
|
|
258
|
+
const stationMatch = address.match(/^s=(\d+);(.+)$/i);
|
|
259
|
+
if (stationMatch) {
|
|
260
|
+
cleanAddress = stationMatch[2];
|
|
261
|
+
}
|
|
262
|
+
// 检查M地址是否跨越1536边界
|
|
263
|
+
if (cleanAddress.match(/^M\d+$/i)) {
|
|
264
|
+
const startAddr = parseInt(cleanAddress.substring(1));
|
|
265
|
+
if (startAddr < 1536 && startAddr + count > 1536) {
|
|
266
|
+
// 需要分割读取
|
|
267
|
+
const firstLength = 1536 - startAddr;
|
|
268
|
+
const secondLength = count - firstLength;
|
|
269
|
+
const result1 = await super.ReadBool(address, firstLength);
|
|
270
|
+
if (!result1.IsSuccess)
|
|
271
|
+
return result1;
|
|
272
|
+
const stationPrefix = stationMatch ? `s=${stationMatch[1]};` : '';
|
|
273
|
+
const result2 = await super.ReadBool(stationPrefix + 'M1536', secondLength);
|
|
274
|
+
if (!result2.IsSuccess)
|
|
275
|
+
return result2;
|
|
276
|
+
const combined = [...result1.Content, ...result2.Content];
|
|
277
|
+
return Core_1.OperateResult.CreateSuccessResult(combined);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return super.ReadBool(address, count);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 写入bool数组,针对DVP系列M地址跨1536的情况进行特殊处理
|
|
285
|
+
*/
|
|
286
|
+
async Write(address, value) {
|
|
287
|
+
if (typeof value === 'boolean' || (Array.isArray(value) && typeof value[0] === 'boolean')) {
|
|
288
|
+
const values = Array.isArray(value) ? value : [value];
|
|
289
|
+
if (this.Series === DeltaSeries.Dvp) {
|
|
290
|
+
let cleanAddress = address;
|
|
291
|
+
const stationMatch = address.match(/^s=(\d+);(.+)$/i);
|
|
292
|
+
if (stationMatch) {
|
|
293
|
+
cleanAddress = stationMatch[2];
|
|
294
|
+
}
|
|
295
|
+
// 检查M地址是否跨越1536边界
|
|
296
|
+
if (cleanAddress.match(/^M\d+$/i)) {
|
|
297
|
+
const startAddr = parseInt(cleanAddress.substring(1));
|
|
298
|
+
if (startAddr < 1536 && startAddr + values.length > 1536) {
|
|
299
|
+
const firstLength = 1536 - startAddr;
|
|
300
|
+
const firstValues = values.slice(0, firstLength);
|
|
301
|
+
const secondValues = values.slice(firstLength);
|
|
302
|
+
const result1 = await super.Write(address, firstValues);
|
|
303
|
+
if (!result1.IsSuccess)
|
|
304
|
+
return result1;
|
|
305
|
+
const stationPrefix = stationMatch ? `s=${stationMatch[1]};` : '';
|
|
306
|
+
return super.Write(stationPrefix + 'M1536', secondValues);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return super.Write(address, value);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* 读取数据,针对DVP系列D地址跨4096的情况进行特殊处理
|
|
315
|
+
*/
|
|
316
|
+
async Read(address, length) {
|
|
317
|
+
if (this.Series === DeltaSeries.Dvp) {
|
|
318
|
+
let cleanAddress = address;
|
|
319
|
+
const stationMatch = address.match(/^s=(\d+);(.+)$/i);
|
|
320
|
+
if (stationMatch) {
|
|
321
|
+
cleanAddress = stationMatch[2];
|
|
322
|
+
}
|
|
323
|
+
// 检查D地址是否跨越4096边界
|
|
324
|
+
if (cleanAddress.match(/^D\d+$/i)) {
|
|
325
|
+
const startAddr = parseInt(cleanAddress.substring(1));
|
|
326
|
+
if (startAddr < 4096 && startAddr + length > 4096) {
|
|
327
|
+
const firstLength = 4096 - startAddr;
|
|
328
|
+
const secondLength = length - firstLength;
|
|
329
|
+
const result1 = await super.Read(address, firstLength);
|
|
330
|
+
if (!result1.IsSuccess)
|
|
331
|
+
return result1;
|
|
332
|
+
const stationPrefix = stationMatch ? `s=${stationMatch[1]};` : '';
|
|
333
|
+
const result2 = await super.Read(stationPrefix + 'D4096', secondLength);
|
|
334
|
+
if (!result2.IsSuccess)
|
|
335
|
+
return result2;
|
|
336
|
+
return Core_1.OperateResult.CreateSuccessResult(Buffer.concat([result1.Content, result2.Content]));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return super.Read(address, length);
|
|
341
|
+
}
|
|
342
|
+
toString() {
|
|
343
|
+
return `DeltaTcpNet[${this.IpAddress}:${this.Port}]`;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
exports.DeltaTcpNet = DeltaTcpNet;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ByteTransform, DataFormat, DeviceClient, OperateResult } from '../core/Core';
|
|
2
|
+
import { GeSRTPMessage } from '../core/INetMessage';
|
|
3
|
+
export interface GeSRTPAddress {
|
|
4
|
+
DataCode: number;
|
|
5
|
+
AddressStart: number;
|
|
6
|
+
Length: number;
|
|
7
|
+
IsBit: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** 解析 GE 地址。PLC 地址从 1 开始,报文内部从 0 开始。 */
|
|
10
|
+
export declare function parseGeSRTPAddress(input: string, length: number, isBit: boolean): OperateResult<GeSRTPAddress>;
|
|
11
|
+
export declare class GeSRTPNet extends DeviceClient {
|
|
12
|
+
ByteTransform: ByteTransform;
|
|
13
|
+
private messageId;
|
|
14
|
+
private initializedSocket?;
|
|
15
|
+
constructor(ipAddress?: string, port?: number);
|
|
16
|
+
get DataFormat(): DataFormat;
|
|
17
|
+
set DataFormat(value: DataFormat);
|
|
18
|
+
protected GetNewNetMessage(): GeSRTPMessage;
|
|
19
|
+
ConnectServer(): Promise<OperateResult<any>>;
|
|
20
|
+
ConnectClose(): Promise<OperateResult<any>>;
|
|
21
|
+
private nextId;
|
|
22
|
+
private transact;
|
|
23
|
+
Read(address: string, length: number): Promise<OperateResult<Buffer>>;
|
|
24
|
+
ReadBool(address: string, length?: number): Promise<OperateResult<boolean | boolean[]>>;
|
|
25
|
+
ReadByte(address: string): Promise<OperateResult<number>>;
|
|
26
|
+
private typedRead;
|
|
27
|
+
ReadInt16(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
28
|
+
ReadUInt16(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
29
|
+
ReadInt32(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
30
|
+
ReadUInt32(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
31
|
+
ReadFloat(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
32
|
+
ReadDouble(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
33
|
+
ReadInt64(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
34
|
+
ReadUInt64(a: string, l?: number): Promise<OperateResult<unknown>>;
|
|
35
|
+
ReadString(address: string, length: number, encoding?: BufferEncoding): Promise<OperateResult<string>>;
|
|
36
|
+
Write(address: string, value: number | boolean | string | Buffer | number[] | boolean[]): Promise<OperateResult<any>>;
|
|
37
|
+
WriteByte(a: string, v: number): OperateResult<unknown> | Promise<OperateResult<any>>;
|
|
38
|
+
WriteInt16(a: string, v: number): Promise<OperateResult<any>>;
|
|
39
|
+
WriteUInt16(a: string, v: number): Promise<OperateResult<any>>;
|
|
40
|
+
WriteInt32(a: string, v: number): Promise<OperateResult<any>>;
|
|
41
|
+
WriteUInt32(a: string, v: number): Promise<OperateResult<any>>;
|
|
42
|
+
WriteFloat(a: string, v: number): Promise<OperateResult<any>>;
|
|
43
|
+
WriteDouble(a: string, v: number): Promise<OperateResult<any>>;
|
|
44
|
+
WriteInt64(a: string, v: bigint | number): Promise<OperateResult<any>>;
|
|
45
|
+
WriteUInt64(a: string, v: bigint | number): Promise<OperateResult<any>>;
|
|
46
|
+
ConnectServerAsync(): Promise<OperateResult<any>>;
|
|
47
|
+
ConnectCloseAsync(): Promise<OperateResult<any>>;
|
|
48
|
+
toString(): string;
|
|
49
|
+
}
|