@iobroker/modbus 7.0.2

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/build/convert.d.ts +2 -0
  4. package/build/convert.js +102 -0
  5. package/build/convert.js.map +1 -0
  6. package/build/index.d.ts +88 -0
  7. package/build/index.js +1005 -0
  8. package/build/index.js.map +1 -0
  9. package/build/lib/Master.d.ts +27 -0
  10. package/build/lib/Master.js +811 -0
  11. package/build/lib/Master.js.map +1 -0
  12. package/build/lib/Put.d.ts +19 -0
  13. package/build/lib/Put.js +113 -0
  14. package/build/lib/Put.js.map +1 -0
  15. package/build/lib/Slave.d.ts +15 -0
  16. package/build/lib/Slave.js +545 -0
  17. package/build/lib/Slave.js.map +1 -0
  18. package/build/lib/common.d.ts +3 -0
  19. package/build/lib/common.js +371 -0
  20. package/build/lib/common.js.map +1 -0
  21. package/build/lib/crc16modbus.d.ts +1 -0
  22. package/build/lib/crc16modbus.js +33 -0
  23. package/build/lib/crc16modbus.js.map +1 -0
  24. package/build/lib/jsmodbus/modbus-client-core.d.ts +78 -0
  25. package/build/lib/jsmodbus/modbus-client-core.js +528 -0
  26. package/build/lib/jsmodbus/modbus-client-core.js.map +1 -0
  27. package/build/lib/jsmodbus/modbus-server-core.d.ts +33 -0
  28. package/build/lib/jsmodbus/modbus-server-core.js +363 -0
  29. package/build/lib/jsmodbus/modbus-server-core.js.map +1 -0
  30. package/build/lib/jsmodbus/transports/errors.d.ts +7 -0
  31. package/build/lib/jsmodbus/transports/errors.js +40 -0
  32. package/build/lib/jsmodbus/transports/errors.js.map +1 -0
  33. package/build/lib/jsmodbus/transports/modbus-client-serial.d.ts +23 -0
  34. package/build/lib/jsmodbus/transports/modbus-client-serial.js +154 -0
  35. package/build/lib/jsmodbus/transports/modbus-client-serial.js.map +1 -0
  36. package/build/lib/jsmodbus/transports/modbus-client-tcp-rtu.d.ts +24 -0
  37. package/build/lib/jsmodbus/transports/modbus-client-tcp-rtu.js +166 -0
  38. package/build/lib/jsmodbus/transports/modbus-client-tcp-rtu.js.map +1 -0
  39. package/build/lib/jsmodbus/transports/modbus-client-tcp-ssl.d.ts +34 -0
  40. package/build/lib/jsmodbus/transports/modbus-client-tcp-ssl.js +138 -0
  41. package/build/lib/jsmodbus/transports/modbus-client-tcp-ssl.js.map +1 -0
  42. package/build/lib/jsmodbus/transports/modbus-client-tcp.d.ts +27 -0
  43. package/build/lib/jsmodbus/transports/modbus-client-tcp.js +123 -0
  44. package/build/lib/jsmodbus/transports/modbus-client-tcp.js.map +1 -0
  45. package/build/lib/jsmodbus/transports/modbus-server-serial.d.ts +29 -0
  46. package/build/lib/jsmodbus/transports/modbus-server-serial.js +206 -0
  47. package/build/lib/jsmodbus/transports/modbus-server-serial.js.map +1 -0
  48. package/build/lib/jsmodbus/transports/modbus-server-tcp.d.ts +25 -0
  49. package/build/lib/jsmodbus/transports/modbus-server-tcp.js +112 -0
  50. package/build/lib/jsmodbus/transports/modbus-server-tcp.js.map +1 -0
  51. package/build/lib/loggingUtils.d.ts +11 -0
  52. package/build/lib/loggingUtils.js +37 -0
  53. package/build/lib/loggingUtils.js.map +1 -0
  54. package/package.json +68 -0
