diff --git a/app/src/main/java/com/sw/platecabinet/GlobalData.kt b/app/src/main/java/com/sw/platecabinet/GlobalData.kt index de0e90a..1212717 100644 --- a/app/src/main/java/com/sw/platecabinet/GlobalData.kt +++ b/app/src/main/java/com/sw/platecabinet/GlobalData.kt @@ -40,7 +40,7 @@ object GlobalData { */ const val LOCAL_BASE_URL: String = "http://192.168.10.101:24801" const val TEST_BASE_URL: String = "https://dev.yixiong-tech.com:8081" - const val PROD_BASE_URL: String = "https://api.dm.yixiong-tech.com:8443" + const val PROD_BASE_URL: String = "https://platform-api.uat.shuziweidao.com" /** * 设备id diff --git a/app/src/main/java/com/sw/platecabinet/utils/mego/PlcHelper.kt b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcHelper.kt index 8447fb1..6a83791 100644 --- a/app/src/main/java/com/sw/platecabinet/utils/mego/PlcHelper.kt +++ b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcHelper.kt @@ -4,10 +4,16 @@ import android.content.Context import android.os.Handler import android.os.Looper import com.megoai.plc_aar.SDK +import java.util.concurrent.atomic.AtomicBoolean /** * PLC 操作工具类(单例) * 封装 SDK 所有接口,统一回调到主线程 + * + * 注意:底层 PLC SDK(Flutter MethodChannel 封装)的 Listener 只有 onMessage 一个回调, + * Flutter 侧 error()/notImplemented() 均为空实现,串口异常或引擎未就绪时不会回调。 + * 因此本类对所有动作类、查询类接口统一加超时兜底:超时未响应则触发 onError, + * 保证上层回调链不会因“无响应”而永久挂起。 */ class PlcHelper private constructor(context: Context) { @@ -28,6 +34,59 @@ class PlcHelper private constructor(context: Context) { } } + // ==================== 超时兜底封装 ==================== + + /** + * 包装 SDK 动作/查询调用:超时未响应时主动触发 onError。 + * + * 背景:底层 SDK 的 Listener 仅在 Flutter 侧 success() 时回调 onMessage, + * error()/notImplemented() 为空实现,串口异常时 Android 侧收不到任何回调, + * 会导致上层回调永久挂起。本方法用定时器兜底,并保证 onSuccess/onError 至多触发一次。 + * + * @param timeoutMs 超时时长(毫秒) + * @param callback 上层回调(统一在主线程回调) + * @param action 实际发起 SDK 调用的逻辑,参数为经过防重入包装的“安全回调”, + * 内部所有成功/失败出口都应通过该回调触发 + * @param 回调结果类型 + */ + private inline fun withTimeout( + timeoutMs: Long, + callback: PlcCallback, + crossinline action: (safeCallback: PlcCallback) -> Unit + ) { + // 标记回调是否已触发,保证 onSuccess/onError 至多执行一次 + val fired = AtomicBoolean(false) + // 包装后的安全回调,所有出口都经过它,避免重复回调 + val safeCallback = object : PlcCallback { + override fun onSuccess(result: T) { + if (fired.compareAndSet(false, true)) callback.onSuccess(result) + } + + override fun onError(message: String) { + if (fired.compareAndSet(false, true)) callback.onError(message) + } + } + // 超时定时器:到期未收到 SDK 回调则触发 onError + val timeoutRunnable = Runnable { + safeCallback.onError("PLC 操作超时(${timeoutMs}ms)未响应") + } + mainHandler.postDelayed(timeoutRunnable, timeoutMs) + // 发起实际 SDK 调用,所有成功/失败都通过 safeCallback 回调 + action(object : PlcCallback { + override fun onSuccess(result: T) { + // 成功后取消超时定时器 + mainHandler.removeCallbacks(timeoutRunnable) + safeCallback.onSuccess(result) + } + + override fun onError(message: String) { + // 失败同样取消超时定时器 + mainHandler.removeCallbacks(timeoutRunnable) + safeCallback.onError(message) + } + }) + } + // ==================== 连接与模式 ==================== /** @@ -43,8 +102,10 @@ class PlcHelper private constructor(context: Context) { * 打开自动模式(应用启动时调用一次) */ fun openAutoMode(callback: PlcCallback) { - sdk.actionOpenAutoMode { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(5000, callback) { safe -> + sdk.actionOpenAutoMode { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } @@ -52,76 +113,90 @@ class PlcHelper private constructor(context: Context) { * 故障复位(出现 alarmCode 或补盘完成后调用) */ fun alarmReset(callback: PlcCallback) { - sdk.actionAlarmReset { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(5000, callback) { safe -> + sdk.actionAlarmReset { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } // ==================== 出盘操作 ==================== /** - * 出盘 + * 出盘(机械动作,超时 10s) */ fun outPlate(callback: PlcCallback) { - sdk.actionOutPlate { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(10000, callback) { safe -> + sdk.actionOutPlate { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } // ==================== 平台控制 ==================== /** - * 平台下降(开始补盘) + * 平台下降(开始补盘,超时 8s) */ fun platformDown(callback: PlcCallback) { - sdk.actionPlatformDown { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(8000, callback) { safe -> + sdk.actionPlatformDown { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } /** - * 平台上升(补盘完成) + * 平台上升(补盘完成,超时 8s) */ fun platformUp(callback: PlcCallback) { - sdk.actionPlatformDownStop { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(8000, callback) { safe -> + sdk.actionPlatformDownStop { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } /** - * 补盘完成返回营业(自动模式 + 故障复位) + * 补盘完成返回营业(自动模式 + 故障复位,超时 5s) */ fun backToBusiness(callback: PlcCallback) { - sdk.actionOpenAutoModeAndActionAlarmReset { result -> - mainHandler.post { callback.onSuccess(result.toString()) } + withTimeout(5000, callback) { safe -> + sdk.actionOpenAutoModeAndActionAlarmReset { result -> + mainHandler.post { safe.onSuccess(result.toString()) } + } } } // ==================== 状态查询 ==================== /** - * 获取 PLC 状态(解析为 PlcStatus 对象) + * 获取 PLC 状态(解析为 PlcStatus 对象,超时 3s) */ fun getStatus(callback: PlcCallback) { - sdk.getPlcStatus { json -> - mainHandler.post { - if (json != null) { - callback.onSuccess(PlcStatus.Companion.fromJson(json.toString())) - } else { - callback.onError("获取状态失败") + withTimeout(3000, callback) { safe -> + sdk.getPlcStatus { json -> + mainHandler.post { + if (json != null) { + safe.onSuccess(PlcStatus.Companion.fromJson(json.toString())) + } else { + safe.onError("获取状态失败") + } } } } } /** - * 获取 PLC 状态(原始 JSON 字符串) + * 获取 PLC 状态(原始 JSON 字符串,超时 3s) */ fun getStatusJson(callback: PlcCallback) { - sdk.getPlcStatus { json -> - mainHandler.post { - if (json != null) callback.onSuccess(json.toString()) - else callback.onError("获取状态失败") + withTimeout(3000, callback) { safe -> + sdk.getPlcStatus { json -> + mainHandler.post { + if (json != null) safe.onSuccess(json.toString()) + else safe.onError("获取状态失败") + } } } } @@ -129,16 +204,18 @@ class PlcHelper private constructor(context: Context) { // ==================== 参数设置 ==================== /** - * 设置 PLC 参数 + * 设置 PLC 参数(超时 3s) * @param paramType 参数类型(如 "18FD" 表示主电机运行最长时间) * @param paramValue 参数值(int,单位 0.1s) */ fun setParams(paramType: String, paramValue: Int, callback: PlcCallback) { - sdk.setPLCParams( - { result -> mainHandler.post { callback.onSuccess(result.toString()) } }, - paramType, - paramValue - ) + withTimeout(3000, callback) { safe -> + sdk.setPLCParams( + { result -> mainHandler.post { safe.onSuccess(result.toString()) } }, + paramType, + paramValue + ) + } } // ==================== 生命周期 ====================