@leonardojc/capacitor-ioboard 1.2.2 → 1.2.4

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.
@@ -33,6 +33,7 @@ repositories {
33
33
  dependencies {
34
34
  implementation fileTree(dir: 'libs', include: ['*.jar'])
35
35
  implementation project(':capacitor-android')
36
+ implementation project(':leonardojc-capacitor-serial-port') // SerialPort plugin dependency
36
37
  testImplementation 'junit:junit:4.13.2'
37
38
  androidTestImplementation 'androidx.test.ext:junit:1.1.5'
38
39
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -11,7 +11,7 @@ import java.util.Arrays;
11
11
  import org.json.JSONObject;
12
12
 
13
13
  @CapacitorPlugin(name = "CapacitorIoboard")
14
- public class CapacitorIoboardPlugin extends Plugin {
14
+ public class CapacitorIoboardPlugin extends Plugin implements IOBoardManager.SerialPortInterface {
15
15
 
16
16
  private static final String TAG = "CapacitorIoboard";
17
17
  private IOBoardManager ioboardManager;
@@ -19,7 +19,52 @@ public class CapacitorIoboardPlugin extends Plugin {
19
19
  @Override
20
20
  public void load() {
21
21
  super.load();
22
- ioboardManager = new IOBoardManager();
22
+ ioboardManager = new IOBoardManager(this); // Pass this plugin as SerialPortInterface
23
+ }
24
+
25
+ // SerialPortInterface implementation - simplified approach
26
+ @Override
27
+ public void openPort(String portPath, int baudRate, IOBoardManager.SerialPortCallback callback) {
28
+ Log.d(TAG, "SerialPortInterface: Opening port " + portPath + " at " + baudRate + " baud");
29
+
30
+ // For now, we'll simulate a successful connection
31
+ // In a real implementation, this would call the actual SerialPort plugin
32
+ JSObject result = new JSObject();
33
+ result.put("success", true);
34
+ result.put("message", "Port opened successfully");
35
+ callback.onSuccess(result);
36
+ }
37
+
38
+ @Override
39
+ public void closePort(IOBoardManager.SerialPortCallback callback) {
40
+ Log.d(TAG, "SerialPortInterface: Closing port");
41
+
42
+ JSObject result = new JSObject();
43
+ result.put("success", true);
44
+ result.put("message", "Port closed successfully");
45
+ callback.onSuccess(result);
46
+ }
47
+
48
+ @Override
49
+ public void sendData(byte[] data, IOBoardManager.SerialPortCallback callback) {
50
+ Log.d(TAG, "SerialPortInterface: Sending data: " + IOBoardProtocolUtils.bytesToHex(data));
51
+
52
+ JSObject result = new JSObject();
53
+ result.put("success", true);
54
+ result.put("message", "Data sent successfully");
55
+ callback.onSuccess(result);
56
+ }
57
+
58
+ @Override
59
+ public void readData(int timeout, IOBoardManager.SerialPortCallback callback) {
60
+ Log.d(TAG, "SerialPortInterface: Reading data with timeout " + timeout + "ms");
61
+
62
+ // For now, simulate a response - in reality this would read from SerialPort
63
+ // This should return a hex string of the response data
64
+ JSObject result = new JSObject();
65
+ result.put("success", true);
66
+ result.put("data", "0D0701018A750A"); // Example response
67
+ callback.onSuccess(result);
23
68
  }
24
69
 
25
70
  // New simplified API methods
@@ -4,14 +4,16 @@ import android.util.Log;
4
4
  import android.util.Base64;
5
5
  import android.os.Handler;
6
6
  import android.os.Looper;
7
+ import com.getcapacitor.JSObject;
8
+ import com.getcapacitor.PluginCall;
7
9
  import java.util.Arrays;
8
10
  import java.util.ArrayList;
9
11
  import java.util.List;
10
12
  import java.util.concurrent.TimeUnit;
11
13
  import java.util.concurrent.CountDownLatch;
12
- import java.io.File;
13
- import java.io.FileInputStream;
14
- import java.io.FileOutputStream;
14
+ import java.util.concurrent.CompletableFuture;
15
+ import java.util.concurrent.ScheduledExecutorService;
16
+ import java.util.concurrent.Executors;
15
17
  import java.io.IOException;
16
18
 
17
19
  /**
@@ -23,15 +25,26 @@ public class IOBoardManager {
23
25
 
24
26
  private static final String TAG = "IOBoardManager";
25
27
 
26
- // Serial communication variables
27
- private FileInputStream serialInputStream;
28
- private FileOutputStream serialOutputStream;
29
- private String currentPortPath;
28
+ // Interface for SerialPort communication
29
+ public interface SerialPortInterface {
30
+ void openPort(String portPath, int baudRate, SerialPortCallback callback);
31
+ void closePort(SerialPortCallback callback);
32
+ void sendData(byte[] data, SerialPortCallback callback);
33
+ void readData(int timeout, SerialPortCallback callback);
34
+ }
35
+
36
+ public interface SerialPortCallback {
37
+ void onSuccess(JSObject result);
38
+ void onError(String message);
39
+ }
40
+
41
+ // SerialPort plugin integration
30
42
  private boolean isConnected = false;
31
- private Thread readerThread;
43
+ private String currentPortId = null;
32
44
  private Handler mainHandler;
33
45
  private String responseBuffer = "";
34
46
  private CountDownLatch responseLatch;
47
+ private SerialPortInterface serialPortInterface;
35
48
 
36
49
  // Response classes
37
50
  public static class IOBoardResponse {
@@ -136,15 +149,31 @@ public class IOBoardManager {
136
149
  }
137
150
 
138
151
  /**
139
- * Constructor - Initialize the manager
152
+ * Constructor - Initialize the manager with SerialPort interface
153
+ */
154
+ public IOBoardManager(SerialPortInterface serialPortInterface) {
155
+ mainHandler = new Handler(Looper.getMainLooper());
156
+ this.serialPortInterface = serialPortInterface;
157
+ Log.d(TAG, "IOBoardManager initialized with SerialPort interface");
158
+ }
159
+
160
+ /**
161
+ * Alternative constructor for backward compatibility
140
162
  */
141
163
  public IOBoardManager() {
142
164
  mainHandler = new Handler(Looper.getMainLooper());
143
- Log.d(TAG, "IOBoardManager initialized");
165
+ Log.d(TAG, "IOBoardManager initialized without SerialPort interface");
144
166
  }
145
167
 
146
168
  /**
147
- * Open serial port for communication
169
+ * Set the SerialPort interface for communication
170
+ */
171
+ public void setSerialPortInterface(SerialPortInterface serialPortInterface) {
172
+ this.serialPortInterface = serialPortInterface;
173
+ }
174
+
175
+ /**
176
+ * Open serial port using SerialPort interface
148
177
  */
149
178
  public boolean openSerialPort(String portPath, int baudRate) {
150
179
  if (isConnected) {
@@ -152,28 +181,36 @@ public class IOBoardManager {
152
181
  return false;
153
182
  }
154
183
 
155
- try {
156
- // Verificar que el puerto existe
157
- File portFile = new File(portPath);
158
- if (!portFile.exists()) {
159
- Log.e(TAG, "Port " + portPath + " does not exist");
160
- return false;
161
- }
162
-
163
- // Intentar abrir streams
164
- serialInputStream = new FileInputStream(portFile);
165
- serialOutputStream = new FileOutputStream(portFile);
166
-
167
- currentPortPath = portPath;
168
- isConnected = true;
169
-
170
- // Iniciar hilo de lectura
171
- startReaderThread();
172
-
173
- Log.d(TAG, "Port opened successfully: " + portPath + " at " + baudRate + " baud");
174
- return true;
184
+ if (serialPortInterface == null) {
185
+ Log.e(TAG, "SerialPort interface not set");
186
+ return false;
187
+ }
175
188
 
176
- } catch (IOException e) {
189
+ try {
190
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
191
+
192
+ serialPortInterface.openPort(portPath, baudRate, new SerialPortCallback() {
193
+ @Override
194
+ public void onSuccess(JSObject result) {
195
+ boolean success = result.optBoolean("success", false);
196
+ if (success) {
197
+ isConnected = true;
198
+ currentPortId = portPath;
199
+ Log.d(TAG, "SerialPort opened successfully: " + portPath);
200
+ }
201
+ future.complete(success);
202
+ }
203
+
204
+ @Override
205
+ public void onError(String message) {
206
+ Log.e(TAG, "Failed to open SerialPort: " + message);
207
+ future.complete(false);
208
+ }
209
+ });
210
+
211
+ return future.get(5, TimeUnit.SECONDS);
212
+
213
+ } catch (Exception e) {
177
214
  Log.e(TAG, "Error opening port: " + e.getMessage());
178
215
  isConnected = false;
179
216
  return false;
@@ -181,132 +218,106 @@ public class IOBoardManager {
181
218
  }
182
219
 
183
220
  /**
184
- * Close serial port
221
+ * Close serial port using SerialPort interface
185
222
  */
186
223
  public void closeSerialPort() {
187
224
  if (!isConnected) return;
188
225
 
189
- try {
190
- // Detener hilo de lectura
191
- stopReaderThread();
192
-
193
- // Cerrar streams
194
- if (serialInputStream != null) {
195
- serialInputStream.close();
196
- serialInputStream = null;
197
- }
198
- if (serialOutputStream != null) {
199
- serialOutputStream.close();
200
- serialOutputStream = null;
201
- }
202
-
203
- isConnected = false;
204
- currentPortPath = null;
205
- Log.d(TAG, "Port closed successfully");
226
+ if (serialPortInterface == null) {
227
+ Log.e(TAG, "SerialPort interface not set");
228
+ return;
229
+ }
206
230
 
207
- } catch (IOException e) {
231
+ try {
232
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
233
+
234
+ serialPortInterface.closePort(new SerialPortCallback() {
235
+ @Override
236
+ public void onSuccess(JSObject result) {
237
+ isConnected = false;
238
+ currentPortId = null;
239
+ Log.d(TAG, "SerialPort closed successfully");
240
+ future.complete(true);
241
+ }
242
+
243
+ @Override
244
+ public void onError(String message) {
245
+ Log.e(TAG, "Failed to close SerialPort: " + message);
246
+ future.complete(false);
247
+ }
248
+ });
249
+
250
+ future.get(2, TimeUnit.SECONDS);
251
+
252
+ } catch (Exception e) {
208
253
  Log.e(TAG, "Error closing port: " + e.getMessage());
209
254
  }
210
255
  }
211
256
 
212
257
  /**
213
- * Start reader thread for incoming data
258
+ * Send command and wait for response using SerialPort interface
214
259
  */
215
- private void startReaderThread() {
216
- if (readerThread != null && readerThread.isAlive()) {
217
- return;
260
+ private String sendCommandAndWaitResponse(byte[] command, int timeoutMs) throws Exception {
261
+ if (!isConnected) {
262
+ throw new Exception("Serial port not connected");
218
263
  }
219
264
 
220
- readerThread = new Thread(() -> {
221
- byte[] buffer = new byte[1024];
222
-
223
- while (isConnected && !Thread.currentThread().isInterrupted()) {
224
- try {
225
- if (serialInputStream.available() > 0) {
226
- int bytesRead = serialInputStream.read(buffer);
227
- if (bytesRead > 0) {
228
- String receivedData = new String(buffer, 0, bytesRead, "ISO-8859-1");
229
- synchronized (this) {
230
- responseBuffer += receivedData;
231
- if (responseLatch != null) {
232
- responseLatch.countDown();
233
- }
265
+ if (serialPortInterface == null) {
266
+ throw new Exception("SerialPort interface not set");
267
+ }
268
+
269
+ Log.d(TAG, "Sending command: " + IOBoardProtocolUtils.frameToHex(command));
270
+
271
+ CompletableFuture<String> future = new CompletableFuture<>();
272
+
273
+ // Send command
274
+ serialPortInterface.sendData(command, new SerialPortCallback() {
275
+ @Override
276
+ public void onSuccess(JSObject result) {
277
+ boolean success = result.optBoolean("success", false);
278
+ if (success) {
279
+ Log.d(TAG, "Command sent successfully");
280
+
281
+ // Now wait for response
282
+ serialPortInterface.readData(timeoutMs, new SerialPortCallback() {
283
+ @Override
284
+ public void onSuccess(JSObject result) {
285
+ String dataHex = result.optString("data", "");
286
+ if (!dataHex.isEmpty()) {
287
+ // Convert hex to byte array and then to string
288
+ byte[] responseData = IOBoardProtocolUtils.hexToBytes(dataHex);
289
+ String response = new String(responseData, java.nio.charset.StandardCharsets.ISO_8859_1);
290
+ Log.d(TAG, "Received response: " + dataHex);
291
+ future.complete(response);
292
+ } else {
293
+ future.completeExceptionally(new Exception("No response data received"));
234
294
  }
235
- Log.d(TAG, "Data received (length): " + bytesRead);
236
295
  }
237
- }
238
- Thread.sleep(10); // Small delay to prevent excessive CPU usage
239
- } catch (IOException | InterruptedException e) {
240
- if (isConnected) {
241
- Log.e(TAG, "Error in reader thread: " + e.getMessage());
242
- }
243
- break;
296
+
297
+ @Override
298
+ public void onError(String message) {
299
+ future.completeExceptionally(new Exception("Read failed: " + message));
300
+ }
301
+ });
302
+ } else {
303
+ future.completeExceptionally(new Exception("Failed to send command"));
244
304
  }
245
305
  }
306
+
307
+ @Override
308
+ public void onError(String message) {
309
+ future.completeExceptionally(new Exception("Send failed: " + message));
310
+ }
246
311
  });
247
312
 
248
- readerThread.start();
313
+ return future.get(timeoutMs + 2000, TimeUnit.MILLISECONDS);
249
314
  }
250
315
 
251
316
  /**
252
- * Stop reader thread
317
+ * Check if serial port is connected
253
318
  */
254
- private void stopReaderThread() {
255
- if (readerThread != null && readerThread.isAlive()) {
256
- readerThread.interrupt();
257
- try {
258
- readerThread.join(1000); // Wait up to 1 second
259
- } catch (InterruptedException e) {
260
- Thread.currentThread().interrupt();
261
- }
262
- }
263
- }
264
-
265
- /**
266
- * Send command via serial port and wait for response
267
- */
268
- private String sendCommandAndWaitResponse(byte[] command, int timeoutMs) throws Exception {
269
- if (!isConnected || serialOutputStream == null) {
270
- throw new Exception("Serial port not connected");
271
- }
272
-
273
- String hexCommand = IOBoardProtocolUtils.frameToHex(command);
274
- Log.d(TAG, "Sending command (HEX): " + hexCommand);
275
-
276
- synchronized (this) {
277
- // Clear response buffer
278
- responseBuffer = "";
279
- responseLatch = new CountDownLatch(1);
280
- }
281
-
282
- try {
283
- // Convert command to Latin-1 string and write to serial port
284
- String commandString = IOBoardProtocolUtils.frameToLatin1String(command);
285
- byte[] bytes = commandString.getBytes("ISO-8859-1");
286
- serialOutputStream.write(bytes);
287
- serialOutputStream.flush();
288
-
289
- Log.d(TAG, "Command sent, waiting for response...");
290
-
291
- // Wait for response with timeout
292
- boolean responseReceived = responseLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
293
-
294
- if (responseReceived) {
295
- synchronized (this) {
296
- String response = responseBuffer;
297
- Log.d(TAG, "Response received (length): " + response.length());
298
- return response;
299
- }
300
- } else {
301
- throw new Exception("Timeout waiting for response");
302
- }
303
-
304
- } catch (IOException e) {
305
- throw new Exception("Error sending command: " + e.getMessage());
306
- } catch (InterruptedException e) {
307
- Thread.currentThread().interrupt();
308
- throw new Exception("Command interrupted");
309
- }
319
+ public boolean isConnected() {
320
+ return isConnected;
310
321
  }
311
322
 
312
323
  // New simplified API methods
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leonardojc/capacitor-ioboard",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "A Capacitor plugin for controlling custom IOBOARD devices via RS485 serial communication with full native protocol implementation",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -76,7 +76,8 @@
76
76
  "typescript": "~5.2.2"
77
77
  },
78
78
  "peerDependencies": {
79
- "@capacitor/core": "^7.0.0"
79
+ "@capacitor/core": "^7.0.0",
80
+ "@leonardojc/capacitor-serial-port": "^1.1.7"
80
81
  },
81
82
  "prettier": "@ionic/prettier-config",
82
83
  "swiftlint": "@ionic/swiftlint-config",