diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7036943..48130c0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -60,6 +60,7 @@ dependencies { implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) implementation(project(":lib_face")) + implementation(files("libs/plc_aar_104.aar")) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/libs/plc_aar_104.aar b/app/libs/plc_aar_104.aar new file mode 100644 index 0000000..1c5eef6 Binary files /dev/null and b/app/libs/plc_aar_104.aar differ diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt index bae86fd..bb7777a 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -57,6 +57,9 @@ import com.sw.platecabinet.utils.LogFileUtil import com.sw.platecabinet.utils.PlateUtils import com.sw.platecabinet.utils.RegisterCallbackHandler import com.sw.platecabinet.utils.SoundPoolUtil +import com.sw.platecabinet.utils.mego.PlcCallback +import com.sw.platecabinet.utils.mego.PlcHelper +import com.sw.platecabinet.utils.mego.PlcStatus import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -386,39 +389,48 @@ class LoginByFaceActivity : BaseActivity(), private var plateEnable = false /** - * 检测有无餐盘 - */ - private fun checkHasPlate(block: (Boolean) -> Unit) { - showWaitingDialog("检测餐盘中,请稍候……") - binding.root.postDelayed({ - hideWaitingDialog() - block(true) - }, 1500) - } - - /** - * 打开餐盘柜 + * 打开餐盘柜:先获取 PLC 状态,有盘则出盘,无盘则播放提示音 */ private fun openPlate(userId: String?) { if (plateEnable.not()) return loadLogInfo("collectFace,openPlate: userId=$userId") - checkHasPlate { hasPlate -> - if (hasPlate.not()) { - //暂无餐盘,请联系管理人员 - loadLogInfo("collectFace,openPlate: 暂无餐盘,请联系管理人员,isCollectFace=$isCollectFace") + showWaitingDialog("检测餐盘中,请稍候……") + PlcHelper.getInstance(this).getStatus(object : PlcCallback { + override fun onSuccess(result: PlcStatus) { + hideWaitingDialog() + if (result.isEmptyPlate) { + // 无餐盘,播放提示音并返回首页 + loadLogInfo("collectFace,openPlate: 暂无餐盘,isEmptyPlate=true,isCollectFace=$isCollectFace") + SoundPoolUtil.getInstance().play(NO_PLATE_REMIND, 0) + goInitActivity() + return + } + // 有餐盘,播放识别成功音效并调用出盘 + loadLogInfo("collectFace,openPlate: 检测到餐盘,开始出盘") + SoundPoolUtil.getInstance().play(RECOGNIZE_SUCCESS, 0) + plateEnable = false + recognizeCountDownUtil.cancelCountDown() + PlcHelper.getInstance(this@LoginByFaceActivity).outPlate(object : PlcCallback { + override fun onSuccess(result: String) { + loadLogInfo("collectFace,openPlate: 出盘成功,result=$result") + goInitActivity() + } + + override fun onError(message: String) { + loadLogInfo("collectFace,openPlate: 出盘失败,message=$message") + goInitActivity() + } + }) + } + + override fun onError(message: String) { + hideWaitingDialog() + // 状态获取失败,保底播放无盘提示 + loadLogInfo("collectFace,openPlate: 获取PLC状态失败,message=$message") SoundPoolUtil.getInstance().play(NO_PLATE_REMIND, 0) goInitActivity() - return@checkHasPlate } - //取餐盘 - SoundPoolUtil.getInstance().play(RECOGNIZE_SUCCESS, 0) - //调用发盘方法 - PlateUtils.open(this, "", false) { - goInitActivity() - } - plateEnable = false - recognizeCountDownUtil.cancelCountDown() - } + }) } private val openDebouncer by lazy { Debouncer(5000) } diff --git a/app/src/main/java/com/sw/platecabinet/utils/mego/PlcCallback.kt b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcCallback.kt new file mode 100644 index 0000000..099cb4e --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcCallback.kt @@ -0,0 +1,16 @@ +package com.sw.platecabinet.utils.mego + +/** + * PLC 操作统一回调接口 + */ +interface PlcCallback { + /** + * 操作成功回调(主线程) + */ + fun onSuccess(result: T) + + /** + * 操作失败回调(主线程) + */ + fun onError(message: String) +} 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 new file mode 100644 index 0000000..8447fb1 --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcHelper.kt @@ -0,0 +1,152 @@ +package com.sw.platecabinet.utils.mego + +import android.content.Context +import android.os.Handler +import android.os.Looper +import com.megoai.plc_aar.SDK + +/** + * PLC 操作工具类(单例) + * 封装 SDK 所有接口,统一回调到主线程 + */ +class PlcHelper private constructor(context: Context) { + + private val sdk: SDK = SDK.getInstance(context) + private val mainHandler = Handler(Looper.getMainLooper()) + + companion object { + @Volatile + private var instance: PlcHelper? = null + + /** + * 获取单例实例 + */ + fun getInstance(context: Context): PlcHelper { + return instance ?: synchronized(this) { + instance ?: PlcHelper(context.applicationContext).also { instance = it } + } + } + } + + // ==================== 连接与模式 ==================== + + /** + * 打开出盘串口(应用启动时调用) + */ + fun openSerialPort(callback: PlcCallback) { + sdk.openPlcSerialPort { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + /** + * 打开自动模式(应用启动时调用一次) + */ + fun openAutoMode(callback: PlcCallback) { + sdk.actionOpenAutoMode { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + /** + * 故障复位(出现 alarmCode 或补盘完成后调用) + */ + fun alarmReset(callback: PlcCallback) { + sdk.actionAlarmReset { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + // ==================== 出盘操作 ==================== + + /** + * 出盘 + */ + fun outPlate(callback: PlcCallback) { + sdk.actionOutPlate { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + // ==================== 平台控制 ==================== + + /** + * 平台下降(开始补盘) + */ + fun platformDown(callback: PlcCallback) { + sdk.actionPlatformDown { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + /** + * 平台上升(补盘完成) + */ + fun platformUp(callback: PlcCallback) { + sdk.actionPlatformDownStop { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + /** + * 补盘完成返回营业(自动模式 + 故障复位) + */ + fun backToBusiness(callback: PlcCallback) { + sdk.actionOpenAutoModeAndActionAlarmReset { result -> + mainHandler.post { callback.onSuccess(result.toString()) } + } + } + + // ==================== 状态查询 ==================== + + /** + * 获取 PLC 状态(解析为 PlcStatus 对象) + */ + fun getStatus(callback: PlcCallback) { + sdk.getPlcStatus { json -> + mainHandler.post { + if (json != null) { + callback.onSuccess(PlcStatus.Companion.fromJson(json.toString())) + } else { + callback.onError("获取状态失败") + } + } + } + } + + /** + * 获取 PLC 状态(原始 JSON 字符串) + */ + fun getStatusJson(callback: PlcCallback) { + sdk.getPlcStatus { json -> + mainHandler.post { + if (json != null) callback.onSuccess(json.toString()) + else callback.onError("获取状态失败") + } + } + } + + // ==================== 参数设置 ==================== + + /** + * 设置 PLC 参数 + * @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 + ) + } + + // ==================== 生命周期 ==================== + + /** + * 释放资源,清除单例 + */ + fun release() { + instance = null + } +} diff --git a/app/src/main/java/com/sw/platecabinet/utils/mego/PlcStatus.kt b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcStatus.kt new file mode 100644 index 0000000..96bdf15 --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/mego/PlcStatus.kt @@ -0,0 +1,34 @@ +package com.sw.platecabinet.utils.mego + +import org.json.JSONObject + +/** + * PLC 状态数据类 + */ +data class PlcStatus( + val isEmptyPlate: Boolean = false, // 是否空盘 + val isPlateformDown: Boolean = false, // 平台是否在下位 + val isPlateformUp: Boolean = false, // 平台是否在上位 + val isTakePlateInfrared: Boolean = false, // 取盘红外是否触发 + val alarmCode: Int = 0 // 报警代码 +) { + companion object { + /** + * 从 JSON 字符串解析状态 + */ + fun fromJson(json: String): PlcStatus { + return try { + val obj = JSONObject(json) + PlcStatus( + isEmptyPlate = obj.optBoolean("isEmptyPlate", false), + isPlateformDown = obj.optBoolean("isPlateformDown", false), + isPlateformUp = obj.optBoolean("isPlateformUp", false), + isTakePlateInfrared = obj.optBoolean("isTakePlateInfrared", false), + alarmCode = obj.optInt("alarmCode", 0) + ) + } catch (e: Exception) { + PlcStatus() + } + } + } +}