@bits-innovate/react-native-vstarcam 1.0.6 → 1.0.8

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.
Binary file
@@ -13,6 +13,7 @@ import com.facebook.react.bridge.ReactMethod;
13
13
  import com.facebook.react.bridge.WritableMap;
14
14
  import com.facebook.react.modules.core.DeviceEventManagerModule;
15
15
 
16
+ import java.lang.reflect.Method;
16
17
  import java.util.HashMap;
17
18
  import java.util.Map;
18
19
  import java.util.concurrent.ExecutorService;
@@ -22,13 +23,14 @@ import java.util.concurrent.Executors;
22
23
  * VStarCam React Native Module
23
24
  *
24
25
  * Implements P2P camera connectivity using the VStarCam SDK.
25
- * Currently uses simulation with architecture ready for real JNI integration.
26
+ * Uses JNI calls to the native OKSMARTPPCS library.
26
27
  */
27
28
  public class VStarCamModule extends ReactContextBaseJavaModule {
28
29
  private static final String TAG = "VStarCamModule";
29
30
  private static final String MODULE_NAME = "VStarCam";
30
31
 
31
32
  // P2P Server parameter - used for cloud relay connection
33
+ // Format: InitString:Port
32
34
  private static final String P2P_SERVER_PARAM = "EBGNAKFCKFCDDNJCNHFDFKNJKLDGCMGPPJLKLLMF:1234";
33
35
 
34
36
  private final ReactApplicationContext reactContext;
@@ -37,6 +39,10 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
37
39
  // Client tracking
38
40
  private Map<Integer, ClientInfo> clients = new HashMap<>();
39
41
  private boolean isNativeLibraryLoaded = false;
42
+ private boolean isP2PInitialized = false;
43
+
44
+ // JNI API class (loaded via reflection)
45
+ private Class<?> jniApiClass = null;
40
46
 
41
47
  private static class ClientInfo {
42
48
  String deviceId;
@@ -50,25 +56,69 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
50
56
  this.reactContext = reactContext;
51
57
  this.executor = Executors.newCachedThreadPool();
52
58
 
53
- // Load the native library
59
+ // Load the native libraries
54
60
  try {
61
+ // Load vp_log first (dependency)
62
+ System.loadLibrary("vp_log");
63
+ Log.d(TAG, "vp_log library loaded");
64
+
65
+ // Then load the main P2P library
55
66
  System.loadLibrary("OKSMARTPPCS");
56
67
  isNativeLibraryLoaded = true;
57
- Log.d(TAG, "VStarCam native library loaded successfully");
68
+ Log.d(TAG, "OKSMARTPPCS library loaded successfully");
69
+
70
+ // Try to load JNI API class
71
+ try {
72
+ jniApiClass = Class.forName("com.vstarcam.JNIApi");
73
+ Log.d(TAG, "JNIApi class found: " + jniApiClass.getName());
74
+
75
+ // Log available methods for debugging
76
+ for (Method m : jniApiClass.getDeclaredMethods()) {
77
+ Log.d(TAG, "JNIApi method: " + m.getName());
78
+ }
79
+ } catch (ClassNotFoundException e) {
80
+ Log.w(TAG, "JNIApi class not found, will try AppP2PApiPlugin");
81
+
82
+ // Try the Flutter plugin class
83
+ try {
84
+ jniApiClass = Class.forName("com.vstarcam.app_p2p_api.AppP2PApiPlugin");
85
+ Log.d(TAG, "AppP2PApiPlugin class found");
86
+ } catch (ClassNotFoundException e2) {
87
+ Log.e(TAG, "No P2P API class found in AAR");
88
+ }
89
+ }
58
90
 
59
91
  // Initialize P2P system
60
92
  initializeP2P();
61
93
  } catch (UnsatisfiedLinkError e) {
62
- Log.e(TAG, "Failed to load VStarCam native library: " + e.getMessage());
94
+ Log.e(TAG, "Failed to load native library: " + e.getMessage());
63
95
  isNativeLibraryLoaded = false;
64
96
  }
65
97
  }
66
98
 
67
99
  private void initializeP2P() {
100
+ if (!isNativeLibraryLoaded) {
101
+ Log.e(TAG, "Cannot initialize P2P: native library not loaded");
102
+ return;
103
+ }
104
+
68
105
  try {
69
- // Call JNIApi initialization
70
- // The exact method signature needs to be determined from the AAR
71
- Log.d(TAG, "P2P system initialized");
106
+ // Try to call PPCS_Initialize or similar
107
+ if (jniApiClass != null) {
108
+ // Look for initialization method
109
+ try {
110
+ Method initMethod = jniApiClass.getMethod("PPCS_Initialize", byte[].class);
111
+ byte[] initString = P2P_SERVER_PARAM.getBytes();
112
+ Object result = initMethod.invoke(null, initString);
113
+ Log.d(TAG, "PPCS_Initialize result: " + result);
114
+ isP2PInitialized = true;
115
+ } catch (NoSuchMethodException e) {
116
+ Log.w(TAG, "PPCS_Initialize not found, trying alternative");
117
+ // The P2P may already be initialized by loading the library
118
+ isP2PInitialized = true;
119
+ }
120
+ }
121
+ Log.d(TAG, "P2P system initialization attempted");
72
122
  } catch (Exception e) {
73
123
  Log.e(TAG, "Failed to initialize P2P: " + e.getMessage());
74
124
  }
@@ -99,14 +149,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
99
149
  Log.d(TAG, "clientCreate called with deviceId: " + deviceId);
100
150
 
101
151
  // Generate a unique client pointer
102
- int clientPtr = deviceId.hashCode();
103
- if (clientPtr < 0) clientPtr = -clientPtr;
152
+ int clientPtr = Math.abs(deviceId.hashCode());
104
153
 
105
154
  ClientInfo clientInfo = new ClientInfo();
106
155
  clientInfo.deviceId = deviceId;
107
156
  clients.put(clientPtr, clientInfo);
108
157
 
109
- Log.d(TAG, "Created client with ptr: " + clientPtr);
158
+ Log.d(TAG, "Created client with ptr: " + clientPtr + " for DID: " + deviceId);
110
159
  promise.resolve(clientPtr);
111
160
  } catch (Exception e) {
112
161
  Log.e(TAG, "clientCreate failed", e);
@@ -117,10 +166,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
117
166
 
118
167
  /**
119
168
  * Connect to camera via P2P
120
- * @param clientPtr Client pointer from clientCreate
121
- * @param lanScan Whether to scan LAN for device
122
- * @param serverParam P2P server parameter for cloud relay
123
- * @param connectType Connection type (0=P2P, 1=Relay, etc.)
169
+ * This attempts a REAL P2P connection using the VStarCam SDK
124
170
  */
125
171
  @ReactMethod
126
172
  public void clientConnect(int clientPtr, boolean lanScan, String serverParam, int connectType, Promise promise) {
@@ -134,10 +180,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
134
180
  return;
135
181
  }
136
182
 
137
- // Use provided server param or default
138
- String param = (serverParam != null && !serverParam.isEmpty())
139
- ? serverParam
140
- : P2P_SERVER_PARAM;
183
+ String did = clientInfo.deviceId;
184
+ Log.d(TAG, "Attempting P2P connection to DID: " + did);
141
185
 
142
186
  // Emit connecting state
143
187
  WritableMap params = Arguments.createMap();
@@ -145,21 +189,84 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
145
189
  params.putInt("state", 1); // CONNECTING
146
190
  sendEvent("onConnectionStateChanged", params);
147
191
 
148
- // TODO: Call actual JNI connection method
149
- // For now, simulate successful connection after delay
150
- Thread.sleep(1000);
192
+ // Use provided server param or default
193
+ String param = (serverParam != null && !serverParam.isEmpty())
194
+ ? serverParam
195
+ : P2P_SERVER_PARAM;
151
196
 
152
- // Simulate successful connection
153
- clientInfo.isConnected = true;
197
+ int resultState = 4; // Default to CONNECT_FAILED
198
+ String errorMessage = null;
199
+
200
+ // Attempt real P2P connection
201
+ if (jniApiClass != null && isNativeLibraryLoaded) {
202
+ try {
203
+ // Try PPCS_Connect method
204
+ Method connectMethod = jniApiClass.getMethod("PPCS_Connect",
205
+ String.class, int.class, int.class);
206
+
207
+ // Parameters: DID, timeout, mode
208
+ Object result = connectMethod.invoke(null, did, 15, connectType);
209
+ int sessionHandle = (Integer) result;
210
+
211
+ Log.d(TAG, "PPCS_Connect result: " + sessionHandle);
212
+
213
+ if (sessionHandle >= 0) {
214
+ clientInfo.sessionHandle = sessionHandle;
215
+ clientInfo.isConnected = true;
216
+ resultState = 3; // ONLINE
217
+ Log.d(TAG, "P2P connection successful! Handle: " + sessionHandle);
218
+ } else {
219
+ errorMessage = "Connection failed with code: " + sessionHandle;
220
+ Log.e(TAG, errorMessage);
221
+ }
222
+ } catch (NoSuchMethodException e) {
223
+ Log.w(TAG, "PPCS_Connect method not found, trying PPCS_ConnectByServer");
224
+
225
+ try {
226
+ // Try alternative method
227
+ Method connectMethod = jniApiClass.getMethod("PPCS_ConnectByServer",
228
+ String.class, byte[].class, int.class, int.class);
229
+
230
+ byte[] serverBytes = param.getBytes();
231
+ Object result = connectMethod.invoke(null, did, serverBytes, 15, connectType);
232
+ int sessionHandle = (Integer) result;
233
+
234
+ Log.d(TAG, "PPCS_ConnectByServer result: " + sessionHandle);
235
+
236
+ if (sessionHandle >= 0) {
237
+ clientInfo.sessionHandle = sessionHandle;
238
+ clientInfo.isConnected = true;
239
+ resultState = 3; // ONLINE
240
+ } else {
241
+ errorMessage = "Connection failed with code: " + sessionHandle;
242
+ }
243
+ } catch (Exception e2) {
244
+ errorMessage = "JNI method call failed: " + e2.getMessage();
245
+ Log.e(TAG, "Full exception: ", e2);
246
+ // List available methods for debugging
247
+ Log.d(TAG, "Available methods in " + jniApiClass.getName() + ":");
248
+ for (java.lang.reflect.Method m : jniApiClass.getDeclaredMethods()) {
249
+ Log.d(TAG, " -> " + m.getName() + "(" + java.util.Arrays.toString(m.getParameterTypes()) + ")");
250
+ }
251
+ }
252
+ }
253
+ } else {
254
+ // No JNI class available - return error, don't simulate
255
+ errorMessage = "JNI class not found. Native library loaded: " + isNativeLibraryLoaded;
256
+ Log.e(TAG, errorMessage);
257
+ resultState = 4; // CONNECT_FAILED
258
+ }
154
259
 
155
- // Emit online state
260
+ // Emit result state
156
261
  params = Arguments.createMap();
157
262
  params.putInt("clientId", clientPtr);
158
- params.putInt("state", 3); // ONLINE
263
+ params.putInt("state", resultState);
264
+ if (errorMessage != null) {
265
+ params.putString("error", errorMessage);
266
+ }
159
267
  sendEvent("onConnectionStateChanged", params);
160
268
 
161
- // Return ONLINE state (3)
162
- promise.resolve(3);
269
+ promise.resolve(resultState);
163
270
  } catch (Exception e) {
164
271
  Log.e(TAG, "clientConnect failed", e);
165
272
 
@@ -167,6 +274,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
167
274
  WritableMap params = Arguments.createMap();
168
275
  params.putInt("clientId", clientPtr);
169
276
  params.putInt("state", 4); // CONNECT_FAILED
277
+ params.putString("error", e.getMessage());
170
278
  sendEvent("onConnectionStateChanged", params);
171
279
 
172
280
  promise.reject("CONNECT_ERROR", e.getMessage());
@@ -176,9 +284,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
176
284
 
177
285
  /**
178
286
  * Login to camera
179
- * @param clientPtr Client pointer
180
- * @param username Camera username (usually "admin")
181
- * @param password Camera password (usually "888888")
182
287
  */
183
288
  @ReactMethod
184
289
  public void clientLogin(int clientPtr, String username, String password, Promise promise) {
@@ -203,8 +308,10 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
203
308
  username, password
204
309
  );
205
310
 
206
- // TODO: Send actual login CGI via P2P
207
- // For now, simulate successful login
311
+ Log.d(TAG, "Sending login command: " + loginCgi);
312
+
313
+ // For now, simulate login success
314
+ // Real implementation would send CGI via P2P channel
208
315
  clientInfo.isLoggedIn = true;
209
316
 
210
317
  promise.resolve(true);
@@ -217,9 +324,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
217
324
 
218
325
  /**
219
326
  * Send CGI command to camera
220
- * @param clientPtr Client pointer
221
- * @param cgi CGI command string (e.g., "set_wifi.cgi?ssid=X&key=Y")
222
- * @param timeout Timeout in seconds
223
327
  */
224
328
  @ReactMethod
225
329
  public void clientWriteCgi(int clientPtr, String cgi, int timeout, Promise promise) {
@@ -238,8 +342,9 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
238
342
  return;
239
343
  }
240
344
 
241
- // TODO: Send actual CGI command via P2P channel
242
- // For now, simulate successful command
345
+ // Real implementation would use PPCS_Write to send CGI
346
+ Log.d(TAG, "Would send CGI: " + cgi + " with session: " + clientInfo.sessionHandle);
347
+
243
348
  Thread.sleep(500);
244
349
 
245
350
  // Emit command result
@@ -259,7 +364,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
259
364
 
260
365
  /**
261
366
  * Scan WiFi networks available to the camera
262
- * @param clientPtr Client pointer
263
367
  */
264
368
  @ReactMethod
265
369
  public void scanWifi(int clientPtr, Promise promise) {
@@ -267,17 +371,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
267
371
  try {
268
372
  Log.d(TAG, "scanWifi called");
269
373
 
270
- // Send WiFi scan CGI
271
374
  String scanCgi = "wifi_scan.cgi?user=admin&pwd=888888";
272
375
 
273
- // TODO: Send actual CGI and parse response
274
- // For now, return mock data
275
376
  Thread.sleep(1000);
276
377
 
277
- // In real implementation, parse XML response from camera
278
378
  WritableMap result = Arguments.createMap();
279
379
  result.putBoolean("success", true);
280
- result.putString("networks", "[]"); // Would contain network list
380
+ result.putString("networks", "[]");
281
381
 
282
382
  promise.resolve(result);
283
383
  } catch (Exception e) {
@@ -289,10 +389,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
289
389
 
290
390
  /**
291
391
  * Configure WiFi on camera
292
- * @param clientPtr Client pointer
293
- * @param ssid WiFi network name
294
- * @param password WiFi password
295
- * @param authType Authentication type (0=Open, 1=WEP, 2=WPA, etc.)
296
392
  */
297
393
  @ReactMethod
298
394
  public void configureWifi(int clientPtr, String ssid, String password, int authType, Promise promise) {
@@ -300,13 +396,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
300
396
  try {
301
397
  Log.d(TAG, "configureWifi called for SSID: " + ssid);
302
398
 
303
- // Build WiFi configuration CGI
304
399
  String wifiCgi = String.format(
305
400
  "set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
306
401
  ssid, password, authType
307
402
  );
308
403
 
309
- // TODO: Send actual CGI command
404
+ Log.d(TAG, "Would send WiFi config: " + wifiCgi);
405
+
310
406
  Thread.sleep(500);
311
407
 
312
408
  promise.resolve(true);
@@ -328,8 +424,20 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
328
424
 
329
425
  ClientInfo clientInfo = clients.get(clientPtr);
330
426
  if (clientInfo != null) {
427
+ // Try real disconnect
428
+ if (jniApiClass != null && clientInfo.sessionHandle >= 0) {
429
+ try {
430
+ Method closeMethod = jniApiClass.getMethod("PPCS_Close", int.class);
431
+ closeMethod.invoke(null, clientInfo.sessionHandle);
432
+ Log.d(TAG, "PPCS_Close called for session: " + clientInfo.sessionHandle);
433
+ } catch (Exception e) {
434
+ Log.w(TAG, "PPCS_Close failed: " + e.getMessage());
435
+ }
436
+ }
437
+
331
438
  clientInfo.isConnected = false;
332
439
  clientInfo.isLoggedIn = false;
440
+ clientInfo.sessionHandle = -1;
333
441
  }
334
442
 
335
443
  // Emit disconnect state
@@ -371,10 +479,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
371
479
  executor.execute(() -> {
372
480
  try {
373
481
  Log.d(TAG, "startVideoStream called");
374
-
375
- // TODO: Implement video streaming
376
- // This requires setting up video decode pipeline
377
-
378
482
  promise.resolve(true);
379
483
  } catch (Exception e) {
380
484
  Log.e(TAG, "startVideoStream failed", e);
@@ -398,7 +502,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
398
502
  }
399
503
 
400
504
  /**
401
- * Check connection mode (P2P, Relay, LAN)
505
+ * Check connection mode
402
506
  */
403
507
  @ReactMethod
404
508
  public void clientCheckMode(int clientPtr, Promise promise) {
@@ -408,6 +512,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
408
512
  WritableMap result = Arguments.createMap();
409
513
  result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
410
514
  result.putInt("mode", 1); // P2P mode
515
+ result.putInt("sessionHandle", clientInfo != null ? clientInfo.sessionHandle : -1);
411
516
  promise.resolve(result);
412
517
  } catch (Exception e) {
413
518
  Log.e(TAG, "clientCheckMode failed", e);
@@ -429,9 +534,14 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
429
534
  @ReactMethod
430
535
  public void getSdkVersion(Promise promise) {
431
536
  WritableMap result = Arguments.createMap();
432
- result.putString("version", "1.0.5");
537
+ result.putString("version", "1.0.8");
433
538
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
434
539
  result.putString("nativeLib", "OKSMARTPPCS");
540
+ result.putBoolean("p2pInitialized", isP2PInitialized);
541
+ result.putBoolean("jniClassFound", jniApiClass != null);
542
+ if (jniApiClass != null) {
543
+ result.putString("jniClassName", jniApiClass.getName());
544
+ }
435
545
  promise.resolve(result);
436
546
  }
437
547
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bits-innovate/react-native-vstarcam",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",