modbus-rs-wasm 0.14.1 → 0.15.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/README.md CHANGED
@@ -12,13 +12,13 @@ npm install modbus-rs-wasm
12
12
 
13
13
  ## Integration & Frameworks (Vite, Svelte, React, etc.)
14
14
 
15
- No custom resolver aliases or configuration workarounds are required starting in `v0.14.0`. Standard package entry points are resolved automatically based on your builder/bundler targets.
15
+ No custom resolver aliases are required. Standard package entry points are resolved automatically based on your builder/bundler targets.
16
16
 
17
17
  ### Web (Direct / HTML / Vanilla JS)
18
- When loading the package in browser environments without a bundler, import the web entry point and await the initialization promise:
18
+ When loading the package in browser environments without a bundler (e.g. from CDNs like unpkg or jsDelivr), import the web entry point and await the initialization promise:
19
19
 
20
20
  ```javascript
21
- import init, { WasmTcpTransport } from 'modbus-rs-wasm/dist/web/modbus-rs.js';
21
+ import init, { WasmTcpTransport } from 'modbus-rs-wasm/web';
22
22
 
23
23
  await init();
24
24
  const transport = new WasmTcpTransport('ws://localhost:8502', {
@@ -29,27 +29,87 @@ const transport = new WasmTcpTransport('ws://localhost:8502', {
29
29
  const client = transport.create_client({ unitId: 1 });
30
30
  ```
31
31
 
32
- ### Bundlers & Frameworks (Vite, SvelteKit, Next.js, etc.)
33
- When using modern bundlers, the root import automatically maps to the bundler target:
32
+ ### Bundlers & Modern Frameworks
33
+
34
+ When using modern bundlers (Vite, Webpack, Next.js, etc.), the root import maps to the bundler target where WebAssembly is loaded automatically:
34
35
 
35
36
  ```javascript
36
37
  import { WasmTcpTransport } from 'modbus-rs-wasm';
37
38
  ```
38
- *(Make sure your bundler is configured to load WebAssembly, e.g., using `vite-plugin-wasm` and `vite-plugin-top-level-await` in Vite).*
39
+
40
+ Because WASM is an asynchronous module dependency, you must configure your bundler to support WASM loader options:
41
+
42
+ #### 1. Vite (React, Svelte, Vue, SolidJS, etc. via Vite)
43
+ Vite requires helper plugins to support WebAssembly. Install `vite-plugin-wasm` and `vite-plugin-top-level-await`:
44
+
45
+ ```bash
46
+ npm install -D vite-plugin-wasm vite-plugin-top-level-await
47
+ ```
48
+
49
+ In your `vite.config.ts`, register the plugins and **exclude** `modbus-rs-wasm` from dependency pre-bundling (to prevent Esbuild from trying to optimize the WASM module):
50
+
51
+ ```typescript
52
+ import { defineConfig } from 'vite';
53
+ import wasm from 'vite-plugin-wasm';
54
+ import topLevelAwait from 'vite-plugin-top-level-await';
55
+
56
+ export default defineConfig({
57
+ plugins: [wasm(), topLevelAwait()],
58
+ optimizeDeps: {
59
+ exclude: ['modbus-rs-wasm']
60
+ }
61
+ });
62
+ ```
63
+
64
+ #### 2. Webpack 5 (React, Angular, or custom Webpack setups)
65
+ Webpack 5 supports WebAssembly natively but it is disabled by default. You need to enable the `asyncWebAssembly` experiment in your `webpack.config.js`:
66
+
67
+ ```javascript
68
+ module.exports = {
69
+ // ...
70
+ experiments: {
71
+ asyncWebAssembly: true,
72
+ },
73
+ };
74
+ ```
75
+
76
+ #### 3. Next.js (Webpack mode)
77
+ Configure `next.config.js` to enable WebAssembly support inside Next.js's internal Webpack runner:
78
+
79
+ ```javascript
80
+ /** @type {import('next').NextConfig} */
81
+ const nextConfig = {
82
+ webpack(config) {
83
+ config.experiments = {
84
+ ...config.experiments,
85
+ asyncWebAssembly: true,
86
+ };
87
+ return config;
88
+ },
89
+ };
90
+
91
+ module.exports = nextConfig;
92
+ ```
39
93
 
40
94
  ## Quick Start
41
95
 
42
96
  ### Examples
43
97
  Ready-to-run HTML examples demonstrating both Modbus client and server functionality in the browser:
44
98
 
