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

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.
@@ -13,7 +13,9 @@ 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.InvocationHandler;
16
17
  import java.lang.reflect.Method;
18
+ import java.lang.reflect.Proxy;
17
19
  import java.util.HashMap;
18
20
  import java.util.Map;
19
21
  import java.util.concurrent.ExecutorService;
@@ -23,30 +25,41 @@ import java.util.concurrent.Executors;
23
25
  * VStarCam React Native Module
24
26
  *
25
27
  * Implements P2P camera connectivity using the VStarCam SDK.
26
- * Uses JNI calls to the native OKSMARTPPCS library.
28
+ * Uses JNI calls to the native OKSMARTPPCS library via JNIApi class.
29
+ *
30
+ * JNI API Methods (discovered via reflection):
31
+ * - create(String did, String serverParam) -> long clientPtr
32
+ * - connect(long clientPtr, int timeout, String serverParam, int connectType)
33
+ * - login(long clientPtr, String username, String password)
34
+ * - disconnect(long clientPtr)
35
+ * - destroy(long clientPtr)
36
+ * - writeCgi(long clientPtr, String cgi, int timeout)
37
+ * - init(ClientStateListener, ClientCommandListener, ClientReleaseListener)
27
38
  */
28
39
  public class VStarCamModule extends ReactContextBaseJavaModule {
29
40
  private static final String TAG = "VStarCamModule";
30
41
  private static final String MODULE_NAME = "VStarCam";
31
42
 
32
43
  // P2P Server parameter - used for cloud relay connection
33
- // Format: InitString:Port
34
44
  private static final String P2P_SERVER_PARAM = "EBGNAKFCKFCDDNJCNHFDFKNJKLDGCMGPPJLKLLMF:1234";
35
45
 
36
46
  private final ReactApplicationContext reactContext;
37
47
  private final ExecutorService executor;
38
48
 
39
- // Client tracking
49
+ // Client tracking - maps our clientPtr to actual SDK client handle
40
50
  private Map<Integer, ClientInfo> clients = new HashMap<>();
41
51
  private boolean isNativeLibraryLoaded = false;
42
52
  private boolean isP2PInitialized = false;
43
53
 
44
- // JNI API class (loaded via reflection)
54
+ // JNI API class and listener interfaces
45
55
  private Class<?> jniApiClass = null;
56
+ private Class<?> stateListenerClass = null;
57
+ private Class<?> commandListenerClass = null;
58
+ private Class<?> releaseListenerClass = null;
46
59
 
47
60
  private static class ClientInfo {
48
61
  String deviceId;
49
- int sessionHandle = -1;
62
+ long sdkClientPtr = 0; // Actual SDK client pointer (long)
50
63
  boolean isConnected = false;
51
64
  boolean isLoggedIn = false;
52
65
  }
@@ -67,29 +80,22 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
67
80
  isNativeLibraryLoaded = true;
68
81
  Log.d(TAG, "OKSMARTPPCS library loaded successfully");
69
82
 
70
- // Try to load JNI API class
83
+ // Load JNI API class
71
84
  try {
72
85
  jniApiClass = Class.forName("com.vstarcam.JNIApi");
73
86
  Log.d(TAG, "JNIApi class found: " + jniApiClass.getName());
74
87
 
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");
88
+ // Load listener interfaces
89
+ stateListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientStateListener");
90
+ commandListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientCommandListener");
91
+ releaseListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientReleaseListener");
92
+ Log.d(TAG, "Listener interfaces loaded");
81
93
 
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
- }
94
+ // Initialize P2P system with listeners
95
+ initializeP2P();
96
+ } catch (ClassNotFoundException e) {
97
+ Log.e(TAG, "JNIApi class not found: " + e.getMessage());
89
98
  }
90
-
91
- // Initialize P2P system
92
- initializeP2P();
93
99
  } catch (UnsatisfiedLinkError e) {
94
100
  Log.e(TAG, "Failed to load native library: " + e.getMessage());
95
101
  isNativeLibraryLoaded = false;
@@ -97,30 +103,111 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
97
103
  }
98
104
 
