@bits-innovate/react-native-vstarcam 1.0.7 → 1.0.9

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,33 @@ 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
+ if (sdkClientPtr <= 0) {
251
+ promise.reject("CREATE_ERROR", "Failed to create client, result: " + sdkClientPtr);
252
+ return;
253
+ }
254
+
255
+ // Generate our own client ID (hash of deviceId) and store mapping
256
+ int ourClientPtr = Math.abs(deviceId.hashCode());
153
257
 
154
258
  ClientInfo clientInfo = new ClientInfo();
155
259
  clientInfo.deviceId = deviceId;
156
- clients.put(clientPtr, clientInfo);
260
+ clientInfo.sdkClientPtr = sdkClientPtr;
261
+ clients.put(ourClientPtr, clientInfo);
157
262
 
158
- Log.d(TAG, "Created client with ptr: " + clientPtr + " for DID: " + deviceId);
159
- promise.resolve(clientPtr);
263
+ Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr);
264
+ promise.resolve(ourClientPtr);
160
265
  } catch (Exception e) {
161
266
  Log.e(TAG, "clientCreate failed", e);
162
267
  promise.reject("CREATE_ERROR", e.getMessage());
@@ -166,7 +271,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
166
271
 
167
272
  /**
168
273
  * Connect to camera via P2P
169
- * This attempts a REAL P2P connection using the VStarCam SDK
274
+ * JNIApi.connect(long clientPtr, int timeout, String serverParam, int connectType)
170
275
  */
171
276
  @ReactMethod
172
277
  public void clientConnect(int clientPtr, boolean lanScan, String serverParam, int connectType, Promise promise) {
@@ -180,8 +285,10 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
180
285
  return;
181
286
  }
182
287
 
183
- String did = clientInfo.deviceId;
184
- Log.d(TAG, "Attempting P2P connection to DID: " + did);
288
+ if (jniApiClass == null) {
289
+ promise.reject("CONNECT_ERROR", "JNIApi not available");
290
+ return;
291
+ }
185
292
 
186
293
  // Emit connecting state
187
294
  WritableMap params = Arguments.createMap();
@@ -189,89 +296,26 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
189
296
  params.putInt("state", 1); // CONNECTING
190
297
  sendEvent("onConnectionStateChanged", params);
191
298
 
192
- // Use provided server param or default
193
299
  String param = (serverParam != null && !serverParam.isEmpty())
194
300
  ? serverParam
195
301
  : P2P_SERVER_PARAM;
196
302
 
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
- Log.e(TAG, "P2P connection method failed: " + e2.getMessage());
245
- errorMessage = "JNI method call failed: " + e2.getMessage();
246
-
247
- // Fallback to simulation for testing
248
- Log.w(TAG, "Falling back to simulated connection");
249
- clientInfo.isConnected = true;
250
- resultState = 3; // Simulated ONLINE
251
- }
252
- }
253
- } else {
254
- // No JNI class available - use simulation
255
- Log.w(TAG, "JNI class not available, using simulated connection");
256
- Thread.sleep(1000);
257
- clientInfo.isConnected = true;
258
- resultState = 3; // Simulated ONLINE
259
- }
303
+ // Call JNIApi.connect(sdkClientPtr, timeout, serverParam, connectType)
304
+ // Signature: connect([long, int, class java.lang.String, int])
305
+ Method connectMethod = jniApiClass.getMethod("connect",
306
+ long.class, int.class, String.class, int.class);
260
307
 
261
- // Emit result state
262
- params = Arguments.createMap();
263
- params.putInt("clientId", clientPtr);
264
- params.putInt("state", resultState);
265
- if (errorMessage != null) {
266
- params.putString("error", errorMessage);
267
- }
268
- sendEvent("onConnectionStateChanged", params);
308
+ Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + connectType + ")");
309
+ connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, connectType);
310
+
311
+ Log.d(TAG, "JNIApi.connect called - waiting for state callback");
269
312
 
