njs-modbus 1.4.0 → 2.0.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 (59) hide show
  1. package/README.md +27 -11
  2. package/dist/index.cjs +2117 -1243
  3. package/dist/index.d.ts +312 -87
  4. package/dist/index.mjs +2110 -1244
  5. package/dist/src/error-code.d.ts +27 -1
  6. package/dist/src/index.d.ts +2 -0
  7. package/dist/src/layers/application/abstract-application-layer.d.ts +11 -8
  8. package/dist/src/layers/application/ascii-application-layer.d.ts +14 -10
  9. package/dist/src/layers/application/index.d.ts +2 -0
  10. package/dist/src/layers/application/rtu-application-layer.d.ts +52 -18
  11. package/dist/src/layers/application/tcp-application-layer.d.ts +4 -8
  12. package/dist/src/layers/physical/abstract-physical-layer.d.ts +5 -1
  13. package/dist/src/layers/physical/index.d.ts +1 -0
  14. package/dist/src/layers/physical/serial-physical-layer.d.ts +2 -0
  15. package/dist/src/layers/physical/tcp-client-physical-layer.d.ts +3 -0
  16. package/dist/src/layers/physical/tcp-server-physical-layer.d.ts +3 -1
  17. package/dist/src/layers/physical/udp-physical-layer.d.ts +25 -10
  18. package/dist/src/master/index.d.ts +2 -0
  19. package/dist/src/master/master-session.d.ts +18 -0
  20. package/dist/src/master/master.d.ts +27 -5
  21. package/dist/src/slave/index.d.ts +1 -1
  22. package/dist/src/slave/slave.d.ts +22 -3
  23. package/dist/src/types.d.ts +33 -2
  24. package/dist/src/utils/bitsToMs.d.ts +13 -0
  25. package/dist/src/utils/crc.d.ts +1 -1
  26. package/dist/src/utils/genConnectionId.d.ts +2 -0
  27. package/dist/src/utils/index.d.ts +5 -1
  28. package/dist/src/utils/isUint8.d.ts +8 -0
  29. package/dist/src/utils/predictRtuFrameLength.d.ts +20 -0
  30. package/dist/src/vars.d.ts +47 -0
  31. package/dist/test/ascii-hex-validation.test.d.ts +1 -0
  32. package/dist/test/ascii-tcp-fragmentation.test.d.ts +1 -0
  33. package/dist/test/check-range.test.d.ts +1 -0
  34. package/dist/test/fallback-atomic.test.d.ts +1 -0
  35. package/dist/test/fallback-serial.test.d.ts +1 -0
  36. package/dist/test/fc17-serverid-validation.test.d.ts +1 -0
  37. package/dist/test/fc43-conformity.test.d.ts +1 -0
  38. package/dist/test/fc43-utf8-objects.test.d.ts +1 -0
  39. package/dist/test/gen-connection-id.test.d.ts +1 -0
  40. package/dist/test/helpers/raw-tcp.d.ts +38 -0
  41. package/dist/test/master-concurrent.test.d.ts +1 -0
  42. package/dist/test/modbus-error.test.d.ts +1 -0
  43. package/dist/test/physical-lifecycle.test.d.ts +1 -0
  44. package/dist/test/predict-rtu.test.d.ts +1 -0
  45. package/dist/test/rtu-custom-fc.test.d.ts +1 -0
  46. package/dist/test/rtu-pool-overflow.test.d.ts +1 -0
  47. package/dist/test/rtu-t15-timing.test.d.ts +1 -0
  48. package/dist/test/rtu-t35-default.test.d.ts +1 -0
  49. package/dist/test/rtu-t35-strict.test.d.ts +1 -0
  50. package/dist/test/rtu-tcp-fragmentation.test.d.ts +1 -0
  51. package/dist/test/serial-e2e.test.d.ts +1 -0
  52. package/dist/test/slave-multi-connection.test.d.ts +1 -0
  53. package/dist/test/slave.test.d.ts +1 -0
  54. package/dist/test/tcp-fragmentation.test.d.ts +1 -0
  55. package/dist/test/udp-multi-client.test.d.ts +1 -0
  56. package/package.json +4 -1
  57. package/dist/src/utils/getThreePointFiveT.d.ts +0 -7
  58. /package/dist/test/{master.d.ts → adu-buffer.test.d.ts} +0 -0
  59. /package/dist/test/{slave.d.ts → ascii-hex-sentry.test.d.ts} +0 -0
package/README.md CHANGED
@@ -66,7 +66,6 @@ npm install njs-modbus
66
66
  ### Modbus RTU Master
67
67
 
68
68
  ```typescript
69
- import type { ModbusSlaveModel } from 'njs-modbus';
70
69
  import { SerialPhysicalLayer, RtuApplicationLayer, ModbusMaster } from 'njs-modbus';
71
70
 
72
71
  const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
@@ -90,21 +89,22 @@ modbusMaster
90
89
  ### Modbus RTU Slave
91
90
 
92
91
  ```typescript