99
105
  private void initializeP2P() {
100
- if (!isNativeLibraryLoaded) {
101
- Log.e(TAG, "Cannot initialize P2P: native library not loaded");
106
+ if (!isNativeLibraryLoaded || jniApiClass == null) {
107
+ Log.e(TAG, "Cannot initialize P2P: native library or JNIApi not available");
102
108
  return;
103
109
  }
104
110
 
105
111
  try {
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;
112
+ // Create dynamic proxy for ClientStateListener
113
+ Object stateListener = Proxy.newProxyInstance(
114
+ stateListenerClass.getClassLoader(),
115
+ new Class<?>[] { stateListenerClass },
116
+ new InvocationHandler() {
117
+ @Override
118
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
119
+ Log.d(TAG, "ClientStateListener." + method.getName() + " called");
120
+ if (method.getName().equals("stateChange")) {
121
+ // args: long clientPtr, int state
122
+ long clientPtr = (Long) args[0];
123
+ int state = (Integer) args[1];
124
+ handleStateChange(clientPtr, state);
125
+ }
126
+ return null;
127
+ }
119
128
  }
120
- }
121
- Log.d(TAG, "P2P system initialization attempted");
129
+ );
130
+
131
+ // Create dynamic proxy for ClientCommandListener
132
+ Object commandListener = Proxy.newProxyInstance(
133
+ commandListenerClass.getClassLoader(),
134
+ new Class<?>[] { commandListenerClass },
135
+ new InvocationHandler() {
136
+ @Override
137
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
138
+ Log.d(TAG, "ClientCommandListener." + method.getName() + " called");
139
+ if (method.getName().equals("commandReceive")) {
140
+ // args: long clientPtr, int command, byte[] data, int length
141
+ long clientPtr = (Long) args[0];
142
+ int command = (Integer) args[1];
143
+ byte[] data = (byte[]) args[2];
144
+ handleCommandReceive(clientPtr, command, data);
145
+ }
146
+ return null;
147
+ }
148
+ }
149
+ );
150
+
151
+ // Create dynamic proxy for ClientReleaseListener
152
+ Object releaseListener = Proxy.newProxyInstance(
153
+ releaseListenerClass.getClassLoader(),
154
+ new Class<?>[] { releaseListenerClass },
155
+ new InvocationHandler() {
156
+ @Override
157
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
158
+ Log.d(TAG, "ClientReleaseListener." + method.getName() + " called");
159
+ return null;
160
+ }
161
+ }
162
+ );
163
+
164
+ // Call JNIApi.init(stateListener, commandListener, releaseListener)
165
+ Method initMethod = jniApiClass.getMethod("init",
166
+ stateListenerClass, commandListenerClass, releaseListenerClass);
167
+ initMethod.invoke(null, stateListener, commandListener, releaseListener);
168
+
169
+ isP2PInitialized = true;
170
+ Log.d(TAG, "P2P system initialized successfully!");
122
171
  } catch (Exception e) {
123
- Log.e(TAG, "Failed to initialize P2P: " + e.getMessage());
172
+ Log.e(TAG, "Failed to initialize P2P: " + e.getMessage(), e);
173
+ }
174
+ }
175
+
176
+ private void handleStateChange(long clientPtr, int state) {
177
+ Log.d(TAG, "State change: clientPtr=" + clientPtr + ", state=" + state);
178
+
179
+ // Find our client by SDK pointer
180
+ for (Map.Entry<Integer, ClientInfo> entry : clients.entrySet()) {
181
+ if (entry.getValue().sdkClientPtr == clientPtr) {
182
+ int ourClientPtr = entry.getKey();
183
+
184
+ WritableMap params = Arguments.createMap();
185
+ params.putInt("clientId", ourClientPtr);
186
+ params.putInt("state", state);
187
+ sendEvent("onConnectionStateChanged", params);
188
+
189
+ // Update connected state
190
+ entry.getValue().isConnected = (state == 3); // ONLINE
191
+ break;
192
+ }
193
+ }
194
+ }
195
+
196
+ private void handleCommandReceive(long clientPtr, int command, byte[] data) {
197
+ Log.d(TAG, "Command receive: clientPtr=" + clientPtr + ", command=" + command);
198
+
199
+ // Find our client by SDK pointer
200
+ for (Map.Entry<Integer, ClientInfo> entry : clients.entrySet()) {
201
+ if (entry.getValue().sdkClientPtr == clientPtr) {
202
+ int ourClientPtr = entry.getKey();
203
+
204
+ WritableMap params = Arguments.createMap();
205
+ params.putInt("clientId", ourClientPtr);
206
+ params.putInt("command", command);
207
+ params.putString("data", data != null ? new String(data) : "");
208
+ sendEvent("onCommandReceived", params);
209
+ break;
210
+ }
124
211
  }
125
212
  }
