@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
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
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
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Object
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
152
|
-
|
|
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
|
-
|
|
260
|
+
clientInfo.sdkClientPtr = sdkClientPtr;
|
|
261
|
+
clients.put(ourClientPtr, clientInfo);
|
|
157
262
|
|
|
158
|
-
Log.d(TAG, "Created client
|
|
159
|
-
promise.resolve(
|
|
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
|
-
*
|
|
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
|
-
|
|
184
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
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 (
|
|
302
|
-
promise.reject("LOGIN_ERROR", "
|
|
346
|
+
if (jniApiClass == null) {
|
|
347
|
+
promise.reject("LOGIN_ERROR", "JNIApi not available");
|
|
303
348
|
return;
|
|
304
349
|
}
|
|
305
350
|
|
|
306
|
-
//
|
|
307
|
-
|
|
308
|
-
|
|
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, "
|
|
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 (
|
|
342
|
-
promise.reject("CGI_ERROR", "
|
|
385
|
+
if (jniApiClass == null) {
|
|
386
|
+
promise.reject("CGI_ERROR", "JNIApi not available");
|
|
343
387
|
return;
|
|
344
388
|
}
|
|
345
389
|
|
|
346
|
-
//
|
|
347
|
-
|
|
390
|
+
// Call JNIApi.writeCgi(sdkClientPtr, cgi, timeout)
|
|
391
|
+
Method writeCgiMethod = jniApiClass.getMethod("writeCgi",
|
|
392
|
+
long.class, String.class, int.class);
|
|
348
393
|
|
|
349
|
-
|
|
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
|
-
|
|
372
|
-
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
429
|
-
|
|
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
|
-
|
|
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); //
|
|
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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
-
|
|
497
|
-
|
|
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",
|
|
516
|
-
result.
|
|
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.
|
|
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);
|