@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
|
-
*
|
|
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
|
|
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, "
|
|
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
|
|
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
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
138
|
-
|
|
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
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
192
|
+
// Use provided server param or default
|
|
193
|
+
String param = (serverParam != null && !serverParam.isEmpty())
|
|
194
|
+
? serverParam
|
|
195
|
+
: P2P_SERVER_PARAM;
|
|
151
196
|
|
|
152
|
-
//
|
|
153
|
-
|
|
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
|
|
260
|
+
// Emit result state
|
|
156
261
|
params = Arguments.createMap();
|
|
157
262
|
params.putInt("clientId", clientPtr);
|
|
158
|
-
params.putInt("state",
|
|
263
|
+
params.putInt("state", resultState);
|
|
264
|
+
if (errorMessage != null) {
|
|
265
|
+
params.putString("error", errorMessage);
|
|
266
|
+
}
|
|
159
267
|
sendEvent("onConnectionStateChanged", params);
|
|
160
268
|
|
|
161
|
-
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
//
|
|
242
|
-
|
|
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", "[]");
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
}
|