126
213
 
@@ -140,7 +227,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
140
227
 
141
228
  /**
142
229
  * Create a P2P client for a device
143
- * @param deviceId The camera's Device ID (DID)
230
+ * JNIApi.create(String did, String serverParam) -> long
144
231
  */
145
232
  @ReactMethod
146
233
  public void clientCreate(String deviceId, Promise promise) {
@@ -148,15 +235,34 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
148
235
  try {
149
236
  Log.d(TAG, "clientCreate called with deviceId: " + deviceId);
150
237
 
151
- // Generate a unique client pointer
152
- int clientPtr = Math.abs(deviceId.hashCode());
238
+ if (jniApiClass == null) {
239
+ promise.reject("CREATE_ERROR", "JNIApi not available");
240
+ return;
241
+ }
242
+
243
+ // Call JNIApi.create(did, serverParam)
244
+ Method createMethod = jniApiClass.getMethod("create", String.class, String.class);
245
+ Object result = createMethod.invoke(null, deviceId, P2P_SERVER_PARAM);
246
+ long sdkClientPtr = (Long) result;
247
+
248
+ Log.d(TAG, "JNIApi.create result: " + sdkClientPtr);
249
+
250
+ // Note: pointer can be negative (unsigned long cast to signed) - only 0 is invalid
251
+ if (sdkClientPtr == 0) {
252
+ promise.reject("CREATE_ERROR", "Failed to create client, result: " + sdkClientPtr);
253
+ return;
254
+ }
255
+
256
+ // Generate our own client ID (hash of deviceId) and store mapping
257
+ int ourClientPtr = Math.abs(deviceId.hashCode());
153
258
 
154
259
  ClientInfo clientInfo = new ClientInfo();
155
260
  clientInfo.deviceId = deviceId;
156
- clients.put(clientPtr, clientInfo);
261
+ clientInfo.sdkClientPtr = sdkClientPtr;
262
+ clients.put(ourClientPtr, clientInfo);
157
263
 
158
- Log.d(TAG, "Created client with ptr: " + clientPtr + " for DID: " + deviceId);
159
- promise.resolve(clientPtr);
264
+ Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr);
265
+ promise.resolve(ourClientPtr);
160
266
  } catch (Exception e) {
161
267
  Log.e(TAG, "clientCreate failed", e);
162
268
  promise.reject("CREATE_ERROR", e.getMessage());
@@ -166,7 +272,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
166
272
 
167
273
  /**
168
274
  * Connect to camera via P2P
169
- * This attempts a REAL P2P connection using the VStarCam SDK
275
+ * JNIApi.connect(long clientPtr, int timeout, String serverParam, int connectType)
170
276
  */
171
277
  @ReactMethod
172
278
  public void clientConnect(int clientPtr, boolean lanScan, String serverParam, int connectType, Promise promise) {
@@ -180,8 +286,10 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
180
286
  return;
181
287
  }
182
288
 
183
- String did = clientInfo.deviceId;
184
- Log.d(TAG, "Attempting P2P connection to DID: " + did);
289
+ if (jniApiClass == null) {
290
+ promise.reject("CONNECT_ERROR", "JNIApi not available");
291
+ return;
292
+ }
185
293
 
186
294
  // Emit connecting state
187
295
  WritableMap params = Arguments.createMap();
@@ -189,88 +297,26 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
189
297
  params.putInt("state", 1); // CONNECTING
190
298
  sendEvent("onConnectionStateChanged", params);
191
299
 
192
- // Use provided server param or default
193
300
  String param = (serverParam != null && !serverParam.isEmpty())
194
301
  ? serverParam
195
302
  : P2P_SERVER_PARAM;
196
303
 
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
- }
304
+ // Call JNIApi.connect(sdkClientPtr, timeout, serverParam, connectType)
305
+ // Signature: connect([long, int, class java.lang.String, int])
306
+ Method connectMethod = jniApiClass.getMethod("connect",
307
+ long.class, int.class, String.class, int.class);
259
308
 