@@ -0,0 +1,24 @@
1
+ import ModbusClientCore from '../modbus-client-core';
2
+ export default class ModbusClientTcpRtu extends ModbusClientCore {
3
+ #private;
4
+ private closedOnPurpose;
5
+ private buffer;
6
+ private socket;
7
+ private tcp;
8
+ private readonly unitId;
9
+ constructor(options: {
10
+ tcp: {
11
+ host?: string;
12
+ port?: number;
13
+ protocolVersion?: number;
14
+ autoReconnect?: boolean;
15
+ reconnectTimeout?: number;
16
+ };
17
+ unitId?: number;
18
+ logger: ioBroker.Logger;
19
+ timeout?: number;
20
+ });
21
+ connect(): void;
22
+ reconnect(): void;
23
+ close(): void;
24
+ }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Put_1 = __importDefault(require("../../Put"));
7
+ const crc16modbus_1 = __importDefault(require("../../crc16modbus"));
8
+ const node_net_1 = require("node:net");
9
+ const modbus_client_core_1 = __importDefault(require("../modbus-client-core"));
10
+ const errors_1 = __importDefault(require("./errors"));
11
+ function toStrArray(buf) {
12
+ if (!buf?.length) {
13
+ return '';
14
+ }
15
+ let text = '';
16
+ for (let i = 0; i < buf.length; i++) {
17
+ text += (text ? ',' : '') + buf[i];
18
+ }
19
+ return text;
20
+ }
21
+ class ModbusClientTcpRtu extends modbus_client_core_1.default {
22
+ closedOnPurpose = false;
23
+ #reconnect = false;
24
+ buffer = Buffer.alloc(0);
25
+ socket = null;
26
+ tcp;
27
+ unitId;
28
+ constructor(options) {
29
+ super(options);
30
+ this.setState('init');
31
+ this.tcp = options.tcp;
32
+ this.unitId = options.unitId || 1;
33
+ this.tcp.protocolVersion ||= 0;
34
+ this.tcp.port ||= 502;
35
+ this.tcp.host ||= 'localhost';
36
+ this.tcp.autoReconnect ||= false;
37
+ this.tcp.reconnectTimeout ||= 0;
38
+ this.on('send', this.#onSend);
39
+ this.on('newState_error', this.#onError);
40
+ }
41
+ #onSocketConnect = () => {
42
+ this.emit('connect');
43
+ this.setState('ready');
44
+ };
45
+ #onSocketClose = (hadErrors) => {
46
+ this.log.debug(hadErrors ? 'Socket closed with error' : 'Socket closed');
47
+ this.setState('closed');
48
+ this.emit('close');
49
+ if (!this.closedOnPurpose && (this.tcp.autoReconnect || this.#reconnect)) {
50
+ setTimeout(() => {
51
+ this.#reconnect = false;
52
+ this.connect();
53
+ }, this.tcp.reconnectTimeout);
54
+ }
55
+ };
56
+ #onSocketError = (err) => {
57
+ this.log.error(`Socket Error ${err}`);
58
+ this.setState('error');
59
+ this.emit('error', err);
60
+ };
61
+ #onSocketData = (data) => {
62
+ this.buffer = Buffer.concat([this.buffer, data]);
63
+ while (this.buffer.length > 4) {
64
+ // 1. there is no mbap
65
+ // 2. extract pdu
66
+ // 0 - device ID
67
+ // 1 - Function CODE
68
+ // 2 - Bytes length
69
+ // 3.. Data
70
+ // checksum.(2 bytes
71
+ let len;
72
+ let pdu;
73
+ // if response for write
74
+ if (this.buffer[1] === 5 || this.buffer[1] === 6 || this.buffer[1] === 15 || this.buffer[1] === 16) {
75
+ if (this.buffer.length < 8) {
76
+ break;
77
+ }
78
+ pdu = this.buffer.slice(0, 8); // 1 byte device ID + 1 byte FC + 2 bytes address + 2 bytes value + 2 bytes CRC
79
+ }
80
+ else if (this.buffer[1] > 0 && this.buffer[1] < 5) {
81
+ len = this.buffer[2];
82
+ if (this.buffer.length < len + 5) {
83
+ break;
84
+ }
85
+ pdu = this.buffer.slice(0, len + 5); // 1 byte deviceID + 1 byte FC + 1 byte length + 2 bytes CRC
86
+ }
87
+ else {
88
+ if (this.buffer[1] & 0x80) {
89
+ const errorCode = this.buffer[2];
90
+ // error code
91
+ if (errorCode && errors_1.default[errorCode]) {
92
+ this.log.error(`Error response for FCx${this.buffer[1] & 0x7f}: ${errors_1.default[errorCode].name}`);
93
+ this.log.error(`Error response: ${errors_1.default[errorCode].desc}`);
94
+ }
95
+ else {
96
+ this.log.error(`Error response: ${errorCode.toString(16)}`);
97
+ }
98
+ }
99
+ else {
100
+ // unknown function code
101
+ this.log.error(`unknown function code: 0x${this.buffer[1].toString(16)}, 0x${this.buffer[2].toString(16)}`);
102
+ }
103
+ // reset buffer and try again
104
+ this.buffer = Buffer.alloc(0);
105
+ break;
106
+ }
107
+ if (!(0, crc16modbus_1.default)(pdu)) {
108
+ /* PDU is valid if CRC across whole PDU equals 0, else ignore and do nothing */
109
+ if (this.unitId !== undefined && pdu[0] !== this.unitId) {
110
+ // answer for a wrong device
111
+ this.log.debug(`received answer for wrong ID ${this.buffer[0]}, expected ${this.unitId}`);
112
+ }
113
+ // emit data event and let the
114
+ // listener handle the pdu
115
+ this.emit('data', pdu.slice(1, pdu.length - 2), pdu[0]);
116
+ }
117
+ else {
118
+ this.log.error(`Wrong CRC for frame: ${toStrArray(pdu)}`);
119
+ // reset buffer and try again
120
+ this.buffer = Buffer.alloc(0);
121
+ break;
122
+ }
123
+ this.buffer = this.buffer.slice(pdu.length, this.buffer.length);
124
+ }
125
+ };
126
+ #onError = () => {
127
+ this.log.error('Client in error state.');
128
+ this.socket?.destroy();
129
+ };
130
+ #onSend = (pdu, unitId) => {
131
+ this.log.debug('Sending pdu to the socket.');
132
+ const pkt = new Put_1.default()
133
+ .word8((unitId === undefined ? this.unitId : unitId) || 0) // unit id
134
+ .put(pdu); // the actual pdu
135
+ const buf = pkt.buffer();
136
+ const crc16 = (0, crc16modbus_1.default)(buf);
137
+ this.socket?.write(pkt.word16le(crc16).buffer());
138
+ };
139
+ connect() {
140
+ this.setState('connect');
141
+ if (!this.socket) {
142
+ this.socket = new node_net_1.Socket();
143
+ this.socket.on('connect', this.#onSocketConnect);
144
+ this.socket.on('close', this.#onSocketClose);
145
+ this.socket.on('error', this.#onSocketError);
146
+ this.socket.on('data', this.#onSocketData);
147
+ }
148
+ this.socket.connect(this.tcp.port, this.tcp.host);
149
+ }
150
+ reconnect() {
151
+ if (!this.inState('closed')) {
152
+ return;
153
+ }
154
+ this.closedOnPurpose = false;
155
+ this.#reconnect = true;
156
+ this.log.debug('Reconnecting client.');
157
+ this.socket?.end();
158
+ }
159
+ close() {
160
+ this.closedOnPurpose = true;
161
+ this.log.debug('Closing client on purpose.');
162
+ this.socket?.end();
163
+ }
164
+ }
165
+ exports.default = ModbusClientTcpRtu;
166
+ //# sourceMappingURL=modbus-client-tcp-rtu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modbus-client-tcp-rtu.js","sourceRoot":"","sources":["../../../../src/lib/jsmodbus/transports/modbus-client-tcp-rtu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import ModbusClientCore from '../modbus-client-core';
2
+ export default class ModbusClientTcpSsl extends ModbusClientCore {
3
+ #private;
4
+ private reqId;
5
+ private currentRequestId;
6
+ private closedOnPurpose;
7
+ private buffer;
8
+ private trashRequestId;
9
+ private socket;
10
+ private tcp;
11
+ private ssl;
12
+ private unitId;
13
+ constructor(options: {
14
+ tcp: {
15
+ host: string;
16
+ port: number;
17
+ protocolVersion?: number;
18
+ autoReconnect?: boolean;
19
+ reconnectTimeout?: number;
20
+ };
21
+ ssl: {
22
+ rejectUnauthorized?: boolean;
23
+ key: string;
24
+ cert: string;
25
+ ca?: string;
26
+ };
27
+ unitId?: number;
28
+ logger: ioBroker.Logger;
29
+ timeout?: number;
30
+ });
31
+ connect(): void;
32
+ reconnect(): void;
33
+ close(): void;
34
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_tls_1 = require("node:tls");
7
+ const modbus_client_core_1 = __importDefault(require("../modbus-client-core"));
8
+ const Put_1 = __importDefault(require("../../Put"));
9
+ class ModbusClientTcpSsl extends modbus_client_core_1.default {
10
+ reqId = 0;
11
+ currentRequestId = 0;
12
+ closedOnPurpose = false;
13
+ #reconnect = false;
14
+ buffer = Buffer.alloc(0);
15
+ trashRequestId;
16
+ socket = null;
17
+ tcp;
18
+ ssl;
19
+ unitId;
20
+ constructor(options) {
21
+ super(options);
22
+ this.setState('init');
23
+ this.tcp = options.tcp;
24
+ this.ssl = options.ssl;
25
+ this.unitId = options.unitId || 1;
26
+ this.on('send', this.#onSend);
27
+ this.on('newState_error', this.#onError);
28
+ this.on('trashCurrentRequest', this.#onTrashCurrentRequest);
29
+ }
30
+ #onSocketConnect = () => {
31
+ this.log.debug('SSL/TLS connection established');
32
+ // Log certificate information for debugging
33
+ if (this.socket?.getPeerCertificate) {
34
+ const cert = this.socket.getPeerCertificate();
35
+ if (cert?.subject) {
36
+ this.log.debug(`Connected to SSL server with certificate subject: ${cert.subject.CN || 'Unknown'}`);
37
+ }
38
+ }
39
+ this.emit('connect');
40
+ this.setState('ready');
41
+ };
42
+ #onSocketClose = (hadErrors) => {
43
+ this.log.debug(hadErrors ? 'SSL/TLS socket closed with error' : 'SSL/TLS socket closed');
44
+ this.setState('closed');
45
+ this.emit('close');
46
+ if (!this.closedOnPurpose && (this.tcp.autoReconnect || this.#reconnect)) {
47
+ setTimeout(() => {
48
+ this.#reconnect = false;
49
+ this.connect();
50
+ }, this.tcp.reconnectTimeout);
51
+ }
52
+ };
53
+ #onSocketError = (err) => {
54
+ this.log.error(`SSL/TLS Socket Error${err}`);
55
+ this.setState('error');
56
+ this.emit('error', err);
57
+ };
58
+ #onSocketData = (data) => {
59
+ this.buffer = Buffer.concat([this.buffer, data]);
60
+ while (this.buffer.length > 8) {
61
+ // http://www.simplymodbus.ca/TCP.htm
62
+ // 1. extract mbap
63
+ const id = this.buffer.readUInt16BE(0);
64
+ //const protId = buffer.readUInt16BE(2);
65
+ const len = this.buffer.readUInt16BE(4);
66
+ const unitId = this.buffer.readUInt8(6);
67
+ // 2. extract pdu
68
+ if (this.buffer.length < 7 + len - 1) {
69
+ break;
70
+ }
71
+ const pdu = this.buffer.slice(7, 7 + len - 1);
72
+ if (id === this.trashRequestId) {
73
+ this.log.debug('current mbap contains trashed request id.');
74
+ }
75
+ else {
76
+ // emit data event and let the
77
+ // listener handle the pdu
78
+ this.emit('data', pdu, unitId);
79
+ }
80
+ this.buffer = this.buffer.slice(pdu.length + 7, this.buffer.length);
81
+ }
82
+ };
83
+ #onError = () => {
84
+ this.log.error(`SSL/TLS Client in error state.`);
85
+ this.socket?.destroy();
86
+ };
87
+ #onSend = (pdu, unitId) => {
88
+ this.reqId = (this.reqId + 1) % 0xffff;
89
+ const pkt = new Put_1.default()
90
+ .word16be(this.reqId) // transaction id
91
+ .word16be(this.tcp.protocolVersion) // protocol version
92
+ .word16be(pdu.length + 1) // pdu length
93
+ .word8((unitId === undefined ? this.unitId : unitId) || 0) // unit id
94
+ .put(pdu) // the actual pdu
95
+ .buffer();
96
+ this.currentRequestId = this.reqId;
97
+ this.socket?.write(pkt);
98
+ };
99
+ #onTrashCurrentRequest = () => {
100
+ this.trashRequestId = this.currentRequestId;
101
+ };
102
+ connect() {
103
+ this.setState('connect');
104
+ if (!this.socket) {
105
+ // Prepare SSL/TLS options
106
+ const sslOptions = {
107
+ host: this.tcp.host,
108
+ port: this.tcp.port,
109
+ rejectUnauthorized: this.ssl?.rejectUnauthorized !== false,
110
+ };
111
+ // Load SSL certificates if provided
112
+ sslOptions.cert = this.ssl.cert;
113
+ sslOptions.key = this.ssl.key;
114
+ sslOptions.ca = this.ssl.ca;
115
+ this.socket = (0, node_tls_1.connect)(sslOptions);
116
+ this.socket.on('secureConnect', this.#onSocketConnect);
117
+ this.socket.on('close', this.#onSocketClose);
118
+ this.socket.on('error', this.#onSocketError);
119
+ this.socket.on('data', this.#onSocketData);
120
+ }
121
+ }
122
+ reconnect() {
123
+ if (!this.inState('closed')) {
124
+ return;
125
+ }
126
+ this.closedOnPurpose = false;
127
+ this.#reconnect = true;
128
+ this.log.debug('Reconnecting SSL/TLS client.');
129
+ this.socket?.end();
130
+ }
131
+ close() {
132
+ this.closedOnPurpose = true;
133
+ this.log.debug('Closing SSL/TLS client on purpose.');
134
+ this.socket?.end();
135
+ }
136
+ }
137
+ exports.default = ModbusClientTcpSsl;
138
+ //# sourceMappingURL=modbus-client-tcp-ssl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modbus-client-tcp-ssl.js","sourceRoot":"","sources":["../../../../src/lib/jsmodbus/transports/modbus-client-tcp-ssl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import ModbusClientCore from '../modbus-client-core';
2
+ export default class ModbusClientTCP extends ModbusClientCore {
3
+ #private;
4
+ private reqId;
5
+ private currentRequestId;
6
+ private closedOnPurpose;
7
+ private buffer;
8
+ private trashRequestId;
9
+ private socket;
10
+ private tcp;
11
+ private unitId;
12
+ constructor(options: {
13
+ tcp: {
14
+ host?: string;
15
+ port?: number;
16
+ protocolVersion?: number;
17
+ autoReconnect?: boolean;
18
+ reconnectTimeout?: number;
19
+ };
20
+ unitId?: number;
21
+ logger: ioBroker.Logger;
22
+ timeout?: number;
23
+ });
24
+ connect(): void;
25
+ reconnect(): void;
26
+ close(): void;
27
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Put_1 = __importDefault(require("../../Put"));
7
+ const node_net_1 = require("node:net");
8
+ const modbus_client_core_1 = __importDefault(require("../modbus-client-core"));
9
+ class ModbusClientTCP extends modbus_client_core_1.default {
10
+ reqId = 0;
11
+ currentRequestId = 0;
12
+ closedOnPurpose = false;
13
+ #reconnect = false;
14
+ buffer = Buffer.alloc(0);
15
+ trashRequestId;
16
+ socket = null;
17
+ tcp;
18
+ unitId;
19
+ constructor(options) {
20
+ super(options);
21
+ this.setState('init');
22
+ this.tcp = options.tcp;
23
+ this.unitId = options.unitId || 1;
24
+ this.tcp.protocolVersion ||= 0;
25
+ this.tcp.port ||= 502;
26
+ this.tcp.host ||= 'localhost';
27
+ this.tcp.autoReconnect ||= false;
28
+ this.tcp.reconnectTimeout ||= 0;
29
+ this.on('send', this.#onSend);
30
+ this.on('newState_error', this.#onError);
31
+ this.on('trashCurrentRequest', this.#onTrashCurrentRequest);
32
+ }
33
+ #onSocketConnect = () => {
34
+ this.emit('connect');
35
+ this.setState('ready');
36
+ };
37
+ #onSocketClose = (hadErrors) => {
38
+ this.log.debug(hadErrors ? 'Socket closed with error' : 'Socket closed');
39
+ this.setState('closed');
40
+ this.emit('close');
41
+ if (!this.closedOnPurpose && (this.tcp.autoReconnect || this.#reconnect)) {
42
+ setTimeout(() => {
43
+ this.#reconnect = false;
44
+ this.connect();
45
+ }, this.tcp.reconnectTimeout);
46
+ }
47
+ };
48
+ #onSocketError = (err) => {
49
+ this.log.error(`Socket Error ${err}`);
50
+ this.setState('error');
51
+ this.emit('error', err);
52
+ };
53
+ #onSocketData = (data) => {
54
+ this.buffer = Buffer.concat([this.buffer, data]);
55
+ while (this.buffer.length > 8) {
56
+ // http://www.simplymodbus.ca/TCP.htm
57
+ // 1. extract mbap
58
+ const id = this.buffer.readUInt16BE(0);
59
+ const len = this.buffer.readUInt16BE(4);
60
+ const unitId = this.buffer.readUInt8(6);
61
+ // 2. extract pdu
62
+ if (this.buffer.length < 7 + len - 1) {
63
+ break;
64
+ }
65
+ const pdu = this.buffer.slice(7, 7 + len - 1);
66
+ if (id === this.trashRequestId) {
67
+ this.log.debug('current mbap contains trashed request id.');
68
+ }
69
+ else {
70
+ // emit data event and let the
71
+ // listener handle the pdu
72
+ this.emit('data', pdu, unitId);
73
+ }
74
+ this.buffer = this.buffer.slice(pdu.length + 7, this.buffer.length);
75
+ }
76
+ };
77
+ #onError = () => {
78
+ this.log.error(`Client in error state.`);
79
+ this.socket?.destroy();
80
+ };
81
+ #onSend = (pdu, unitId) => {
82
+ this.reqId = (this.reqId + 1) % 0xffff;
83
+ const pkt = new Put_1.default()
84
+ .word16be(this.reqId) // transaction id
85
+ .word16be(this.tcp.protocolVersion) // protocol version
86
+ .word16be(pdu.length + 1) // pdu length
87
+ .word8((unitId === undefined ? this.unitId : unitId) || 0) // unit id
88
+ .put(pdu) // the actual pdu
89
+ .buffer();
90
+ this.currentRequestId = this.reqId;
91
+ this.socket?.write(pkt);
92
+ };
93
+ #onTrashCurrentRequest = () => {
94
+ this.trashRequestId = this.currentRequestId;
95
+ };
96
+ connect() {
97
+ this.setState('connect');
98
+ if (!this.socket) {
99
+ this.socket = new node_net_1.Socket();
100
+ this.socket.on('connect', this.#onSocketConnect);
101
+ this.socket.on('close', this.#onSocketClose);
102
+ this.socket.on('error', this.#onSocketError);
103
+ this.socket.on('data', this.#onSocketData);
104
+ }
105
+ this.socket.connect(this.tcp.port, this.tcp.host);
106
+ }
107
+ reconnect() {
108
+ if (!this.inState('closed')) {
109
+ return;
110
+ }
111
+ this.closedOnPurpose = false;
112
+ this.#reconnect = true;
113
+ this.log.debug('Reconnecting client.');
114
+ this.socket?.end();
115
+ }
116
+ close() {
117
+ this.closedOnPurpose = true;
118
+ this.log.debug('Closing client on purpose.');
119
+ this.socket?.end();
120
+ }
121
+ }
122
+ exports.default = ModbusClientTCP;
123
+ //# sourceMappingURL=modbus-client-tcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modbus-client-tcp.js","sourceRoot":"","sources":["../../../../src/lib/jsmodbus/transports/modbus-client-tcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import ModbusServerCore from '../modbus-server-core';
2
+ export default class ModbusServerSerial extends ModbusServerCore {
3
+ #private;
4
+ private buffer;
5
+ private fifo;
6
+ private serialPort;
7
+ private readonly deviceId;
8
+ private serial;
9
+ constructor(options: {
10
+ serial: {
11
+ portName: string;
12
+ baudRate?: number;
13
+ dataBits?: 5 | 6 | 7 | 8;
14
+ stopBits?: 1 | 2;
15
+ parity?: 'none' | 'even' | 'mark' | 'odd' | 'space';
16
+ };
17
+ deviceId?: number;
18
+ logger: ioBroker.Logger;
19
+ timeout?: number;
20
+ responseDelay?: number;
21
+ coils?: Buffer;
22
+ holding?: Buffer;
23
+ input?: Buffer;
24
+ discrete?: Buffer;
25
+ });
26
+ getExpectedFrameLength: (functionCode: number, buffer: Buffer) => number;
27
+ close(cb?: (err?: Error | null) => void): void;
28
+ getClients(): string[];
29
+ }