feat(ch934x_serial): 添加多端口并发轮询流功能

- 新增多端口并发轮询流 portDataStream 方法,支持每周期轮询 8 个端口
- 修改 read 方法增加 serialPortIndex 参数,支持指定端口读取数据
- 更新 Android 原生实现,支持通过 serialPortIndex 参数指定读取端口
- 移除 IDataCallback 注册逻辑,改用轮询方式拉取数据避免缓冲区冲突
- 添加主线程切换机制,确保异常推送在主线程执行
- 更新 pubspec.yaml 添加 ch934x_serial 本地插件依赖
- 更新项目路线图,标记 Phase 42 完成,进度更新至 50%
This commit is contained in:
Developer
2026-07-07 14:25:24 +08:00
parent 71fd9f52ec
commit ee19d2fdfa
4 changed files with 45 additions and 34 deletions
@@ -10,6 +10,8 @@ import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -22,7 +24,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import cn.wch.ch934xlib.CH934XManager;
import cn.wch.ch934xlib.callback.IDataCallback;
import cn.wch.ch934xlib.callback.IModemStatus;
import cn.wch.ch934xlib.callback.IUsbStateChange;
import cn.wch.ch934xlib.chip.ChipType;
@@ -74,9 +75,6 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
/** 当前会话选中的串口索引(对应文档 5.1.1 中的 serialPortIndex)。 */
private int activeSerialNumber = -1;
/** 当前会话是否已注册了 IDataCallback,用于避免重复注册。 */
private boolean dataCallbackRegistered = false;
/** 当前会话是否已注册了 IModemStatus,用于避免重复注册。 */
private boolean modemCallbackRegistered = false;
@@ -153,7 +151,6 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
}
activeDevice = null;
activeSerialNumber = -1;
dataCallbackRegistered = false;
modemCallbackRegistered = false;
exceptionCallbackEnabled = false;
}
@@ -371,7 +368,9 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
}
activeDevice = device;
activeSerialNumber = serialPortIndex;
ensureDataCallback();
// 注意:不注册 IDataCallback — SDK 在有回调注册时会通过回调
// 投递数据并释放内部缓冲区,导致 readData() 返回空。
// 通过 dataStream 轮询 readData() 拉取数据。
ensureModemCallback();
return true;
}
@@ -486,7 +485,6 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
}
activeDevice = null;
activeSerialNumber = -1;
dataCallbackRegistered = false;
modemCallbackRegistered = false;
modemStatusCache = 0;
return true;
@@ -519,10 +517,13 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
if (length == null || length <= 0) {
return new byte[0];
}
// 可选参数:指定读哪个端口的缓冲区。不传则读 activeSerialNumber(向后兼容)
Integer portIndex = call.argument("serialPortIndex");
int idx = (portIndex != null) ? portIndex : activeSerialNumber;
try {
// SDK 返回内部缓冲的所有数据,与文档 read 语义一致。
byte[] data = CH934XManager.getInstance()
.readData(activeDevice, activeSerialNumber);
.readData(activeDevice, idx);
if (data == null || data.length == 0) {
return new byte[0];
}
@@ -682,25 +683,6 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
return ports;
}
/** 注册 IDataCallback 推送数据上抛(可选,目前仅用作 SDK 内部缓冲预热)。 */
private void ensureDataCallback() {
if (dataCallbackRegistered || activeDevice == null) {
return;
}
try {
CH934XManager.getInstance().registerDataCallback(activeDevice,
new IDataCallback() {
@Override
public void onData(int serialNumber, byte[] buffer, int length) {
// 数据通过 readData 拉取即可,这里留空。
}
});
dataCallbackRegistered = true;
} catch (Throwable t) {
// 注册失败不影响主流程,readData 仍可工作。
}
}
private void ensureModemCallback() {
if (modemCallbackRegistered || activeDevice == null) {
return;
@@ -740,11 +722,15 @@ public class Ch934xSerialPlugin implements FlutterPlugin, MethodCallHandler, Act
}
}
/** 主动上抛异常给 Dart 侧。 */
/** 主动上抛异常给 Dart 侧。若当前非主线程则自动切换到主线程再发送。 */
private void pushException(int type, String message, @Nullable String cause) {
if (!exceptionCallbackEnabled || channel == null) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
new Handler(Looper.getMainLooper()).post(() -> pushException(type, message, cause));
return;
}
Map<String, Object> payload = new HashMap<>();
payload.put("type", type);
payload.put("message", message);