260
- // Emit result state
261
- params = Arguments.createMap();
262
- params.putInt("clientId", clientPtr);
263
- params.putInt("state", resultState);
264
- if (errorMessage != null) {
265
- params.putString("error", errorMessage);
266
- }
267
- sendEvent("onConnectionStateChanged", params);
309
+ Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + connectType + ")");
310
+ connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, connectType);
311
+
312
+ Log.d(TAG, "JNIApi.connect called - waiting for state callback");
268
313
 
269
- promise.resolve(resultState);
314
+ // The actual state will come via the ClientStateListener callback
315
+ // For now, return immediately - the JS side will get updates via events
316
+ promise.resolve(1); // CONNECTING
270
317
  } catch (Exception e) {
271
318
  Log.e(TAG, "clientConnect failed", e);
272
319
 
273
- // Emit connection failed state
274
320
  WritableMap params = Arguments.createMap();
275
321
  params.putInt("clientId", clientPtr);
276
322
  params.putInt("state", 4); // CONNECT_FAILED
@@ -284,6 +330,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
284
330
 
285
331
  /**
286
332
  * Login to camera
333
+ * JNIApi.login(long clientPtr, String username, String password)
287
334
  */
288
335
  @ReactMethod
289
336
  public void clientLogin(int clientPtr, String username, String password, Promise promise) {
@@ -297,22 +344,20 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
297
344
  return;
298
345
  }
299
346
 
300
- if (!clientInfo.isConnected) {
301
- promise.reject("LOGIN_ERROR", "Not connected");
347
+ if (jniApiClass == null) {
348
+ promise.reject("LOGIN_ERROR", "JNIApi not available");
302
349
  return;
303
350
  }
304
351
 
305
- // Build login CGI command
306
- String loginCgi = String.format(
307
- "login.cgi?user=%s&pwd=%s",
308
- username, password
309
- );
352
+ // Call JNIApi.login(sdkClientPtr, username, password)
353
+ Method loginMethod = jniApiClass.getMethod("login",
354
+ long.class, String.class, String.class);
310
355
 
311
- Log.d(TAG, "Sending login command: " + loginCgi);
356
+ Log.d(TAG, "Calling JNIApi.login(" + clientInfo.sdkClientPtr + ", " + username + ", ***)");
357
+ loginMethod.invoke(null, clientInfo.sdkClientPtr, username, password);
312
358
 
313
- // For now, simulate login success
314
- // Real implementation would send CGI via P2P channel
315
359
  clientInfo.isLoggedIn = true;
360
+ Log.d(TAG, "JNIApi.login called successfully");
316
361
 
317
362
  promise.resolve(true);
318
363
  } catch (Exception e) {
@@ -324,6 +369,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
324
369
 
325
370
  /**
326
371
  * Send CGI command to camera
372
+ * JNIApi.writeCgi(long clientPtr, String cgi, int timeout)
327
373
  */
328
374
  @ReactMethod
329
375
  public void clientWriteCgi(int clientPtr, String cgi, int timeout, Promise promise) {
@@ -337,23 +383,19 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
337
383
  return;
338
384
  }
339
385
 
340
- if (!clientInfo.isConnected) {
341
- promise.reject("CGI_ERROR", "Not connected");
386
+ if (jniApiClass == null) {
387
+ promise.reject("CGI_ERROR", "JNIApi not available");
342
388
  return;
343
389
  }
344
390
 
345
- // Real implementation would use PPCS_Write to send CGI
346
- Log.d(TAG, "Would send CGI: " + cgi + " with session: " + clientInfo.sessionHandle);
391
+ // Call JNIApi.writeCgi(sdkClientPtr, cgi, timeout)
392
+ Method writeCgiMethod = jniApiClass.getMethod("writeCgi",
393
+ long.class, String.class, int.class);
347
394
 
348
- Thread.sleep(500);
349
-
350
- // Emit command result
351
- WritableMap params = Arguments.createMap();
352
- params.putInt("clientId", clientPtr);
353
- params.putInt("command", cgi.hashCode());
354
- params.putString("data", "OK");
355
- sendEvent("onCommandReceived", params);
395
+ Log.d(TAG, "Calling JNIApi.writeCgi(" + clientInfo.sdkClientPtr + ", " + cgi + ", " + timeout + ")");
396
+ writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, timeout);
356
397
 
398
+ Log.d(TAG, "JNIApi.writeCgi called successfully");
357
399
  promise.resolve(true);
358
400
  } catch (Exception e) {
359
401
  Log.e(TAG, "clientWriteCgi failed", e);
@@ -367,24 +409,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
367
409
  */
368
410
  @ReactMethod
369
411
  public void scanWifi(int clientPtr, Promise promise) {
370
- executor.execute(() -> {
371
- try {
372
- Log.d(TAG, "scanWifi called");
373
-
374
- String scanCgi = "wifi_scan.cgi?user=admin&pwd=888888";
375
-
376
- Thread.sleep(1000);
377
-
378
- WritableMap result = Arguments.createMap();
379
- result.putBoolean("success", true);
380
- result.putString("networks", "[]");
381
-
382
- promise.resolve(result);
383
- } catch (Exception e) {
384
- Log.e(TAG, "scanWifi failed", e);
385
- promise.reject("WIFI_ERROR", e.getMessage());
386
- }
387
- });
412
+ // Use writeCgi to send wifi_scan command
413
+ clientWriteCgi(clientPtr, "wifi_scan.cgi?user=admin&pwd=888888", 10, promise);
388
414
  }
389
415
 
390
416
  /**
@@ -392,58 +418,36 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
392
418
  */
393
419
  @ReactMethod
394
420
  public void configureWifi(int clientPtr, String ssid, String password, int authType, Promise promise) {
395
- executor.execute(() -> {
396
- try {
397
- Log.d(TAG, "configureWifi called for SSID: " + ssid);
398
-
399
- String wifiCgi = String.format(
400
- "set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
401
- ssid, password, authType
402
- );
403
-
404
- Log.d(TAG, "Would send WiFi config: " + wifiCgi);
405
-
406
- Thread.sleep(500);
407
-
408
- promise.resolve(true);
409
- } catch (Exception e) {
410
- Log.e(TAG, "configureWifi failed", e);
411
- promise.reject("WIFI_ERROR", e.getMessage());
412
- }
413
- });
421
+ String wifiCgi = String.format(
422
+ "set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
423
+ ssid, password, authType
424
+ );
425
+ clientWriteCgi(clientPtr, wifiCgi, 10, promise);
414
426
  }
415
427
 
416
428
  /**
417
429
  * Disconnect from camera
430
+ * JNIApi.disconnect(long clientPtr)
418
431
  */
419
432
  @ReactMethod
420
433
  public void clientDisconnect(int clientPtr, Promise promise) {
421
434
  executor.execute(() -> {
422
435
  try {
423
- Log.d(TAG, "clientDisconnect called");
436
+ Log.d(TAG, "clientDisconnect called for: " + clientPtr);
424
437
 
425
438
  ClientInfo clientInfo = clients.get(clientPtr);
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
- }
439
+ if (clientInfo != null && jniApiClass != null) {
440
+ Method disconnectMethod = jniApiClass.getMethod("disconnect", long.class);
441
+ disconnectMethod.invoke(null, clientInfo.sdkClientPtr);
437
442
 
438
443
  clientInfo.isConnected = false;
439
444
  clientInfo.isLoggedIn = false;
440
- clientInfo.sessionHandle = -1;
445
+ Log.d(TAG, "JNIApi.disconnect called successfully");
441
446
  }
442
447
 
443
- // Emit disconnect state
444
448
  WritableMap params = Arguments.createMap();
445
449
  params.putInt("clientId", clientPtr);
446
- params.putInt("state", 5); // DISCONNECT
450
+ params.putInt("state", 5); // DISCONNECTED
447
451
  sendEvent("onConnectionStateChanged", params);
448
452
 
449
453
  promise.resolve(true);
@@ -456,12 +460,21 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
456
460
 
457
461
  /**
458
462
  * Destroy client and cleanup resources
463
+ * JNIApi.destroy(long clientPtr)
459
464
  */
460
465
  @ReactMethod
461
466
  public void clientDestroy(int clientPtr, Promise promise) {
462
467
  executor.execute(() -> {
463
468
  try {
464
- Log.d(TAG, "clientDestroy called");
469
+ Log.d(TAG, "clientDestroy called for: " + clientPtr);
470
+
471
+ ClientInfo clientInfo = clients.get(clientPtr);
472
+ if (clientInfo != null && jniApiClass != null) {
473
+ Method destroyMethod = jniApiClass.getMethod("destroy", long.class);
474
+ destroyMethod.invoke(null, clientInfo.sdkClientPtr);
475
+ Log.d(TAG, "JNIApi.destroy called successfully");
476
+ }
477
+
465
478
  clients.remove(clientPtr);
466
479
  promise.resolve(true);
467
480
  } catch (Exception e) {
@@ -476,15 +489,9 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
476
489
  */
477
490
  @ReactMethod
478
491
  public void startVideoStream(int clientPtr, int streamType, Promise promise) {
479
- executor.execute(() -> {
480
- try {
481
- Log.d(TAG, "startVideoStream called");
482
- promise.resolve(true);
483
- } catch (Exception e) {
484
- Log.e(TAG, "startVideoStream failed", e);
485
- promise.reject("VIDEO_ERROR", e.getMessage());
486
- }
487
- });
492
+ // TODO: Implement video streaming
493
+ Log.d(TAG, "startVideoStream called - not yet implemented");
494
+ promise.resolve(true);
488
495
  }
489
496
 
490
497
  /**
@@ -492,27 +499,35 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
492
499
  */
493
500
  @ReactMethod
494
501
  public void stopVideoStream(int clientPtr, Promise promise) {
495
- try {
496
- Log.d(TAG, "stopVideoStream called");
497
- promise.resolve(true);
498
- } catch (Exception e) {
499
- Log.e(TAG, "stopVideoStream failed", e);
500
- promise.reject("VIDEO_ERROR", e.getMessage());
501
- }
502
+ Log.d(TAG, "stopVideoStream called");
503
+ promise.resolve(true);
502
504
  }
503
505
 
504
506
  /**
505
507
  * Check connection mode
508
+ * JNIApi.checkMode(long clientPtr)
506
509
  */
507
510
  @ReactMethod
508
511
  public void clientCheckMode(int clientPtr, Promise promise) {
509
512
  try {
510
513
  ClientInfo clientInfo = clients.get(clientPtr);
511
514
 
515
+ int mode = 0;
516
+ if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr > 0) {
517
+ try {
518
+ Method checkModeMethod = jniApiClass.getMethod("checkMode", long.class);
519
+ Object result = checkModeMethod.invoke(null, clientInfo.sdkClientPtr);
520
+ mode = (Integer) result;
521
+ Log.d(TAG, "JNIApi.checkMode result: " + mode);
522
+ } catch (Exception e) {
523
+ Log.e(TAG, "checkMode failed", e);
524
+ }
525
+ }
526
+
512
527
  WritableMap result = Arguments.createMap();
513
528
  result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
514
- result.putInt("mode", 1); // P2P mode
515
- result.putInt("sessionHandle", clientInfo != null ? clientInfo.sessionHandle : -1);
529
+ result.putInt("mode", mode);
530
+ result.putDouble("sessionHandle", clientInfo != null ? clientInfo.sdkClientPtr : -1);
516
531
  promise.resolve(result);
517
532
  } catch (Exception e) {
518
533
  Log.e(TAG, "clientCheckMode failed", e);
@@ -534,7 +549,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
534
549
  @ReactMethod
535
550
  public void getSdkVersion(Promise promise) {
536
551
  WritableMap result = Arguments.createMap();
537
- result.putString("version", "1.0.8");
552
+ result.putString("version", "1.0.10");
538
553
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
539
554
  result.putString("nativeLib", "OKSMARTPPCS");
540
555
  result.putBoolean("p2pInitialized", isP2PInitialized);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bits-innovate/react-native-vstarcam",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",