@bits-innovate/react-native-vstarcam 1.0.8 → 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,88 +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
- 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
- }
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);
259
307
 
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);
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");
268
312
 
269
- 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
270
316
  } catch (Exception e) {
271
317
  Log.e(TAG, "clientConnect failed", e);
272
318
 
273
- // Emit connection failed state
274
319
  WritableMap params = Arguments.createMap();
275
320
  params.putInt("clientId", clientPtr);
276
321
  params.putInt("state", 4); // CONNECT_FAILED
@@ -284,6 +329,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
284
329
 
285
330
  /**
286
331
  * Login to camera
332
+ * JNIApi.login(long clientPtr, String username, String password)
287
333
  */
288
334
  @ReactMethod
289
335
  public void clientLogin(int clientPtr, String username, String password, Promise promise) {
@@ -297,22 +343,20 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
297
343
  return;
298
344
  }
299
345
 
300
- if (!clientInfo.isConnected) {
301
- promise.reject("LOGIN_ERROR", "Not connected");
346
+ if (jniApiClass == null) {
347
+ promise.reject("LOGIN_ERROR", "JNIApi not available");
302
348
  return;
303
349
  }
304
350
 
305
- // Build login CGI command
306
- String loginCgi = String.format(
307
- "login.cgi?user=%s&pwd=%s",
308
- username, password
309
- );
351
+ // Call JNIApi.login(sdkClientPtr, username, password)
352
+ Method loginMethod = jniApiClass.getMethod("login",
353
+ long.class, String.class, String.class);
310
354
 
311
- 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);
312
357
 
313
- // For now, simulate login success
314
- // Real implementation would send CGI via P2P channel
315
358
  clientInfo.isLoggedIn = true;
359
+ Log.d(TAG, "JNIApi.login called successfully");
316
360
 
317
361
  promise.resolve(true);
318
362
  } catch (Exception e) {
@@ -324,6 +368,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
324
368
 
325
369
  /**
326
370
  * Send CGI command to camera
371
+ * JNIApi.writeCgi(long clientPtr, String cgi, int timeout)
327
372
  */
328
373
  @ReactMethod
329
374
  public void clientWriteCgi(int clientPtr, String cgi, int timeout, Promise promise) {
@@ -337,23 +382,19 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
337
382
  return;
338
383
  }
339
384
 
340
- if (!clientInfo.isConnected) {
341
- promise.reject("CGI_ERROR", "Not connected");
385
+ if (jniApiClass == null) {
386
+ promise.reject("CGI_ERROR", "JNIApi not available");
342
387
  return;
343
388
  }
344
389
 
345
- // Real implementation would use PPCS_Write to send CGI
346
- 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);
347
393
 
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);
394
+ Log.d(TAG, "Calling JNIApi.writeCgi(" + clientInfo.sdkClientPtr + ", " + cgi + ", " + timeout + ")");
395
+ writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, timeout);
356
396
 
397
+ Log.d(TAG, "JNIApi.writeCgi called successfully");
357
398
  promise.resolve(true);
358
399
  } catch (Exception e) {
359
400
  Log.e(TAG, "clientWriteCgi failed", e);
@@ -367,24 +408,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
367
408
  */
368
409
  @ReactMethod
369
410
  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
- });
411
+ // Use writeCgi to send wifi_scan command
412
+ clientWriteCgi(clientPtr, "wifi_scan.cgi?user=admin&pwd=888888", 10, promise);
388
413
  }
389
414
 
390
415
  /**
@@ -392,58 +417,36 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
392
417
  */
393
418
  @ReactMethod
394
419
  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
- });
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);
414
425
  }
415
426
 
416
427
  /**
417
428
  * Disconnect from camera
429
+ * JNIApi.disconnect(long clientPtr)
418
430
  */
419
431
  @ReactMethod
420
432
  public void clientDisconnect(int clientPtr, Promise promise) {
421
433
  executor.execute(() -> {
422
434
  try {
423
- Log.d(TAG, "clientDisconnect called");
435
+ Log.d(TAG, "clientDisconnect called for: " + clientPtr);
424
436
 
425
437
  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
- }
438
+ if (clientInfo != null && jniApiClass != null) {
439
+ Method disconnectMethod = jniApiClass.getMethod("disconnect", long.class);
440
+ disconnectMethod.invoke(null, clientInfo.sdkClientPtr);
437
441
 
438
442
  clientInfo.isConnected = false;
439
443
  clientInfo.isLoggedIn = false;
440
- clientInfo.sessionHandle = -1;
444
+ Log.d(TAG, "JNIApi.disconnect called successfully");
441
445
  }
442
446
 
443
- // Emit disconnect state
444
447
  WritableMap params = Arguments.createMap();
445
448
  params.putInt("clientId", clientPtr);
446
- params.putInt("state", 5); // DISCONNECT
449
+ params.putInt("state", 5); // DISCONNECTED
447
450
  sendEvent("onConnectionStateChanged", params);
448
451
 
449
452
  promise.resolve(true);
@@ -456,12 +459,21 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
456
459
 
457
460
  /**
458
461
  * Destroy client and cleanup resources
462
+ * JNIApi.destroy(long clientPtr)
459
463
  */
460
464
  @ReactMethod
461
465
  public void clientDestroy(int clientPtr, Promise promise) {
462
466
  executor.execute(() -> {
463
467
  try {
464
- 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
+
465
477
  clients.remove(clientPtr);
466
478
  promise.resolve(true);
467
479
  } catch (Exception e) {
@@ -476,15 +488,9 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
476
488
  */
477
489
  @ReactMethod
478
490
  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
- });
491
+ // TODO: Implement video streaming
492
+ Log.d(TAG, "startVideoStream called - not yet implemented");
493
+ promise.resolve(true);
488
494
  }
489
495
 
490
496
  /**
@@ -492,27 +498,35 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
492
498
  */
493
499
  @ReactMethod
494
500
  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
- }
501
+ Log.d(TAG, "stopVideoStream called");
502
+ promise.resolve(true);
502
503
  }
503
504
 
504
505
  /**
505
506
  * Check connection mode
507
+ * JNIApi.checkMode(long clientPtr)
506
508
  */
507
509
  @ReactMethod
508
510
  public void clientCheckMode(int clientPtr, Promise promise) {
509
511
  try {
510
512
  ClientInfo clientInfo = clients.get(clientPtr);
511
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
+
512
526
  WritableMap result = Arguments.createMap();
513
527
  result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
514
- result.putInt("mode", 1); // P2P mode
515
- result.putInt("sessionHandle", clientInfo != null ? clientInfo.sessionHandle : -1);
528
+ result.putInt("mode", mode);
529
+ result.putDouble("sessionHandle", clientInfo != null ? clientInfo.sdkClientPtr : -1);
516
530
  promise.resolve(result);
517
531
  } catch (Exception e) {
518
532
  Log.e(TAG, "clientCheckMode failed", e);
@@ -534,7 +548,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
534
548
  @ReactMethod
535
549
  public void getSdkVersion(Promise promise) {
536
550
  WritableMap result = Arguments.createMap();
537
- result.putString("version", "1.0.8");
551
+ result.putString("version", "1.0.9");
538
552
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
539
553
  result.putString("nativeLib", "OKSMARTPPCS");
540
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.8",
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",