forked from DeveloperRejaul/react-native-usb-serial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUsbSerialModule.kt
More file actions
301 lines (266 loc) · 9.37 KB
/
Copy pathUsbSerialModule.kt
File metadata and controls
301 lines (266 loc) · 9.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
package com.usbserial
import android.hardware.usb.UsbDevice
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.ReadableMap
import com.rezaul.usbserial.UsbManager
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.rezaul.usbserial.RawReadConfig
import com.rezaul.usbserial.SoilSensorConfig
import com.facebook.react.bridge.Promise
@ReactModule(name = UsbSerialModule.NAME)
class UsbSerialModule(reactContext: ReactApplicationContext) :
NativeUsbSerialSpec(reactContext) {
private val usbManager = UsbManager(reactContext)
override fun multiply(a: Double, b: Double): Double {
return a * b
}
private fun sendEvent(eventName: String, data: Any?) {
reactApplicationContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit(eventName, data)
}
private fun readableMapToUsbDevice(map: ReadableMap): UsbDevice? {
val devices = usbManager.getDeviceList()
val vendorId = map.getInt("vendorId")
val productId = map.getInt("productId")
for (device in devices) {
if (device.vendorId == vendorId && device.productId == productId) {
return device
}
}
return null
}
private fun usbDeviceToMap(device: UsbDevice): WritableMap {
val map = Arguments.createMap()
map.putInt("vendorId", device.vendorId)
map.putInt("productId", device.productId)
map.putString("manufacturer", device.manufacturerName)
return map
}
/**
* Returns all connected USB devices
*/
override fun getDeviceList(): WritableArray {
val result: WritableArray = Arguments.createArray()
val devices: List<UsbDevice> = usbManager.getDeviceList()
for (device in devices) {
result.pushMap(usbDeviceToMap(device))
}
return result
}
/**
* Check if app has permission for a specific device
*/
override fun hasPermission(device: ReadableMap, promise: Promise) {
try {
val usbDevice = readableMapToUsbDevice(device)
if (usbDevice == null) {
promise.reject("DEVICE_NOT_FOUND", "USB device not found")
return
}
val hasPermission = usbManager.hasPermission(usbDevice)
promise.resolve(hasPermission)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Request USB permission for a specific device
*/
override fun requestUsbPermission(device: ReadableMap, promise: Promise) {
try {
val usbDevice = readableMapToUsbDevice(device)
if (usbDevice == null) {
promise.reject("DEVICE_NOT_FOUND", "USB device not found")
return
}
usbManager.requestUsbPermission(usbDevice) { granted ->
promise.resolve(granted)
}
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Connect to a specific USB device with optional baud rate
*/
override fun connect(device: ReadableMap, baudRate: Double?, promise: Promise) {
try {
val usbDevice = readableMapToUsbDevice(device)
if (usbDevice == null) {
promise.reject("DEVICE_NOT_FOUND", "USB device not found")
return
}
val baud = baudRate?.toInt() ?: 9600
val connected = usbManager.connect(usbDevice, baud)
promise.resolve(connected)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Check if serial connection is active
*/
override fun isConnected(promise: Promise) {
try {
val connected = usbManager.isConnected()
promise.resolve(connected)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Disconnect the current serial device
*/
override fun disconnect(promise: Promise) {
try {
usbManager.disconnect()
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Write data to the serial port
*/
override fun write(data: String, promise: Promise) {
try {
usbManager.write(data.toByteArray())
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Read data from the serial port
*/
override fun read(bufferSize: Double?, timeout: Double?, promise: Promise) {
try {
val buffer = bufferSize?.toInt() ?: 1024
val timeoutVal = timeout?.toInt() ?: 1000
val data = usbManager.read(buffer, timeoutVal)
promise.resolve(String(data))
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Start listening for raw serial data at specified interval
*/
override fun onReadInterval(intervalMs: Double, config: ReadableMap?, promise: Promise) {
try {
val bufferSize = config?.getInt("bufferSize") ?: 1024
val timeout = config?.getInt("timeout") ?: 1000
val readConfig = RawReadConfig(bufferSize, timeout)
usbManager.onReadInterval(
intervalMs = intervalMs.toLong(),
onDataReceived = { bytes: ByteArray ->
val map = Arguments.createMap()
map.putString("data", String(bytes))
sendEvent("USB_SERIAL_DATA", map)
},
config = readConfig
)
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Stop listening for raw serial data
*/
override fun offReadInterval(promise: Promise) {
try {
usbManager.offReadInterval()
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Get currently connected device
*/
override fun getConnectedDevice(promise: Promise) {
try {
val device = usbManager.getConnectedDevice()
if (device == null) {
promise.resolve(null)
} else {
promise.resolve(usbDeviceToMap(device))
}
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Read soil sensor data once
*/
override fun readSoilData(config: ReadableMap?, promise: Promise) {
try {
val slaveId = config?.getInt("slaveId") ?: 1
val startAddress = config?.getInt("startAddress") ?: 0x0000
val registerCount = config?.getInt("registerCount") ?: 8
val responseDelayMs = config?.getInt("responseDelayMs") ?: 300
val data = usbManager.utils.readSoilData(slaveId, startAddress, registerCount, responseDelayMs)
if (data == null) {
promise.resolve(null)
return
}
val map: WritableMap = Arguments.createMap()
data.forEach { (key: String, value: Double?) ->
if (value != null) {
map.putDouble(key, value)
}
}
promise.resolve(map)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Start listening for soil sensor data at specified interval
*/
override fun onReadSoilDataInterval(intervalMs: Double, config: ReadableMap?, promise: Promise) {
try {
val slaveId = config?.getInt("slaveId") ?: 1
val startAddress = config?.getInt("startAddress") ?: 0x0000
val registerCount = config?.getInt("registerCount") ?: 8
val responseDelayMs = config?.getInt("responseDelayMs") ?: 300
val soilConfig = SoilSensorConfig(slaveId, startAddress, registerCount, responseDelayMs)
usbManager.utils.onReadSoilDataInterval(
intervalMs = intervalMs.toLong(),
onDataReceived = { soilData: Map<String, Double?> ->
val map = Arguments.createMap()
soilData.forEach { (key: String, value: Double?) ->
if (value != null) {
map.putDouble(key, value)
}
}
sendEvent("USB_SOIL_DATA", map)
},
config = soilConfig
)
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
/**
* Stop listening for soil sensor data
*/
override fun offReadSoilDataInterval(promise: Promise) {
try {
usbManager.utils.offReadSoilDataInterval()
promise.resolve(null)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
companion object {
const val NAME = NativeUsbSerialSpec.NAME
}
}