@rhinosw/react-native-usb-serial 0.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.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rezaul Karim
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,477 @@
1
+ # React-native-usb-serial
2
+
3
+ A professional-grade React Native module providing seamless USB serial communication for **Android devices only**. Built with Kotlin and supporting USB CDC devices, modbus sensors, and high-performance serial data streaming.
4
+
5
+ > **Important:** This library is **exclusively for Android**. iOS is not supported due to platform limitations. For iOS projects, consider alternative solutions.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/react-native-usb-serial.svg)](https://www.npmjs.com/package/react-native-usb-serial)
8
+ [![license](https://img.shields.io/npm/l/react-native-usb-serial.svg)](LICENSE)
9
+ [![Platform - Android Only](https://img.shields.io/badge/Platform-Android%20Only-green)]()
10
+ [![Kotlin](https://img.shields.io/badge/Language-Kotlin-purple)]()
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Supported-blue)]()
12
+
13
+ ## Features
14
+
15
+ - **Full USB Device Control** - Enumerate, connect, and manage USB devices
16
+ - **Real-time Data Streaming** - Configurable interval-based serial data reading
17
+ - **Modbus Soil Sensors** - Native support for 8-in-1 modbus soil sensors
18
+ - **Configurable Parameters** - Custom baud rates, buffer sizes, and timeouts
19
+ - **Permission Handling** - Integrated USB permission request management
20
+ - **Type-Safe** - Full TypeScript support with comprehensive type definitions
21
+ - **High Performance** - Native Android implementation for optimal throughput
22
+
23
+ ## Platform Support
24
+
25
+ | Platform | Status | Details |
26
+ |----------|--------|---------|
27
+ | **Android** | **Fully Supported** | API Level 24+ required |
28
+ | **iOS** | **Not Supported** | iOS does not allow direct USB serial access |
29
+ | **Web** | **Not Supported** | Web platform not compatible |
30
+
31
+ ### Why Android Only?
32
+
33
+ - **iOS Limitation:** Apple's iOS sandboxing prevents direct USB serial device access without specific MFi (Made for iPhone) certification
34
+ - **Platform Design:** This library uses Android's native USB Host API which is Android-specific
35
+ - **Alternative for iOS:** Consider using Bluetooth/BLE modules instead
36
+
37
+ > **Important:** If you have an iOS requirement, you must use a different architecture (e.g., Bluetooth serial modules with a compatible React Native Bluetooth library).
38
+
39
+ ## Minimum Requirements
40
+
41
+ - **React Native** >= 0.71.0
42
+ - **Android API Level** >= 24 (Android 7.0+)
43
+ - **Java** 8+ (OpenJDK or Oracle JDK)
44
+ - **Kotlin** 2.0.21+ (included in build system)
45
+
46
+ ## Installation
47
+
48
+ > **Android Only:** This package only works on Android devices. It will not function on iOS.
49
+
50
+ ```bash
51
+ npm install @rhinosw/react-native-usb-serial
52
+ # or
53
+ yarn add @rhinosw/react-native-usb-serial
54
+ ```
55
+
56
+ ### Android Configuration
57
+
58
+ Add USB permissions to your `AndroidManifest.xml`:
59
+
60
+ ```xml
61
+ <uses-permission android:name="android.permission.USB_PERMISSION" />
62
+ <uses-feature android:name="android.hardware.usb.host" />
63
+ ```
64
+
65
+ ## Quick Start
66
+
67
+ ### Basic Device Enumeration
68
+
69
+ ```typescript
70
+ import {
71
+ getDeviceList,
72
+ type UsbDevice,
73
+ } from '@rhinosw/react-native-usb-serial';
74
+
75
+ // Get all connected USB devices
76
+ const devices: UsbDevice[] = getDeviceList();
77
+
78
+ devices.forEach(device => {
79
+ console.log(`Device: ${device.productName}`);
80
+ console.log(`Vendor ID: ${device.vendorId}`);
81
+ console.log(`Product ID: ${device.productId}`);
82
+ });
83
+ ```
84
+
85
+ ### Device Connection with Permission Handling
86
+
87
+ ```typescript
88
+ import {
89
+ hasPermission,
90
+ requestUsbPermission,
91
+ connect,
92
+ disconnect,
93
+ } from '@rhinosw/react-native-usb-serial';
94
+
95
+ async function connectToDevice(device: UsbDevice): Promise<void> {
96
+ try {
97
+ // Check existing permission
98
+ let hasAccess = await hasPermission(device);
99
+
100
+ // Request permission if needed
101
+ if (!hasAccess) {
102
+ hasAccess = await requestUsbPermission(device);
103
+ if (!hasAccess) {
104
+ throw new Error('USB permission denied');
105
+ }
106
+ }
107
+
108
+ // Connect with custom baud rate (9600 is default)
109
+ const connected = await connect(device, 115200);
110
+
111
+ if (connected) {
112
+ console.log('Connected successfully');
113
+ }
114
+ } catch (error) {
115
+ console.error('Connection failed:', error);
116
+ }
117
+ }
118
+
119
+ // Disconnect when done
120
+ await disconnect();
121
+ ```
122
+
123
+ ### Real-time Serial Data Streaming
124
+
125
+ ```typescript
126
+ import {
127
+ onReadInterval,
128
+ offReadInterval,
129
+ type RawReadConfig,
130
+ NativeEventEmitter,
131
+ } from '@rhinosw/react-native-usb-serial';
132
+
133
+ // Configure reading parameters
134
+ const readConfig: RawReadConfig = {
135
+ bufferSize: 2048, // Buffer size in bytes
136
+ timeout: 1000, // Read timeout in milliseconds
137
+ };
138
+
139
+ // Start listening for data every 100ms
140
+ await onReadInterval(100, readConfig);
141
+
142
+ // Listen to serial data events
143
+ const eventEmitter = new NativeEventEmitter();
144
+ const subscription = eventEmitter.addListener(
145
+ 'USB_SERIAL_DATA',
146
+ (event: { data: string }) => {
147
+ console.log('Received:', event.data);
148
+ }
149
+ );
150
+
151
+ // Stop listening when done
152
+ await offReadInterval();
153
+
154
+ // Clean up
155
+ subscription.remove();
156
+ ```
157
+
158
+ ### Writing Data to Serial Port
159
+
160
+ ```typescript
161
+ import { write, isConnected } from '@rhinosw/react-native-usb-serial';
162
+
163
+ async function sendCommand(command: string): Promise<void> {
164
+ try {
165
+ const connected = await isConnected();
166
+ if (!connected) {
167
+ throw new Error('Device not connected');
168
+ }
169
+
170
+ await write(command);
171
+ console.log('Data sent:', command);
172
+ } catch (error) {
173
+ console.error('Write failed:', error);
174
+ }
175
+ }
176
+
177
+ // Send AT commands
178
+ await sendCommand('AT+RST\r\n');
179
+ ```
180
+
181
+ ### Manual Serial Reading
182
+
183
+ ```typescript
184
+ import { read } from '@rhinosw/react-native-usb-serial';
185
+
186
+ async function readSerialData(): Promise<void> {
187
+ try {
188
+ // Read with default buffer (1024 bytes) and timeout (1000ms)
189
+ let data = await read();
190
+
191
+ // Or with custom parameters
192
+ data = await read(4096, 2000);
193
+
194
+ console.log('Received:', data);
195
+ } catch (error) {
196
+ console.error('Read failed:', error);
197
+ }
198
+ }
199
+ ```
200
+
201
+ ## Advanced Usage
202
+
203
+ ### Soil Sensor Integration
204
+
205
+ ```typescript
206
+ import {
207
+ readSoilData,
208
+ onReadSoilDataInterval,
209
+ offReadSoilDataInterval,
210
+ type SoilSensorConfig,
211
+ type SoilData,
212
+ NativeEventEmitter,
213
+ } from '@rhinosw/react-native-usb-serial';
214
+
215
+ // Configure modbus soil sensor
216
+ const soilConfig: SoilSensorConfig = {
217
+ slaveId: 1, // Modbus slave ID
218
+ startAddress: 0x0000, // Register start address
219
+ registerCount: 8, // Number of registers to read
220
+ responseDelayMs: 300, // Response wait time
221
+ };
222
+
223
+ // Read once
224
+ const soilData: SoilData | null = await readSoilData(soilConfig);
225
+ if (soilData) {
226
+ console.log('Soil Moisture:', soilData.moisture);
227
+ console.log('Soil Temperature:', soilData.temperature);
228
+ }
229
+
230
+ // Start continuous monitoring (every 500ms)
231
+ await onReadSoilDataInterval(500, soilConfig);
232
+
233
+ // Listen to soil sensor events
234
+ const eventEmitter = new NativeEventEmitter();
235
+ const subscription = eventEmitter.addListener(
236
+ 'USB_SOIL_DATA',
237
+ (event: SoilData) => {
238
+ console.log('Soil Data:', {
239
+ moisture: event.moisture,
240
+ temperature: event.temperature,
241
+ ec: event.ec,
242
+ });
243
+ }
244
+ );
245
+
246
+ // Stop monitoring
247
+ await offReadSoilDataInterval();
248
+ subscription.remove();
249
+ ```
250
+
251
+ ### Get Currently Connected Device
252
+
253
+ ```typescript
254
+ import { getConnectedDevice } from '@rhinosw/react-native-usb-serial';
255
+
256
+ const device = await getConnectedDevice();
257
+ if (device) {
258
+ console.log('Connected to:', device.productName);
259
+ console.log('Serial Number:', device.serialNumber);
260
+ } else {
261
+ console.log('No device connected');
262
+ }
263
+ ```
264
+
265
+ ## Event Listening
266
+
267
+ Use `NativeEventEmitter` to listen to real-time data:
268
+
269
+ ```typescript
270
+ import { NativeEventEmitter } from 'react-native';
271
+
272
+ const eventEmitter = new NativeEventEmitter();
273
+
274
+ // Serial data events
275
+ const serialSub = eventEmitter.addListener('USB_SERIAL_DATA', (event) => {
276
+ console.log('Serial:', event.data);
277
+ });
278
+
279
+ // Soil sensor events
280
+ const soilSub = eventEmitter.addListener('USB_SOIL_DATA', (event) => {
281
+ console.log('Soil:', event);
282
+ });
283
+
284
+ // Clean up
285
+ serialSub.remove();
286
+ soilSub.remove();
287
+ ```
288
+
289
+ ## Error Handling
290
+
291
+ ```typescript
292
+ import { connect, type UsbDevice } from '@rhinosw/react-native-usb-serial';
293
+
294
+ async function safeConnect(device: UsbDevice): Promise<void> {
295
+ try {
296
+ const success = await connect(device);
297
+ if (!success) {
298
+ console.error('Connection failed');
299
+ }
300
+ } catch (error) {
301
+ if (error instanceof Error) {
302
+ console.error('Error:', error.message);
303
+ }
304
+ }
305
+ }
306
+ ```
307
+
308
+ ## Type Definitions
309
+
310
+ ### UsbDevice
311
+
312
+ ```typescript
313
+ type UsbDevice = {
314
+ deviceName: string;
315
+ vendorId: number;
316
+ productId: number;
317
+ manufacturer?: string | null;
318
+ productName?: string | null;
319
+ serialNumber?: string | null;
320
+ };
321
+ ```
322
+
323
+ ### RawReadConfig
324
+
325
+ ```typescript
326
+ type RawReadConfig = {
327
+ bufferSize?: number; // Default: 1024 bytes
328
+ timeout?: number; // Default: 1000 ms
329
+ };
330
+ ```
331
+
332
+ ### SoilSensorConfig
333
+
334
+ ```typescript
335
+ type SoilSensorConfig = {
336
+ slaveId?: number; // Default: 1
337
+ startAddress?: number; // Default: 0x0000
338
+ registerCount?: number; // Default: 8
339
+ responseDelayMs?: number; // Default: 300 ms
340
+ };
341
+ ```
342
+
343
+ ### SoilData
344
+
345
+ ```typescript
346
+ type SoilData = {
347
+ [key: string]: number;
348
+ // Typical keys: moisture, temperature, ec, ph, etc.
349
+ };
350
+ ```
351
+
352
+ ## API Reference
353
+
354
+ ### Device Management
355
+
356
+ #### `getDeviceList(): UsbDevice[]`
357
+ Get all connected USB devices synchronously.
358
+
359
+ #### `hasPermission(device: UsbDevice): Promise<boolean>`
360
+ Check if app has USB permission for a device.
361
+
362
+ #### `requestUsbPermission(device: UsbDevice): Promise<boolean>`
363
+ Request USB permission from user. Returns true if granted.
364
+
365
+ #### `connect(device: UsbDevice, baudRate?: number): Promise<boolean>`
366
+ Connect to a USB device. Default baud rate: 9600.
367
+
368
+ #### `disconnect(): Promise<void>`
369
+ Disconnect from current device.
370
+
371
+ #### `isConnected(): Promise<boolean>`
372
+ Check if currently connected to a device.
373
+
374
+ #### `getConnectedDevice(): Promise<UsbDevice | null>`
375
+ Get the currently connected device information.
376
+
377
+ ### Serial Communication
378
+
379
+ #### `write(data: string): Promise<void>`
380
+ Write data to the serial port.
381
+
382
+ #### `read(bufferSize?: number, timeout?: number): Promise<string>`
383
+ Read data from serial port. Useful for one-off reads.
384
+
385
+ #### `onReadInterval(intervalMs: number, config?: RawReadConfig): Promise<void>`
386
+ Start streaming serial data at specified interval. Emits `USB_SERIAL_DATA` events.
387
+
388
+ #### `offReadInterval(): Promise<void>`
389
+ Stop streaming serial data.
390
+
391
+ ### Soil Sensor
392
+
393
+ #### `readSoilData(config?: SoilSensorConfig): Promise<SoilData | null>`
394
+ Read modbus soil sensor data once.
395
+
396
+ #### `onReadSoilDataInterval(intervalMs: number, config?: SoilSensorConfig): Promise<void>`
397
+ Start reading soil sensor data periodically. Emits `USB_SOIL_DATA` events.
398
+
399
+ #### `offReadSoilDataInterval(): Promise<void>`
400
+ Stop reading soil sensor data.
401
+
402
+ ## Best Practices
403
+
404
+ 1. **Always check connection status** before writing/reading
405
+ 2. **Handle permissions gracefully** - Some devices may refuse access
406
+ 3. **Use appropriate timeouts** for different devices
407
+ 4. **Clean up listeners** to prevent memory leaks
408
+ 5. **Validate device IDs** before connecting
409
+ 6. **Buffer large data** properly with adequate buffer sizes
410
+ 7. **Test with real devices** - Emulator USB support is limited
411
+
412
+ ## Example Application
413
+
414
+ See the [`example`](./example) directory for a complete React Native application demonstrating:
415
+ - Device enumeration and listing
416
+ - Permission management
417
+ - Connection lifecycle
418
+ - Real-time data streaming
419
+ - Error handling
420
+
421
+ ```bash
422
+ cd example
423
+ yarn install
424
+ yarn android
425
+ ```
426
+
427
+ ## Troubleshooting
428
+
429
+ ### Device Not Detected
430
+ - Ensure USB debugging is enabled
431
+ - Check USB cable connection
432
+ - Verify device is recognized by `adb devices`
433
+
434
+ ### Permission Denied
435
+ - Grant USB permission when prompted
436
+ - Check `AndroidManifest.xml` permissions
437
+ - Restart app if permission prompt was dismissed
438
+
439
+ ### No Data Received
440
+ - Verify baud rate matches device
441
+ - Check serial cable quality
442
+ - Increase read timeout value
443
+ - Ensure device is sending data
444
+
445
+ ### Connection Drops
446
+ - Check USB cable stability
447
+ - Reduce read interval if too frequent
448
+ - Monitor system resources
449
+ - Check device firmware
450
+
451
+ ## Performance Tips
452
+
453
+ - Use appropriate buffer sizes (1024-4096 for most cases)
454
+ - Adjust read intervals based on data volume
455
+ - Unsubscribe from events when not needed
456
+ - Handle large data streams with chunking
457
+ - Monitor memory usage with large buffers
458
+
459
+ ## Contributing
460
+
461
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
462
+
463
+ ## Code of Conduct
464
+
465
+ This project adheres to the [Code of Conduct](CODE_OF_CONDUCT.md).
466
+
467
+ ## License
468
+
469
+ MIT - See [LICENSE](LICENSE) file for details.
470
+
471
+ ## Support
472
+
473
+ For issues, questions, or suggestions, please open an [issue on GitHub](https://github.com/yourusername/react-native-usb-serial/issues).
474
+
475
+ ---
476
+
477
+ **Made with ❤️ for the React Native community**
@@ -0,0 +1,69 @@
1
+ buildscript {
2
+ ext.UsbSerial = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36
7
+ ]
8
+
9
+ ext.getExtOrDefault = { prop ->
10
+ if (rootProject.ext.has(prop)) {
11
+ return rootProject.ext.get(prop)
12
+ }
13
+
14
+ return UsbSerial[prop]
15
+ }
16
+
17
+ repositories {
18
+ google()
19
+ mavenCentral()
20
+ maven { url = uri("https://jitpack.io") }
21
+ }
22
+
23
+ dependencies {
24
+ classpath "com.android.tools.build:gradle:8.7.2"
25
+ // noinspection DifferentKotlinGradleVersion
26
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
27
+ }
28
+ }
29
+
30
+
31
+ apply plugin: "com.android.library"
32
+ apply plugin: "kotlin-android"
33
+
34
+ apply plugin: "com.facebook.react"
35
+
36
+ android {
37
+ namespace "com.usbserial"
38
+
39
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
40
+
41
+ defaultConfig {
42
+ minSdkVersion getExtOrDefault("minSdkVersion")
43
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
44
+ }
45
+
46
+ buildFeatures {
47
+ buildConfig true
48
+ }
49
+
50
+ buildTypes {
51
+ release {
52
+ minifyEnabled false
53
+ }
54
+ }
55
+
56
+ lint {
57
+ disable "GradleCompatible"
58
+ }
59
+
60
+ compileOptions {
61
+ sourceCompatibility JavaVersion.VERSION_1_8
62
+ targetCompatibility JavaVersion.VERSION_1_8
63
+ }
64
+ }
65
+
66
+ dependencies {
67
+ implementation "com.facebook.react:react-android"
68
+ implementation("com.github.DeveloperRejaul:usb-serial:v0.0.3")
69
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>