270
- promise.resolve(resultState);
313
+ // The actual state will come via the ClientStateListener callback
314
+ // For now, return immediately - the JS side will get updates via events
315
+ promise.resolve(1); // CONNECTING
271
316
  } catch (Exception e) {
272
317
  Log.e(TAG, "clientConnect failed", e);
273
318
 
274
- // Emit connection failed state
275
319
  WritableMap params = Arguments.createMap();
276
320
  params.putInt("clientId", clientPtr);
277
321
  params.putInt("state", 4); // CONNECT_FAILED
@@ -285,6 +329,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
285
329
 
286
330
  /**
287
331
  * Login to camera
332
+ * JNIApi.login(long clientPtr, String username, String password)
288
333
  */
289
334
  @ReactMethod
290
335
  public void clientLogin(int clientPtr, String username, String password, Promise promise) {
@@ -298,22 +343,20 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
298
343
  return;
299
344
  }
300
345
 
301
- if (!clientInfo.isConnected) {
302
- promise.reject("LOGIN_ERROR", "Not connected");
346
+ if (jniApiClass == null) {
347
+ promise.reject("LOGIN_ERROR", "JNIApi not available");
303
348
  return;
304
349
  }
305
350
 
306
- // Build login CGI command
307
- String loginCgi = String.format(
308
- "login.cgi?user=%s&pwd=%s",
309
- username, password
310
- );
351
+ // Call JNIApi.login(sdkClientPtr, username, password)
352
+ Method loginMethod = jniApiClass.getMethod("login",
353
+ long.class, String.class, String.class);
311
354
 
312
- Log.d(TAG, "Sending login command: " + loginCgi);
355
+ Log.d(TAG, "Calling JNIApi.login(" + clientInfo.sdkClientPtr + ", " + username + ", ***)");
356
+ loginMethod.invoke(null, clientInfo.sdkClientPtr, username, password);
313
357
 
314
- // For now, simulate login success
315
- // Real implementation would send CGI via P2P channel
316
358
  clientInfo.isLoggedIn = true;
359
+ Log.d(TAG, "JNIApi.login called successfully");
317
360
 
318
361
  promise.resolve(true);
319
362
  } catch (Exception e) {
@@ -325,6 +368,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
325
368
 
326
369
  /**
327
370
  * Send CGI command to camera
371
+ * JNIApi.writeCgi(long clientPtr, String cgi, int timeout)
328
372
  */
329
373
  @ReactMethod
330
374
  public void clientWriteCgi(int clientPtr, String cgi, int timeout, Promise promise) {
@@ -338,23 +382,19 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
338
382
  return;
339
383
  }
340
384
 
341
- if (!clientInfo.isConnected) {
342
- promise.reject("CGI_ERROR", "Not connected");
385
+ if (jniApiClass == null) {
386
+ promise.reject("CGI_ERROR", "JNIApi not available");
343
387
  return;
344
388
  }
345
389
 
346
- // Real implementation would use PPCS_Write to send CGI
347
- Log.d(TAG, "Would send CGI: " + cgi + " with session: " + clientInfo.sessionHandle);
390
+ // Call JNIApi.writeCgi(sdkClientPtr, cgi, timeout)
391
+ Method writeCgiMethod = jniApiClass.getMethod("writeCgi",
392
+ long.class, String.class, int.class);
348
393
 
349
- Thread.sleep(500);
350
-
351
- // Emit command result
352
- WritableMap params = Arguments.createMap();
353
- params.putInt("clientId", clientPtr);
354
- params.putInt("command", cgi.hashCode());
355
- params.putString("data", "OK");
356
- sendEvent("onCommandReceived", params);
394
+ Log.d(TAG, "Calling JNIApi.writeCgi(" + clientInfo.sdkClientPtr + ", " + cgi + ", " + timeout + ")");
395
+ writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, timeout);
357
396
 
397
+ Log.d(TAG, "JNIApi.writeCgi called successfully");
358
398
  promise.resolve(true);
359
399
  } catch (Exception e) {
360
400
  Log.e(TAG, "clientWriteCgi failed", e);
@@ -368,24 +408,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
368
408
  */
369
409
  @ReactMethod
370
410
  public void scanWifi(int clientPtr, Promise promise) {
371
- executor.execute(() -> {
372
- try {
373
- Log.d(TAG, "scanWifi called");
374
-
375
- String scanCgi = "wifi_scan.cgi?user=admin&pwd=888888";
376
-
377
- Thread.sleep(1000);
378
-
379
- WritableMap result = Arguments.createMap();
380
- result.putBoolean("success", true);
381
- result.putString("networks", "[]");
382
-
383
- promise.resolve(result);
384
- } catch (Exception e) {
385
- Log.e(TAG, "scanWifi failed", e);
386
- promise.reject("WIFI_ERROR", e.getMessage());
387
- }
388
- });
411
+ // Use writeCgi to send wifi_scan command
412
+ clientWriteCgi(clientPtr, "wifi_scan.cgi?user=admin&pwd=888888", 10, promise);
389
413
  }
390
414
 
391
415
  /**
@@ -393,58 +417,36 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
393
417
  */
394
418
  @ReactMethod
395
419
  public void configureWifi(int clientPtr, String ssid, String password, int authType, Promise promise) {
396
- executor.execute(() -> {
397
- try {
398
- Log.d(TAG, "configureWifi called for SSID: " + ssid);
399
-
400
- String wifiCgi = String.format(
401
- "set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
402
- ssid, password, authType
403
- );
404
-
405
- Log.d(TAG, "Would send WiFi config: " + wifiCgi);
406
-
407
- Thread.sleep(500);
408
-
409
- promise.resolve(true);
410
- } catch (Exception e) {
411
- Log.e(TAG, "configureWifi failed", e);
412
- promise.reject("WIFI_ERROR", e.getMessage());
413
- }
414
- });
420
+ String wifiCgi = String.format(
421
+ "set_wifi.cgi?ssid=%s&key=%s&authtype=%d&enc=0&mode=0&wifienable=1",
422
+ ssid, password, authType
423
+ );
424
+ clientWriteCgi(clientPtr, wifiCgi, 10, promise);
415
425
  }
416
426
 
417
427
  /**
418
428
  * Disconnect from camera
429
+ * JNIApi.disconnect(long clientPtr)
419
430
  */
420
431
  @ReactMethod
421
432
  public void clientDisconnect(int clientPtr, Promise promise) {
422
433
  executor.execute(() -> {
423
434
  try {
424
- Log.d(TAG, "clientDisconnect called");
435
+ Log.d(TAG, "clientDisconnect called for: " + clientPtr);
425
436
 
426
437
  ClientInfo clientInfo = clients.get(clientPtr);
427
- if (clientInfo != null) {
428
- // Try real disconnect
429
- if (jniApiClass != null && clientInfo.sessionHandle >= 0) {
430
- try {
431
- Method closeMethod = jniApiClass.getMethod("PPCS_Close", int.class);
432
- closeMethod.invoke(null, clientInfo.sessionHandle);
433
- Log.d(TAG, "PPCS_Close called for session: " + clientInfo.sessionHandle);
434
- } catch (Exception e) {
435
- Log.w(TAG, "PPCS_Close failed: " + e.getMessage());
436
- }
437
- }
438
+ if (clientInfo != null && jniApiClass != null) {
439
+ Method disconnectMethod = jniApiClass.getMethod("disconnect", long.class);
440
+ disconnectMethod.invoke(null, clientInfo.sdkClientPtr);
438
441
 
439
442
  clientInfo.isConnected = false;
440
443
  clientInfo.isLoggedIn = false;
441
- clientInfo.sessionHandle = -1;
444
+ Log.d(TAG, "JNIApi.disconnect called successfully");
442
445
  }
443
446
 
444
- // Emit disconnect state
445
447
  WritableMap params = Arguments.createMap();
446
448
  params.putInt("clientId", clientPtr);
447
- params.putInt("state", 5); // DISCONNECT
449
+ params.putInt("state", 5); // DISCONNECTED
448
450
  sendEvent("onConnectionStateChanged", params);
449
451
 
450
452
  promise.resolve(true);
@@ -457,12 +459,21 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
457
459
 
458
460
  /**
459
461
  * Destroy client and cleanup resources
462
+ * JNIApi.destroy(long clientPtr)
460
463
  */
461
464
  @ReactMethod
462
465
  public void clientDestroy(int clientPtr, Promise promise) {
463
466
  executor.execute(() -> {
464
467
  try {
465
- Log.d(TAG, "clientDestroy called");
468
+ Log.d(TAG, "clientDestroy called for: " + clientPtr);
469
+
470
+ ClientInfo clientInfo = clients.get(clientPtr);
471
+ if (clientInfo != null && jniApiClass != null) {
472
+ Method destroyMethod = jniApiClass.getMethod("destroy", long.class);
473
+ destroyMethod.invoke(null, clientInfo.sdkClientPtr);
474
+ Log.d(TAG, "JNIApi.destroy called successfully");
475
+ }
476
+
466
477
  clients.remove(clientPtr);
467
478
  promise.resolve(true);
468
479
  } catch (Exception e) {
@@ -477,15 +488,9 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
477
488
  */
478
489
  @ReactMethod
479
490
  public void startVideoStream(int clientPtr, int streamType, Promise promise) {
480
- executor.execute(() -> {
481
- try {
482
- Log.d(TAG, "startVideoStream called");
483
- promise.resolve(true);
484
- } catch (Exception e) {
485
- Log.e(TAG, "startVideoStream failed", e);
486
- promise.reject("VIDEO_ERROR", e.getMessage());
487
- }
488
- });
491
+ // TODO: Implement video streaming
492
+ Log.d(TAG, "startVideoStream called - not yet implemented");
493
+ promise.resolve(true);
489
494
  }
490
495
 
491
496
  /**
@@ -493,27 +498,35 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
493
498
  */
494
499
  @ReactMethod
495
500
  public void stopVideoStream(int clientPtr, Promise promise) {
496
- try {
497
- Log.d(TAG, "stopVideoStream called");
498
- promise.resolve(true);
499
- } catch (Exception e) {
500
- Log.e(TAG, "stopVideoStream failed", e);
501
- promise.reject("VIDEO_ERROR", e.getMessage());
502
- }
501
+ Log.d(TAG, "stopVideoStream called");
502
+ promise.resolve(true);
503
503
  }
504
504
 
505
505
  /**
506
506
  * Check connection mode
507
+ * JNIApi.checkMode(long clientPtr)
507
508
  */
508
509
  @ReactMethod
509
510
  public void clientCheckMode(int clientPtr, Promise promise) {
510
511
  try {
511
512
  ClientInfo clientInfo = clients.get(clientPtr);
512
513
 
514
+ int mode = 0;
515
+ if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr > 0) {
516
+ try {
517
+ Method checkModeMethod = jniApiClass.getMethod("checkMode", long.class);
518
+ Object result = checkModeMethod.invoke(null, clientInfo.sdkClientPtr);
519
+ mode = (Integer) result;
520
+ Log.d(TAG, "JNIApi.checkMode result: " + mode);
521
+ } catch (Exception e) {
522
+ Log.e(TAG, "checkMode failed", e);
523
+ }
524
+ }
525
+
513
526
  WritableMap result = Arguments.createMap();
514
527
  result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
515
- result.putInt("mode", 1); // P2P mode
516
- result.putInt("sessionHandle", clientInfo != null ? clientInfo.sessionHandle : -1);
528
+ result.putInt("mode", mode);
529
+ result.putDouble("sessionHandle", clientInfo != null ? clientInfo.sdkClientPtr : -1);
517
530
  promise.resolve(result);
518
531
  } catch (Exception e) {
519
532
  Log.e(TAG, "clientCheckMode failed", e);
@@ -535,7 +548,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
535
548
  @ReactMethod
536
549
  public void getSdkVersion(Promise promise) {
537
550
  WritableMap result = Arguments.createMap();
538
- result.putString("version", "1.0.7");
551
+ result.putString("version", "1.0.9");
539
552
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
540
553
  result.putString("nativeLib", "OKSMARTPPCS");
541
554
  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.7",
3
+ "version": "1.0.9",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",