45
- - **[wasm_client/network_smoke.html](./examples/wasm_client/network_smoke.html)**: WebSocket Modbus TCP client example.
46
- - **[wasm_client/serial_smoke.html](./examples/wasm_client/serial_smoke.html)**: Web Serial Modbus RTU client example.
47
- - **[wasm_server/network_smoke.html](./examples/wasm_server/network_smoke.html)**: WebSocket Modbus TCP server example.
48
- - **[wasm_server/serial_smoke.html](./examples/wasm_server/serial_smoke.html)**: Web Serial Modbus RTU server example.
99
+ - **[wasm_client/network_smoke.html](https://github.com/Raghava-Ch/modbus-rs/blob/main/mbus-ffi/wasm/examples/wasm_client/network_smoke.html)**: WebSocket Modbus TCP client example.
100
+ - **[wasm_client/serial_smoke.html](https://github.com/Raghava-Ch/modbus-rs/blob/main/mbus-ffi/wasm/examples/wasm_client/serial_smoke.html)**: Web Serial Modbus RTU client example.
101
+ - **[wasm_server/network_smoke.html](https://github.com/Raghava-Ch/modbus-rs/blob/main/mbus-ffi/wasm/examples/wasm_server/network_smoke.html)**: WebSocket Modbus TCP server example.
102
+ - **[wasm_server/serial_smoke.html](https://github.com/Raghava-Ch/modbus-rs/blob/main/mbus-ffi/wasm/examples/wasm_server/serial_smoke.html)**: Web Serial Modbus RTU server example.
103
+ - **[Demo Application](https://modbus-lab.vercel.app)**: Live web application demonstrating modbus-rs-wasm in action. [modbus-lab.vercel.app](https://modbus-lab.vercel.app)
104
+ - **[Real-World Example Source Code](https://github.com/Raghava-Ch/modbus-lab)**: Repository containing the source code for the demo web client and Tauri-based desktop client/server simulators.
49
105
 
50
106
  To run the examples locally:
51
107
  ```bash
52
- npx serve examples/
108
+ # clone the repo
109
+ cd modbus-rs/mbus-ffi/wasm
110
+ npx serve ./
111
+ # Navigate to example folder with chromium based web browser run the examples.
112
+ # you can also use the tauri desktop client and server simulator.
53
113
  ```
54
114
 
55
115
  ### Modbus RTU via Web Serial
@@ -76,16 +136,15 @@ document.getElementById('connect-btn').addEventListener('click', async () => {
76
136
  stopBits: 1,
77
137
  parity: 'even',
78
138
  responseTimeoutMs: 1000,
79
- retryAttempts: 3,
80
- tickIntervalMs: 20
139
+ retryAttempts: 3
81
140
  });
82
141
 
83
142
  // 3. Spawn a client for a specific slave (Unit ID)
84
- const client = transport.create_client({ unitId: 10 });
143
+ const client = transport.createClient({ unitId: 10 });
85
144
 
86
145
  // 4. Read coils
87
- const coils = await client.read_coils(0, 8);
88
- console.log('Coils:', coils); // Uint8Array
146
+ const coils = await client.readCoils({ address: 0, quantity: 8 });
147
+ console.log('Coils:', coils); // boolean[]
89
148
 
90
149
  } catch (err) {
91
150
  console.error('Serial error:', err);
@@ -101,18 +160,17 @@ import { WasmTcpTransport } from 'modbus-rs-wasm';
101
160
 
102
161
  async function readRegisters() {
103
162
  // 1. Connect to a WebSocket proxy that forwards to a Modbus TCP device
104
- const transport = new WasmTcpTransport('ws://localhost:8502', {
163
+ const transport = await WasmTcpTransport.connect('ws://localhost:8502', {
105
164
  responseTimeoutMs: 5000,
106
- retryAttempts: 3,
107
- tickIntervalMs: 20
165
+ retryAttempts: 3
108
166
  });
109
167
 
110
168
  // 2. Spawn a client attached to Unit ID 1
111
- const client = transport.create_client({ unitId: 1 });
169
+ const client = transport.createClient({ unitId: 1 });
112
170
 
113
171
  try {
114
172
  // 3. Read 10 holding registers starting at address 0
115
- const registers = await client.read_holding_registers(0, 10);
173
+ const registers = await client.readHoldingRegisters({ address: 0, quantity: 10 });
116
174
  console.log('Holding registers:', registers); // Uint16Array
117
175
  } catch (error) {
118
176
  console.error('Failed to read registers:', error);
@@ -122,36 +180,40 @@ async function readRegisters() {
122
180
 
123
181
  ### Modbus server demo with modbus-rs-wasm
124
182
 
125
- The `modbus-rs-wasm` package also provides building blocks for server simulation inside the browser. You can instantiate a `WasmTcpServer` or `WasmSerialServer` by providing a configuration and a JavaScript callback to process incoming requests.
183
+ The `modbus-rs-wasm` package also provides building blocks for server simulation inside the browser. You can bind a `WasmTcpServer` or `WasmSerialServer` by providing configurations and an object implementing `ServerHandlers` callback methods.
126
184
 
127
185
  Here is a quick example of setting up a simulated server via a WebSocket TCP gateway:
128
186
 
129
187
  ```javascript
130
- import { WasmTcpGatewayConfig, WasmTcpServer } from 'modbus-rs-wasm';
188
+ import { WasmTcpServer } from 'modbus-rs-wasm';
131
189
 
132
190
  async function simulateServer() {
133
- // 1. Configure the server (e.g., pointing to a WebSocket gateway)
134
- const config = new WasmTcpGatewayConfig("ws://localhost:8080");
135
-
136
- // 2. Create the server and define the request handler
137
- const server = new WasmTcpServer(config, async (request) => {
138
- console.log("Received Modbus request:", request);
139
-
140
- // Simulate processing the request
141
- // The handler can be fully asynchronous and return a Promise
142
- return {
143
- // Return appropriate response fields based on the request
144
- success: true,
145
- data: [100, 200, 300]
146
- };
191
+ // 1. Define the request handlers
192
+ const handlers = {
193
+ onReadHoldingRegisters: async (request) => {
194
+ console.log("Received Modbus request:", request);
195
+
196
+ // Callbacks can return values synchronously or as Promises
197
+ return [100, 200, 300];
198
+ }
199
+ };
200
+
201
+ // 2. Bind the server
202
+ const server = await WasmTcpServer.bind(
203
+ {
204
+ wsUrl: "ws://localhost:8080",
205
+ unitId: 1
206
+ },
207
+ handlers
208
+ );
209
+
210
+ // 3. Start the event loop (runs asynchronously in background)
211
+ server.serve().catch(err => {
212
+ console.error("Server crashed:", err);
147
213
  });
148
-
149
- // 3. Start the server
150
- server.start();
151
214
 
152
- // Observe the server status
153
- console.log("Server running:", server.is_running());
154
- console.log("Server status:", server.status_snapshot());
215
+ // To stop the server later:
216
+ // await server.shutdown();
155
217
  }
156
218
  ```
157
219
 
@@ -160,34 +222,41 @@ async function simulateServer() {
160
222
  You can also create a simulated serial server (RTU or ASCII) and attach a browser `SerialPort` to it using the Web Serial API:
161
223
 
162
224
  ```javascript
163
- import { WasmSerialServerConfig, WasmSerialServer } from 'modbus-rs-wasm';
225
+ import { WasmSerialServer } from 'modbus-rs-wasm';
164
226
 
165
227
  async function simulateSerialServer() {
166
228
  // 1. Request a serial port from the user (requires user gesture)
167
229
  const port = await navigator.serial.requestPort();
168
230
 
169
- // 2. Configure the server for RTU or ASCII mode
170
- const config = WasmSerialServerConfig.rtu(); // or .ascii()
171
-
172
- // 3. Create the server with a request handler callback
173
- const server = new WasmSerialServer(config, async (request) => {
174
- console.log("Received Modbus request via Serial:", request);
175
- return {
176
- success: true,
177
- data: [100, 200, 300]
178
- };
231
+ // 2. Define the request handlers
232
+ const handlers = {
233
+ onReadHoldingRegisters: (request) => {
234
+ console.log("Received Modbus request via Serial:", request);
235
+ return [100, 200, 300];
236
+ }
237
+ };
238
+
239
+ // 3. Bind the server for RTU mode
240
+ const server = await WasmSerialServer.bindRtu(
241
+ {
242
+ serialPort: port,
243
+ unitId: 1,
244
+ baudRate: 19200
245
+ },
246
+ handlers
247
+ );
248
+
249
+ // 4. Start the event loop
250
+ server.serve().catch(err => {
251
+ console.error("Serial Server crashed:", err);
179
252
  });
180
-
181
- // 4. Attach the browser serial port
182
- server.attach_serial_port(port);
183
-
184
- // 5. Start the server
185
- server.start();
186
-
187
- console.log("Serial Server running:", server.is_running());
188
253
  }
189
254
  ```
190
255
 
256
+ ## Migration Guide
257
+
258
+ Detailed step-by-step migration guides are available in the [Migration Guides](https://github.com/Raghava-Ch/modbus-rs/tree/main/documentation/migrations) directory.
259
+
191
260
  ## License
192
261
 
193
262
  GPL-3.0-only — see [LICENSE](./LICENSE). A commercial license is available for proprietary use.