@bits-innovate/react-native-vstarcam 1.0.34 → 1.0.36
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.
|
@@ -103,6 +103,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
103
103
|
if (did == null || did.length() < 4) {
|
|
104
104
|
return SERVICE_PARAM_MAP.get("DEFAULT");
|
|
105
105
|
}
|
|
106
|
+
|
|
107
|
+
// Special case: If it was converted from an ACAE/ACxx virtual UID,
|
|
108
|
+
// it might work better with the vstarcam2018 parameters even if the real prefix is VSTJ/VSTN.
|
|
109
|
+
// However, we'll try prefix-specific first.
|
|
110
|
+
|
|
106
111
|
String prefix = did.substring(0, 4).toUpperCase();
|
|
107
112
|
String param = SERVICE_PARAM_MAP.get(prefix);
|
|
108
113
|
if (param == null) {
|
|
@@ -168,7 +173,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
168
173
|
|
|
169
174
|
// Client tracking - maps our clientPtr to actual SDK client handle
|
|
170
175
|
// Made static so VStarCamVideoView can access SDK pointers
|
|
171
|
-
private static Map<Integer, ClientInfo> clients = new
|
|
176
|
+
private static Map<Integer, ClientInfo> clients = new java.util.concurrent.ConcurrentHashMap<>();
|
|
172
177
|
private boolean isNativeLibraryLoaded = false;
|
|
173
178
|
private boolean isP2PInitialized = false;
|
|
174
179
|
|
|
@@ -336,20 +341,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
336
341
|
|
|
337
342
|
Log.d(TAG, "ClientCommandListener." + methodName + " called");
|
|
338
343
|
if (methodName.equals("commandListener")) {
|
|
339
|
-
|
|
340
|
-
final long clientPtr = (Long) args[0];
|
|
344
|
+
final long sdkPtr = (Long) args[0];
|
|
341
345
|
final byte[] data = (byte[]) args[1];
|
|
342
346
|
final int length = (Integer) args[2];
|
|
343
|
-
Log.d(TAG, "Command callback:
|
|
344
|
-
|
|
345
|
-
if (reactContext != null) {
|
|
346
|
-
reactContext.runOnUiQueueThread(new Runnable() {
|
|
347
|
-
@Override
|
|
348
|
-
public void run() {
|
|
349
|
-
handleCommandReceive(clientPtr, 0, data);
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
}
|
|
347
|
+
Log.d(TAG, "Command callback: sdkPtr=" + sdkPtr + ", len=" + length);
|
|
348
|
+
handleCommandReceive(sdkPtr, 0, data);
|
|
353
349
|
}
|
|
354
350
|
} catch (Exception e) {
|
|
355
351
|
Log.e(TAG, "Error in commandListener callback", e);
|
|
@@ -378,8 +374,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
378
374
|
|
|
379
375
|
Log.d(TAG, "ClientReleaseListener." + methodName + " called");
|
|
380
376
|
if (methodName.equals("releaseListener")) {
|
|
381
|
-
final long
|
|
382
|
-
Log.d(TAG, "Release callback:
|
|
377
|
+
final long sdkPtr = (Long) args[0];
|
|
378
|
+
Log.d(TAG, "Release callback: sdkPtr=" + sdkPtr);
|
|
379
|
+
|
|
380
|
+
// info.sdkClientPtr = 0
|
|
381
|
+
// NOTE: In 1.0.35 we cleared the pointer here, but it caused "Client not connected"
|
|
382
|
+
// because the SDK seems to call this on various events, not just destruction.
|
|
383
|
+
// We will only clear it on explicit disconnect/destroy.
|
|
383
384
|
}
|
|
384
385
|
} catch (Exception e) {
|
|
385
386
|
Log.e(TAG, "Error in releaseListener callback", e);
|
|
@@ -564,11 +565,12 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
564
565
|
params.putInt("state", 1); // CONNECTING
|
|
565
566
|
sendEvent("onConnectionStateChanged", params);
|
|
566
567
|
|
|
567
|
-
//
|
|
568
|
-
|
|
568
|
+
// CRITICAL: For virtual UIDs (like ACAE...), always use the ORIGINAL device ID
|
|
569
|
+
// to look up service parameters. Even if it's converted to a VSTJ/VSTN real ID,
|
|
570
|
+
// it often must connect via the specific vstarcam2018/2019 servers matched to its prefix.
|
|
569
571
|
String param = (serverParam != null && !serverParam.isEmpty())
|
|
570
572
|
? serverParam
|
|
571
|
-
: getServiceParam(
|
|
573
|
+
: getServiceParam(clientInfo.deviceId);
|
|
572
574
|
|
|
573
575
|
// Default connectType to 126 (from V1 app) if not specified
|
|
574
576
|
// connectType 126 = P2P/Relay combination that works reliably
|
|
@@ -584,6 +586,22 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
584
586
|
try {
|
|
585
587
|
Object result = connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, actualConnectType);
|
|
586
588
|
Log.d(TAG, "JNIApi.connect result: " + result);
|
|
589
|
+
|
|
590
|
+
int res = (Integer) result;
|
|
591
|
+
Log.d(TAG, "JNIApi.connect result: " + res);
|
|
592
|
+
|
|
593
|
+
// CRITICAL: In some P2P SDKs, handles can be negative (like pointers).
|
|
594
|
+
// We also saw '7' as a successful handle.
|
|
595
|
+
// We will only reject if it's a specific known error code (usually -1 or -2, but we'll be permissive).
|
|
596
|
+
if (res == -1) {
|
|
597
|
+
Log.w(TAG, "JNIApi.connect failed with code: " + res);
|
|
598
|
+
promise.reject("CONNECT_FAILED", "SDK connect error code: " + res);
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Code >= 0 or other negative values might be a success (Session ID or State)
|
|
603
|
+
Log.d(TAG, "JNIApi.connect successful or handle returned: " + res);
|
|
604
|
+
clientInfo.isConnected = true; // Optimistically set this if we got a handle
|
|
587
605
|
} catch (java.lang.reflect.InvocationTargetException ite) {
|
|
588
606
|
Log.e(TAG, "JNIApi.connect threw exception: " + ite.getCause(), ite.getCause());
|
|
589
607
|
throw ite;
|
|
@@ -645,8 +663,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
645
663
|
// result is likely boolean based on signature log
|
|
646
664
|
if (result instanceof Boolean) {
|
|
647
665
|
loginResult = (Boolean) result;
|
|
666
|
+
} else if (result instanceof Integer) {
|
|
667
|
+
int res = (Integer) result;
|
|
668
|
+
Log.d(TAG, "JNIApi.login integer result: " + res);
|
|
669
|
+
// If it's a handle or 0 (success), treat as true
|
|
670
|
+
loginResult = (res >= 0 || res < -2); // Permissive: only reject -1, -2 as common errors
|
|
648
671
|
} else if (result != null) {
|
|
649
|
-
loginResult = true; // Non-null result usually means success
|
|
672
|
+
loginResult = true; // Non-null result usually means success
|
|
650
673
|
}
|
|
651
674
|
} catch (java.lang.reflect.InvocationTargetException ite) {
|
|
652
675
|
Throwable cause = ite.getCause();
|
|
@@ -966,6 +989,13 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
966
989
|
Log.d(TAG, "Verifying network: " + cgi);
|
|
967
990
|
Object result = writeCgiMethod.invoke(null, clientInfo.sdkClientPtr, cgi, 5);
|
|
968
991
|
|
|
992
|
+
boolean writeSuccess = (result instanceof Boolean) ? (Boolean) result : true;
|
|
993
|
+
if (!writeSuccess) {
|
|
994
|
+
Log.w(TAG, "Network verification failed: writeCgi returned false");
|
|
995
|
+
promise.reject("E_NOT_RESPONSIVE", "Camera not responsive to commands");
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
|
|
969
999
|
// If we reach here, the CGI command was at least sent.
|
|
970
1000
|
// We'll return a basic object representing success for now.
|
|
971
1001
|
WritableMap response = Arguments.createMap();
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -388,11 +388,11 @@ class VStarCamClient {
|
|
|
388
388
|
|
|
389
389
|
// Wait for confirmation
|
|
390
390
|
return new Promise((resolve) => {
|
|
391
|
-
const
|
|
391
|
+
const waitTimeout = setTimeout(() => resolve(false), 10000);
|
|
392
392
|
|
|
393
393
|
const handler: CommandEventListener = (_, cmd, data) => {
|
|
394
394
|
if (cmd === 24593) {
|
|
395
|
-
clearTimeout(
|
|
395
|
+
clearTimeout(waitTimeout);
|
|
396
396
|
this.removeCommandListener(handler);
|
|
397
397
|
const params = this.parseResponse(new TextDecoder().decode(data));
|
|
398
398
|
resolve(params["result"] === "0");
|
|
@@ -407,36 +407,14 @@ class VStarCamClient {
|
|
|
407
407
|
* Get device information
|
|
408
408
|
*/
|
|
409
409
|
async getDeviceInfo(): Promise<DeviceInfo | null> {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
this.removeCommandListener(handler);
|
|
419
|
-
const params = this.parseResponse(new TextDecoder().decode(data));
|
|
420
|
-
|
|
421
|
-
resolve({
|
|
422
|
-
serialNumber: params["id"] || "",
|
|
423
|
-
model: params["model"] || "",
|
|
424
|
-
firmware: params["sys_ver"] || "",
|
|
425
|
-
manufacturer: "VStarCam",
|
|
426
|
-
features: {
|
|
427
|
-
ptz: params["ptz"] === "1",
|
|
428
|
-
audio: params["haveAudio"] === "1",
|
|
429
|
-
twoWayAudio: params["support_talk"] === "1",
|
|
430
|
-
nightVision: params["haveIR"] === "1",
|
|
431
|
-
motionDetection: params["support_alarm"] === "1",
|
|
432
|
-
wifi: params["haveWifi"] === "1",
|
|
433
|
-
},
|
|
434
|
-
responsive: true,
|
|
435
|
-
});
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
this.addCommandListener(handler);
|
|
439
|
-
});
|
|
410
|
+
try {
|
|
411
|
+
// The native module handles credentials and basic command sending.
|
|
412
|
+
// It returns a promise that resolves with the device info and responsive: true.
|
|
413
|
+
return await VStarCamModule.clientGetDeviceInfo(this.clientPtr);
|
|
414
|
+
} catch (e: any) {
|
|
415
|
+
console.error("[VStarCam] getDeviceInfo failed:", e);
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
440
418
|
}
|
|
441
419
|
|
|
442
420
|
/**
|