92
+ import type { ModbusSlaveModel } from 'njs-modbus';
93
93
  import { SerialPhysicalLayer, RtuApplicationLayer, ModbusSlave } from 'njs-modbus';
94
94
 
95
- const MB_SERVER = {
95
+ const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
96
+ const applicationLayer = new RtuApplicationLayer(physicalLayer);
97
+
98
+ const slave1Data = {
96
99
  discreteInputs: new Map<number, boolean>(),
97
100
  coils: new Map<number, boolean>(),
98
101
  inputRegisters: new Map<number, number>(),
99
102
  holdingRegisters: new Map<number, number>(),
100
103
  };
101
-
102
- const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
103
- const applicationLayer = new RtuApplicationLayer(physicalLayer);
104
104
  const slave1: ModbusSlaveModel = {
105
105
  readDiscreteInputs: (address, length) => {
106
106
  return Array.from({ length }).map((_, i) => {
107
- const discreteInput = MB_SERVER.discreteInputs.get(address + i);
107
+ const discreteInput = slave1Data.discreteInputs.get(address + i);
108
108
  if (typeof discreteInput === 'undefined') {
109
109
  return false;
110
110
  }
@@ -114,7 +114,7 @@ const slave1: ModbusSlaveModel = {
114
114
 
115
115
  readCoils: (address, length) => {
116
116
  return Array.from({ length }).map((_, i) => {
117
- const coil = MB_SERVER.coils.get(address + i);
117
+ const coil = slave1Data.coils.get(address + i);
118
118
  if (typeof coil === 'undefined') {
119
119
  return false;
120
120
  }
@@ -122,12 +122,12 @@ const slave1: ModbusSlaveModel = {
122
122
  });
123
123
  },
124
124
  writeSingleCoil: (address, value) => {
125
- MB_SERVER.coils.set(address, value);
125
+ slave1Data.coils.set(address, value);
126
126
  },
127
127
 
128
128
  readInputRegisters: (address, length) => {
129
129
  return Array.from({ length }).map((_, i) => {
130
- const inputRegister = MB_SERVER.inputRegisters.get(address + i);
130
+ const inputRegister = slave1Data.inputRegisters.get(address + i);
131
131
  if (typeof inputRegister === 'undefined') {
132
132
  return 0;
133
133
  }
@@ -137,7 +137,7 @@ const slave1: ModbusSlaveModel = {
137
137
 
138
138
  readHoldingRegisters: (address, length) => {
139
139
  return Array.from({ length }).map((_, i) => {
140
- const holdingRegister = MB_SERVER.holdingRegisters.get(address + i);
140
+ const holdingRegister = slave1Data.holdingRegisters.get(address + i);
141
141
  if (typeof holdingRegister === 'undefined') {
142
142
  return 0;
143
143
  }
@@ -145,7 +145,7 @@ const slave1: ModbusSlaveModel = {
145
145
  });
146
146
  },
147
147
  writeSingleRegister: (address, value) => {
148
- MB_SERVER.holdingRegisters.set(address, value);
148
+ slave1Data.holdingRegisters.set(address, value);
149
149
  },
150
150
 
151
151
  reportServerId: () => ({ additionalData: [1, 2, 3] }),
@@ -178,6 +178,22 @@ modbusSlave
178
178
 
179
179
  For more advanced examples, check out [examples](/examples) included in the repository. If you have created any utilities that meet a specific need, feel free to submit them so others can benefit.
180
180
 
181
+ ## Broadcasts (unit = 0)
182
+
183
+ Slaves never respond to broadcast requests, so the master's `write*(0, ...)` Promise resolves as soon as the bytes are flushed to the wire.
184
+
185
+ If you broadcast over serial (RTU or ASCII), per Modbus over Serial Line V1.02 §2.4.1 you must wait a **turnaround delay** before sending the next request — slow slaves need time to apply the broadcast write that produced no response. The library does not insert this delay automatically because the right value is workload-specific (fast sensors vs. PLCs writing to flash differ by orders of magnitude). Insert it yourself in your call site:
186
+
187
+ ```typescript
188
+ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
189
+
190
+ await master.writeSingleRegister(0, 0x0000, 0x1234); // broadcast
191
+ await sleep(100); // turnaround — tune per devices
192
+ await master.writeSingleRegister(1, 0x0000, 0x5678); // unicast to next slave
193
+ ```
194
+
195
+ A safe lower bound is the RTU t3.5 inter-frame silence (e.g. ~4 ms at 9600 baud, ~1.75 ms above 19200 baud). Many real-world PLCs need 50–100 ms after a broadcast write. Modbus TCP/UDP do not require this delay (TCP gives synchronous acks; broadcasting on TCP is uncommon anyway).
196
+
181
197
  ## Contributing
182
198
 
183
199
  Please read our [contributing guide](/CODE_OF_CONDUCT.md) first.