@leonardojc/capacitor-ioboard 1.1.0

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.
@@ -0,0 +1,657 @@
1
+ package com.leonardojc.capacitor.ioboard;
2
+
3
+ import android.util.Log;
4
+ import android.util.Base64;
5
+ import java.util.Arrays;
6
+ import java.util.concurrent.TimeUnit;
7
+
8
+ /**
9
+ * Manager class for IOBOARD communication protocol
10
+ * This class integrates with the @leonardojc/capacitor-serial-port plugin
11
+ */
12
+ public class IOBoardManager {
13
+
14
+ private static final String TAG = "IOBoardManager";
15
+ private static final int SOI = 0x0D; // Start of frame
16
+ private static final int EOI = 0x0A; // End of frame
17
+
18
+ // Frame types
19
+ private static final int FRAME_TYPE_STATUS_QUERY = 0x00;
20
+ private static final int FRAME_TYPE_SINGLE_PALLET = 0x01;
21
+ private static final int FRAME_TYPE_FULL_PALLET = 0x02;
22
+ private static final int FRAME_TYPE_OTA_REQUEST = 0xF1;
23
+ private static final int FRAME_TYPE_OTA_DATA = 0xF2;
24
+
25
+ private boolean isConnected = false;
26
+
27
+ // Response classes
28
+ public static class IOBoardResponse {
29
+ public boolean success;
30
+ public String message;
31
+
32
+ public IOBoardResponse(boolean success, String message) {
33
+ this.success = success;
34
+ this.message = message;
35
+ }
36
+ }
37
+
38
+ public static class StatusData {
39
+ public int doorLockStatus;
40
+ public SoftwareVersion softwareVersion;
41
+
42
+ public StatusData(int doorLockStatus, SoftwareVersion softwareVersion) {
43
+ this.doorLockStatus = doorLockStatus;
44
+ this.softwareVersion = softwareVersion;
45
+ }
46
+ }
47
+
48
+ public static class SoftwareVersion {
49
+ public int major;
50
+ public int minor;
51
+ public int patch;
52
+
53
+ public SoftwareVersion(int major, int minor, int patch) {
54
+ this.major = major;
55
+ this.minor = minor;
56
+ this.patch = patch;
57
+ }
58
+ }
59
+
60
+ public static class StatusResponse extends IOBoardResponse {
61
+ public StatusData data;
62
+
63
+ public StatusResponse(boolean success, String message, StatusData data) {
64
+ super(success, message);
65
+ this.data = data;
66
+ }
67
+ }
68
+
69
+ public static class LEDControl {
70
+ public int red;
71
+ public int green;
72
+ public int blue;
73
+ public int intensity;
74
+ public int blinkTimes;
75
+ public int blinkSpeed;
76
+
77
+ public LEDControl(int red, int green, int blue, int intensity, int blinkTimes, int blinkSpeed) {
78
+ this.red = Math.max(0, Math.min(255, red));
79
+ this.green = Math.max(0, Math.min(255, green));
80
+ this.blue = Math.max(0, Math.min(255, blue));
81
+ this.intensity = Math.max(0, Math.min(255, intensity));
82
+ this.blinkTimes = Math.max(0, Math.min(255, blinkTimes));
83
+ this.blinkSpeed = Math.max(0, Math.min(30, blinkSpeed));
84
+ }
85
+ }
86
+
87
+ public static class SerialConfig {
88
+ public String portPath;
89
+ public int baudRate;
90
+ public int dataBits;
91
+ public int stopBits;
92
+ public String parity;
93
+ public String flowControl;
94
+ public int timeout;
95
+
96
+ public SerialConfig(String portPath, int baudRate, int dataBits, int stopBits, String parity, String flowControl, int timeout) {
97
+ this.portPath = portPath;
98
+ this.baudRate = baudRate;
99
+ this.dataBits = dataBits;
100
+ this.stopBits = stopBits;
101
+ this.parity = parity;
102
+ this.flowControl = flowControl;
103
+ this.timeout = timeout;
104
+ }
105
+ }
106
+
107
+ // New classes for simplified API
108
+ public static class DeviceInfo {
109
+ public int address;
110
+ public boolean responding;
111
+ public StatusData status;
112
+
113
+ public DeviceInfo(int address, boolean responding, StatusData status) {
114
+ this.address = address;
115
+ this.responding = responding;
116
+ this.status = status;
117
+ }
118
+ }
119
+
120
+ public static class ScanResponse extends IOBoardResponse {
121
+ public DeviceInfo[] devices;
122
+
123
+ public ScanResponse(boolean success, String message, DeviceInfo[] devices) {
124
+ super(success, message);
125
+ this.devices = devices;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Calculate CRC-16 CCITT checksum
131
+ */
132
+ private int calculateCRC16(int[] data) {
133
+ int crc = 0xFFFF;
134
+
135
+ for (int dataByte : data) {
136
+ crc ^= (dataByte << 8);
137
+
138
+ for (int bit = 0; bit < 8; bit++) {
139
+ if ((crc & 0x8000) != 0) {
140
+ crc = (crc << 1) ^ 0x1021;
141
+ } else {
142
+ crc = crc << 1;
143
+ }
144
+ crc &= 0xFFFF;
145
+ }
146
+ }
147
+
148
+ return crc;
149
+ }
150
+
151
+ /**
152
+ * Build a command frame for IOBOARD
153
+ */
154
+ private int[] buildFrame(int address, int frameType, int[] data) {
155
+ // Calculate frame size: SOI + Address + FrameType + Data + CRC(2) + EOI
156
+ int frameSize = 1 + 1 + 1 + data.length + 2 + 1;
157
+ int[] frame = new int[frameSize];
158
+ int index = 0;
159
+
160
+ // SOI
161
+ frame[index++] = SOI;
162
+
163
+ // Address
164
+ frame[index++] = address;
165
+
166
+ // Frame Type
167
+ frame[index++] = frameType;
168
+
169
+ // Data
170
+ for (int dataByte : data) {
171
+ frame[index++] = dataByte;
172
+ }
173
+
174
+ // Calculate CRC for address + frameType + data
175
+ int[] crcData = new int[1 + 1 + data.length];
176
+ crcData[0] = address;
177
+ crcData[1] = frameType;
178
+ System.arraycopy(data, 0, crcData, 2, data.length);
179
+
180
+ int crc = calculateCRC16(crcData);
181
+
182
+ // CRC (high byte first)
183
+ frame[index++] = (crc >> 8) & 0xFF;
184
+ frame[index++] = crc & 0xFF;
185
+
186
+ // EOI
187
+ frame[index] = EOI;
188
+
189
+ return frame;
190
+ }
191
+
192
+ /**
193
+ * Convert frame to byte array for serial transmission
194
+ */
195
+ private byte[] frameToBytes(int[] frame) {
196
+ byte[] bytes = new byte[frame.length];
197
+ for (int i = 0; i < frame.length; i++) {
198
+ bytes[i] = (byte) (frame[i] & 0xFF);
199
+ }
200
+ return bytes;
201
+ }
202
+
203
+ /**
204
+ * Convert frame to hex string for debugging
205
+ */
206
+ private String frameToHex(int[] frame) {
207
+ StringBuilder sb = new StringBuilder();
208
+ for (int i = 0; i < frame.length; i++) {
209
+ if (i > 0) sb.append(" ");
210
+ sb.append(String.format("%02X", frame[i]));
211
+ }
212
+ return sb.toString();
213
+ }
214
+
215
+ // New simplified API methods
216
+
217
+ /**
218
+ * Connect to serial port
219
+ */
220
+ public IOBoardResponse connect(SerialConfig config) {
221
+ Log.d(TAG, "Connecting to serial port: " + config.portPath + " at " + config.baudRate + " baud");
222
+
223
+ try {
224
+ // TODO: Initialize connection with serial port plugin
225
+ // For now, just set the connected flag
226
+ isConnected = true;
227
+
228
+ return new IOBoardResponse(true, "Connected to " + config.portPath + " successfully");
229
+
230
+ } catch (Exception e) {
231
+ Log.e(TAG, "Error connecting", e);
232
+ return new IOBoardResponse(false, "Error connecting: " + e.getMessage());
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Disconnect from serial port
238
+ */
239
+ public IOBoardResponse disconnect() {
240
+ Log.d(TAG, "Disconnecting from serial port");
241
+
242
+ try {
243
+ // TODO: Close connection with serial port plugin
244
+ isConnected = false;
245
+
246
+ return new IOBoardResponse(true, "Disconnected successfully");
247
+
248
+ } catch (Exception e) {
249
+ Log.e(TAG, "Error disconnecting", e);
250
+ return new IOBoardResponse(false, "Error disconnecting: " + e.getMessage());
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Get status of IOBOARD device
256
+ */
257
+ public StatusResponse getStatus(int address, int timeout) {
258
+ Log.d(TAG, "Getting status for address: " + address + " with timeout: " + timeout + "ms");
259
+
260
+ if (!isConnected) {
261
+ return new StatusResponse(false, "No serial connection established", null);
262
+ }
263
+
264
+ try {
265
+ // Build status query frame
266
+ int[] frame = buildFrame(address, FRAME_TYPE_STATUS_QUERY, new int[0]);
267
+
268
+ Log.d(TAG, "Sending status query frame: " + frameToHex(frame));
269
+
270
+ // TODO: Send frame via serial port plugin and receive response
271
+ // For now, return a mock response
272
+ StatusData mockData = new StatusData(0b11010001, new SoftwareVersion(1, 2, 3));
273
+ return new StatusResponse(true, "Status retrieved successfully", mockData);
274
+
275
+ } catch (Exception e) {
276
+ Log.e(TAG, "Error getting status", e);
277
+ return new StatusResponse(false, "Error getting status: " + e.getMessage(), null);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Unlock a specific pallet with LED indication
283
+ */
284
+ public IOBoardResponse unlockPallet(int address, int palletNumber, String ledColor, int timeout) {
285
+ Log.d(TAG, "Unlocking pallet - Address: " + address + ", Pallet: " + palletNumber + ", LED: " + ledColor);
286
+
287
+ if (!isConnected) {
288
+ return new IOBoardResponse(false, "No serial connection established");
289
+ }
290
+
291
+ try {
292
+ // Convert LED color to RGB values
293
+ LEDControl ledControl = getLEDControlFromColor(ledColor);
294
+
295
+ // Build data array for single pallet control
296
+ int[] data = new int[8];
297
+ data[0] = palletNumber;
298
+ data[1] = 1; // doorLock = true (unlock)
299
+ data[2] = ledControl.red;
300
+ data[3] = ledControl.green;
301
+ data[4] = ledControl.blue;
302
+ data[5] = ledControl.intensity;
303
+ data[6] = ledControl.blinkTimes;
304
+ data[7] = ledControl.blinkSpeed;
305
+
306
+ int[] frame = buildFrame(address, FRAME_TYPE_SINGLE_PALLET, data);
307
+
308
+ Log.d(TAG, "Sending unlock pallet frame: " + frameToHex(frame));
309
+
310
+ // TODO: Send frame via serial port plugin and receive response
311
+ return new IOBoardResponse(true, "Pallet " + palletNumber + " unlocked successfully");
312
+
313
+ } catch (Exception e) {
314
+ Log.e(TAG, "Error unlocking pallet", e);
315
+ return new IOBoardResponse(false, "Error unlocking pallet: " + e.getMessage());
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Control multiple pallets using a bitmask
321
+ */
322
+ public IOBoardResponse controlMultiplePallets(int address, int doorLockMask, String ledColor, int timeout) {
323
+ Log.d(TAG, "Controlling multiple pallets - Address: " + address + ", Mask: 0x" + Integer.toHexString(doorLockMask));
324
+
325
+ if (!isConnected) {
326
+ return new IOBoardResponse(false, "No serial connection established");
327
+ }
328
+
329
+ try {
330
+ // Convert LED color to RGB values
331
+ LEDControl ledControl = getLEDControlFromColor(ledColor);
332
+
333
+ // Build data array for full pallet control
334
+ int[] data = new int[2 + (8 * 6)];
335
+ int index = 0;
336
+
337
+ data[index++] = doorLockMask;
338
+ data[index++] = 0; // extendedControl
339
+
340
+ // Add LED controls for 8 pallets
341
+ for (int i = 0; i < 8; i++) {
342
+ // If pallet is affected by mask, use specified LED color, otherwise turn off
343
+ LEDControl led = ((doorLockMask & (1 << i)) != 0) ? ledControl : new LEDControl(0, 0, 0, 0, 0, 0);
344
+ data[index++] = led.red;
345
+ data[index++] = led.green;
346
+ data[index++] = led.blue;
347
+ data[index++] = led.intensity;
348
+ data[index++] = led.blinkTimes;
349
+ data[index++] = led.blinkSpeed;
350
+ }
351
+
352
+ int[] frame = buildFrame(address, FRAME_TYPE_FULL_PALLET, data);
353
+
354
+ Log.d(TAG, "Sending multiple pallets control frame: " + frameToHex(frame));
355
+
356
+ // TODO: Send frame via serial port plugin and receive response
357
+ return new IOBoardResponse(true, "Multiple pallets controlled successfully");
358
+
359
+ } catch (Exception e) {
360
+ Log.e(TAG, "Error controlling multiple pallets", e);
361
+ return new IOBoardResponse(false, "Error controlling multiple pallets: " + e.getMessage());
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Scan for devices in address range
367
+ */
368
+ public ScanResponse scanDevices(int startAddress, int endAddress, int timeout) {
369
+ Log.d(TAG, "Scanning devices from address " + startAddress + " to " + endAddress);
370
+
371
+ if (!isConnected) {
372
+ return new ScanResponse(false, "No serial connection established", null);
373
+ }
374
+
375
+ try {
376
+ int deviceCount = endAddress - startAddress + 1;
377
+ DeviceInfo[] devices = new DeviceInfo[deviceCount];
378
+
379
+ // TODO: Actually scan devices by sending status queries
380
+ // For now, create mock responses
381
+ for (int i = 0; i < deviceCount; i++) {
382
+ int address = startAddress + i;
383
+ boolean responding = (i % 3 == 0); // Mock: every 3rd device responds
384
+ StatusData status = responding ? new StatusData(0x00, new SoftwareVersion(1, 0, 0)) : null;
385
+ devices[i] = new DeviceInfo(address, responding, status);
386
+ }
387
+
388
+ return new ScanResponse(true, "Scanned addresses " + startAddress + "-" + endAddress, devices);
389
+
390
+ } catch (Exception e) {
391
+ Log.e(TAG, "Error scanning devices", e);
392
+ return new ScanResponse(false, "Error scanning devices: " + e.getMessage(), null);
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Send OTA notification (renamed method)
398
+ */
399
+ public IOBoardResponse sendOTANotification(int address, int majorVersion, int minorVersion, int patchVersion, int firmwareSize) {
400
+ return otaNotification(address, majorVersion, minorVersion, patchVersion, firmwareSize);
401
+ }
402
+
403
+ /**
404
+ * Send OTA data (renamed method)
405
+ */
406
+ public IOBoardResponse sendOTAData(int address, int packetNumber, String dataBase64) {
407
+ return otaData(address, packetNumber, dataBase64);
408
+ }
409
+
410
+ /**
411
+ * Helper method to convert color name to LED control
412
+ */
413
+ private LEDControl getLEDControlFromColor(String color) {
414
+ switch (color.toLowerCase()) {
415
+ case "red":
416
+ return new LEDControl(255, 0, 0, 255, 0, 0);
417
+ case "green":
418
+ return new LEDControl(0, 255, 0, 255, 0, 0);
419
+ case "blue":
420
+ return new LEDControl(0, 0, 255, 255, 0, 0);
421
+ case "yellow":
422
+ return new LEDControl(255, 255, 0, 255, 0, 0);
423
+ case "cyan":
424
+ return new LEDControl(0, 255, 255, 255, 0, 0);
425
+ case "magenta":
426
+ return new LEDControl(255, 0, 255, 255, 0, 0);
427
+ case "white":
428
+ return new LEDControl(255, 255, 255, 255, 0, 0);
429
+ case "off":
430
+ return new LEDControl(0, 0, 0, 0, 0, 0);
431
+ default:
432
+ return new LEDControl(0, 255, 0, 255, 0, 0); // Default to green
433
+ }
434
+ }
435
+
436
+ // Legacy methods (keep for backwards compatibility during transition)
437
+
438
+ /**
439
+ * Query status of IOBOARD device
440
+ */
441
+ public StatusResponse queryStatus(int address) {
442
+ Log.d(TAG, "Querying status for address: " + address);
443
+
444
+ if (!isConnected) {
445
+ return new StatusResponse(false, "No serial connection established", null);
446
+ }
447
+
448
+ try {
449
+ // Build status query frame
450
+ int[] frame = buildFrame(address, FRAME_TYPE_STATUS_QUERY, new int[0]);
451
+
452
+ Log.d(TAG, "Sending status query frame: " + frameToHex(frame));
453
+
454
+ // TODO: Send frame via serial port plugin and receive response
455
+ // For now, return a mock response
456
+ StatusData mockData = new StatusData(0x00, new SoftwareVersion(1, 0, 0));
457
+ return new StatusResponse(true, "Status queried successfully", mockData);
458
+
459
+ } catch (Exception e) {
460
+ Log.e(TAG, "Error querying status", e);
461
+ return new StatusResponse(false, "Error querying status: " + e.getMessage(), null);
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Control a single pallet
467
+ */
468
+ public IOBoardResponse controlSinglePallet(int address, int palletNumber, boolean doorLock, LEDControl ledControl) {
469
+ Log.d(TAG, "Controlling single pallet - Address: " + address + ", Pallet: " + palletNumber);
470
+
471
+ if (!isConnected) {
472
+ return new IOBoardResponse(false, "No serial connection established");
473
+ }
474
+
475
+ try {
476
+ // Build data array
477
+ int[] data = new int[8];
478
+ data[0] = palletNumber;
479
+ data[1] = doorLock ? 1 : 0;
480
+ data[2] = ledControl.red;
481
+ data[3] = ledControl.green;
482
+ data[4] = ledControl.blue;
483
+ data[5] = ledControl.intensity;
484
+ data[6] = ledControl.blinkTimes;
485
+ data[7] = ledControl.blinkSpeed;
486
+
487
+ int[] frame = buildFrame(address, FRAME_TYPE_SINGLE_PALLET, data);
488
+
489
+ Log.d(TAG, "Sending single pallet control frame: " + frameToHex(frame));
490
+
491
+ // TODO: Send frame via serial port plugin and receive response
492
+ return new IOBoardResponse(true, "Single pallet controlled successfully");
493
+
494
+ } catch (Exception e) {
495
+ Log.e(TAG, "Error controlling single pallet", e);
496
+ return new IOBoardResponse(false, "Error controlling single pallet: " + e.getMessage());
497
+ }
498
+ }
499
+
500
+ /**
501
+ * Control all pallets
502
+ */
503
+ public IOBoardResponse controlFullPallet(int address, int doorLockControl, int extendedControl, LEDControl[] ledControls) {
504
+ Log.d(TAG, "Controlling full pallet - Address: " + address);
505
+
506
+ if (!isConnected) {
507
+ return new IOBoardResponse(false, "No serial connection established");
508
+ }
509
+
510
+ try {
511
+ // Build data array: doorLockControl + extendedControl + 8 LED controls (6 bytes each)
512
+ int[] data = new int[2 + (8 * 6)];
513
+ int index = 0;
514
+
515
+ data[index++] = doorLockControl;
516
+ data[index++] = extendedControl;
517
+
518
+ // Add LED controls for 8 pallets
519
+ for (int i = 0; i < 8; i++) {
520
+ LEDControl led = (i < ledControls.length) ? ledControls[i] : new LEDControl(0, 0, 0, 0, 0, 0);
521
+ data[index++] = led.red;
522
+ data[index++] = led.green;
523
+ data[index++] = led.blue;
524
+ data[index++] = led.intensity;
525
+ data[index++] = led.blinkTimes;
526
+ data[index++] = led.blinkSpeed;
527
+ }
528
+
529
+ int[] frame = buildFrame(address, FRAME_TYPE_FULL_PALLET, data);
530
+
531
+ Log.d(TAG, "Sending full pallet control frame: " + frameToHex(frame));
532
+
533
+ // TODO: Send frame via serial port plugin and receive response
534
+ return new IOBoardResponse(true, "Full pallet controlled successfully");
535
+
536
+ } catch (Exception e) {
537
+ Log.e(TAG, "Error controlling full pallet", e);
538
+ return new IOBoardResponse(false, "Error controlling full pallet: " + e.getMessage());
539
+ }
540
+ }
541
+
542
+ /**
543
+ * Send OTA notification
544
+ */
545
+ public IOBoardResponse otaNotification(int address, int majorVersion, int minorVersion, int patchVersion, int firmwareSize) {
546
+ Log.d(TAG, "Sending OTA notification - Address: " + address + ", Version: " + majorVersion + "." + minorVersion + "." + patchVersion);
547
+
548
+ if (!isConnected) {
549
+ return new IOBoardResponse(false, "No serial connection established");
550
+ }
551
+
552
+ try {
553
+ // Build OTA notification data: version(3) + firmware size(4)
554
+ int[] data = new int[7];
555
+ data[0] = majorVersion;
556
+ data[1] = minorVersion;
557
+ data[2] = patchVersion;
558
+ data[3] = firmwareSize & 0xFF;
559
+ data[4] = (firmwareSize >> 8) & 0xFF;
560
+ data[5] = (firmwareSize >> 16) & 0xFF;
561
+ data[6] = (firmwareSize >> 24) & 0xFF;
562
+
563
+ int[] frame = buildFrame(address, FRAME_TYPE_OTA_REQUEST, data);
564
+
565
+ Log.d(TAG, "Sending OTA notification frame: " + frameToHex(frame));
566
+
567
+ // TODO: Send frame via serial port plugin and receive response
568
+ return new IOBoardResponse(true, "OTA notification sent successfully");
569
+
570
+ } catch (Exception e) {
571
+ Log.e(TAG, "Error sending OTA notification", e);
572
+ return new IOBoardResponse(false, "Error sending OTA notification: " + e.getMessage());
573
+ }
574
+ }
575
+
576
+ /**
577
+ * Send OTA data packet
578
+ */
579
+ public IOBoardResponse otaData(int address, int packetNumber, String dataBase64) {
580
+ Log.d(TAG, "Sending OTA data - Address: " + address + ", Packet: " + packetNumber);
581
+
582
+ if (!isConnected) {
583
+ return new IOBoardResponse(false, "No serial connection established");
584
+ }
585
+
586
+ try {
587
+ // Decode base64 data
588
+ byte[] firmwareData = Base64.decode(dataBase64, Base64.DEFAULT);
589
+
590
+ // Build OTA data: packet number(4) + data
591
+ int[] data = new int[4 + firmwareData.length];
592
+ data[0] = packetNumber & 0xFF;
593
+ data[1] = (packetNumber >> 8) & 0xFF;
594
+ data[2] = (packetNumber >> 16) & 0xFF;
595
+ data[3] = (packetNumber >> 24) & 0xFF;
596
+
597
+ for (int i = 0; i < firmwareData.length; i++) {
598
+ data[4 + i] = firmwareData[i] & 0xFF;
599
+ }
600
+
601
+ int[] frame = buildFrame(address, FRAME_TYPE_OTA_DATA, data);
602
+
603
+ Log.d(TAG, "Sending OTA data frame: " + frameToHex(frame));
604
+
605
+ // TODO: Send frame via serial port plugin and receive response
606
+ return new IOBoardResponse(true, "OTA data sent successfully");
607
+
608
+ } catch (Exception e) {
609
+ Log.e(TAG, "Error sending OTA data", e);
610
+ return new IOBoardResponse(false, "Error sending OTA data: " + e.getMessage());
611
+ }
612
+ }
613
+
614
+ /**
615
+ * Open serial connection
616
+ */
617
+ public IOBoardResponse openConnection(SerialConfig config) {
618
+ Log.d(TAG, "Opening serial connection - BaudRate: " + config.baudRate);
619
+
620
+ try {
621
+ // TODO: Initialize connection with serial port plugin
622
+ // For now, just set the connected flag
623
+ isConnected = true;
624
+
625
+ return new IOBoardResponse(true, "Serial connection opened successfully");
626
+
627
+ } catch (Exception e) {
628
+ Log.e(TAG, "Error opening connection", e);
629
+ return new IOBoardResponse(false, "Error opening connection: " + e.getMessage());
630
+ }
631
+ }
632
+
633
+ /**
634
+ * Close serial connection
635
+ */
636
+ public IOBoardResponse closeConnection() {
637
+ Log.d(TAG, "Closing serial connection");
638
+
639
+ try {
640
+ // TODO: Close connection with serial port plugin
641
+ isConnected = false;
642
+
643
+ return new IOBoardResponse(true, "Serial connection closed successfully");
644
+
645
+ } catch (Exception e) {
646
+ Log.e(TAG, "Error closing connection", e);
647
+ return new IOBoardResponse(false, "Error closing connection: " + e.getMessage());
648
+ }
649
+ }
650
+
651
+ /**
652
+ * Check if serial connection is open
653
+ */
654
+ public boolean isConnected() {
655
+ return isConnected;
656
+ }
657
+ }