From 7a6c4012d1db11bab2dfa5dffdfcee84968612d4 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 26 Dec 2025 14:05:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A4=90=E7=9B=98=E6=9F=9C=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/gradle.xml | 2 +- .../java/com/sw/platecabinet/GlobalData.kt | 2 +- .../main/java/com/sw/platecabinet/MyApp.kt | 2 + .../sw/platecabinet/activity/BaseActivity.kt | 112 +++++++++-- .../activity/DeviceInitActivity.kt | 56 +++--- .../activity/LoginByFaceActivity.kt | 7 +- .../activity/LoginByPwdActivity.kt | 8 +- .../java/com/sw/platecabinet/ext/CommonExt.kt | 13 ++ .../fragment/BindPlateFragment.kt | 85 +++++---- .../fragment/SettingListFragment.kt | 16 +- .../fragment/UnBindPlateFragment.kt | 41 ++-- .../platecabinet/model/request/BindParam.kt | 10 +- .../platecabinet/model/request/LoginParam.kt | 12 +- .../model/response/EquipmentUserInfo.kt | 49 +++-- .../model/response/SearchResult.kt | 53 +++--- .../model/response/UserFaceModel.kt | 27 +-- .../sw/platecabinet/network/api/ApiService.kt | 158 +++++++++++----- .../network/interceptor/RequestInterceptor.kt | 4 + .../network/task/HeartBeatTask.kt | 104 +++++----- .../repository/RemoteRepository.kt | 127 ++++++++----- .../sw/platecabinet/utils/IntervalExecutor.kt | 66 +++++++ .../com/sw/platecabinet/utils/SpTool.java | 20 ++ .../platecabinet/viewmodel/BaseViewModel.kt | 4 +- .../platecabinet/viewmodel/DeviceViewModel.kt | 136 ++++++------- .../viewmodel/SettingViewModel.kt | 178 ++++++++++++------ .../platecabinet/viewmodel/UserViewModel.kt | 70 +++---- lib_face/build.gradle.kts | 2 +- .../com/sw/plate/utils/arcface/FaceApi.java | 2 +- 28 files changed, 859 insertions(+), 507 deletions(-) create mode 100644 app/src/main/java/com/sw/platecabinet/utils/IntervalExecutor.kt create mode 100644 app/src/main/java/com/sw/platecabinet/utils/SpTool.java diff --git a/.idea/gradle.xml b/.idea/gradle.xml index fdafc97..f94744b 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,6 +4,7 @@ diff --git a/app/src/main/java/com/sw/platecabinet/GlobalData.kt b/app/src/main/java/com/sw/platecabinet/GlobalData.kt index 83895f9..01c2ba6 100644 --- a/app/src/main/java/com/sw/platecabinet/GlobalData.kt +++ b/app/src/main/java/com/sw/platecabinet/GlobalData.kt @@ -33,7 +33,7 @@ object GlobalData { /** * 具体业务baseurl */ - var appBaseUrl: String = "" + var appBaseUrl: String = "https://dev.yixiong-tech.com:8081" /** * 设备id diff --git a/app/src/main/java/com/sw/platecabinet/MyApp.kt b/app/src/main/java/com/sw/platecabinet/MyApp.kt index 5419329..147b774 100644 --- a/app/src/main/java/com/sw/platecabinet/MyApp.kt +++ b/app/src/main/java/com/sw/platecabinet/MyApp.kt @@ -26,5 +26,7 @@ class MyApp : App() { private fun initGlobalData() { GlobalData.appVersion = AppUtil.getAppVersionCode(this).toString() GlobalData.globalEquipmentCode = "202501171634" + + GlobalData.appBaseUrl = "http://192.168.1.201:14801" } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt index 1f58728..fe997cb 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt @@ -17,8 +17,11 @@ import androidx.core.view.WindowCompat import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding import com.sw.inbound.utils.DateTimeUtils +import com.sw.plate.utils.Base64 import com.sw.plate.utils.ScanGunKeyEventHelper import com.sw.plate.utils.ToastUtils +import com.sw.plate.utils.arcface.facedb.FaceDatabase +import com.sw.plate.utils.arcface.facedb.entity.FaceEntity import com.sw.plate.utils.comn.SerialApi import com.sw.plate.utils.comn.SerialPortManager import com.sw.platecabinet.R @@ -26,7 +29,10 @@ import com.sw.platecabinet.databinding.ItemTitleTimeBinding import com.sw.platecabinet.dialog.BalanceNotEnoughDialog import com.sw.platecabinet.ext.setClickListeners import com.sw.platecabinet.model.response.EquipmentUserInfo +import com.sw.platecabinet.model.response.UserFaceModel +import com.sw.platecabinet.utils.IntervalExecutor import com.sw.platecabinet.utils.PermissionHelper +import com.sw.platecabinet.utils.SpTool import com.sw.platecabinet.view.CustomLoadingDialog import com.sw.platecabinet.viewmodel.SettingViewModel import com.sw.platecabinet.viewmodel.UserViewModel @@ -77,6 +83,8 @@ abstract class BaseActivity : AppCompatActivity() { registerKeyEvent() val durationTime = System.currentTimeMillis() - startTime Timber.d("启动时间:$durationTime") + + startFaceTask() } /** @@ -291,23 +299,27 @@ abstract class BaseActivity : AppCompatActivity() { handleLoginSuccess(it, true) } } - lifecycleScope.launch { - settingViewModel.equipmentList.collect { - if (it.isEmpty()) return@collect - val unbindList = it.filter { !it.isBound() } - if (unbindList.isEmpty()) { - MainActivity.start(context = context, pageType = PageType.PLATE_CABINET_FULL) - } else { - val firstInfo = unbindList[0] - val currentUserInfo = settingViewModel.searchUserInfo.value - firstInfo.plateNumber = currentUserInfo?.plateNumber ?: "" - MainActivity.start( - context = context, - pageType = PageType.BIND_PLATE, - equipmentUserInfo = firstInfo - ) - } - } +// lifecycleScope.launch { +// settingViewModel.equipmentList.collect { +// loadEquipmentList(it) +// } +// } + } + + private fun loadEquipmentList(items:List) { + if (items.isEmpty()) return + val unbindList = items.filter { !it.isBound() } + if (unbindList.isEmpty()) { + MainActivity.start(context = context, pageType = PageType.PLATE_CABINET_FULL) + } else { + val firstInfo = unbindList[0] + val currentUserInfo = settingViewModel.searchUserInfo.value + firstInfo.plateNumber = currentUserInfo?.plateNumber ?: "" + MainActivity.start( + context = context, + pageType = PageType.BIND_PLATE, + equipmentUserInfo = firstInfo + ) } } @@ -352,7 +364,9 @@ abstract class BaseActivity : AppCompatActivity() { }) } else { if (isAdmin) { - settingViewModel.getEquipmentList() + settingViewModel.getEquipmentList{ + loadEquipmentList(it) + } } else { Timber.d("无餐盘信息") MainActivity.start( @@ -370,4 +384,66 @@ abstract class BaseActivity : AppCompatActivity() { keyEventHelper?.onDestroy() super.onDestroy() } + + + private val intervalExecutor by lazy { IntervalExecutor() } + private var faceTaskJob: Job? = null + + // private val initialDelay = 5 * 60 * 1000L +// private val dealyMillis = 10 * 60 * 1000L + private val initialDelay = 60 * 1000L + private val dealyMillis = 30 * 1000L + private var taskPageNo = 1 + fun startFaceTask() { + faceTaskJob = + intervalExecutor.startIntervalTaskWithInitialDelay(initialDelay, dealyMillis) { + settingViewModel.getFaceIncrementList( + pageNo = taskPageNo, + timestamp = SpTool.getLastFaceTimestamp() + ) { list -> + runOnUiThread { + if (list.isEmpty()) { + return@runOnUiThread + } + SpTool.setLastFaceTimestamp(System.currentTimeMillis()) + updateFaceData(list) + } + } + } + } + + private fun updateFaceData(list: List) { + Thread { + val faceList = mutableListOf() + try { + list.forEach { model -> + if (model.faceDeleted == true) { + //删除数据 + FaceDatabase.getInstance(this).faceDao().deleteFaceById(model.userId) + } else { + //保存数据 + val faceEntity = FaceEntity( + model.userId, + null, + Base64.decode(model.faceFeatureStr) + ).also { + it.userType = "1" + } + faceList.add(faceEntity) + } + } + } catch (e: Exception) { + e.printStackTrace() + } + try { + if (faceList.isNotEmpty()) { + FaceDatabase.getInstance(this).faceDao().insert(faceList) + } + recognizeViewModel.refreshFaceList(); + } catch (e: Exception) { + e.printStackTrace() + } + }.start() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt index 1e03489..b27170d 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt @@ -1,24 +1,19 @@ package com.sw.platecabinet.activity import android.content.Intent -import androidx.activity.viewModels -import androidx.lifecycle.lifecycleScope import com.sw.plate.utils.AppUtil import com.sw.platecabinet.GlobalData import com.sw.platecabinet.databinding.ActivityDeviceInitBinding import com.sw.platecabinet.databinding.ItemTitleTimeBinding -import com.sw.platecabinet.utils.QRCodeUtil -import com.sw.platecabinet.viewmodel.DeviceViewModel -import kotlinx.coroutines.launch -import timber.log.Timber -import kotlin.getValue +import com.sw.platecabinet.ext.gone +import com.sw.platecabinet.ext.invisible /** * 设备初始化界面 */ class DeviceInitActivity : BaseActivity() { - private val deviceViewModel by viewModels() +// private val deviceViewModel by viewModels() override fun inflateViewBinding(): ActivityDeviceInitBinding { return ActivityDeviceInitBinding.inflate(layoutInflater) @@ -32,31 +27,36 @@ class DeviceInitActivity : BaseActivity() { var deviceId = AppUtil.getUDID(this) deviceId = "be154831-3466-3ba2-a2ea-57652c919fed" GlobalData.deviceId = deviceId - val isSuccess = deviceViewModel.checkEquipmentInfo() - if (isSuccess) { +// val isSuccess = deviceViewModel.checkEquipmentInfo() +// if (isSuccess) { +// goLoginActivity() +// return +// } +// binding.ivQrCode.setImageBitmap( +// QRCodeUtil.generateQRCode( +// content = GlobalData.deviceId, +// size = 200 +// ) +// ) +// binding.btnInit.setOnClickListener { +// deviceViewModel.getDeviceToken() +// } + binding.btnInit.gone() + binding.ivQrCode.invisible() + binding.root.postDelayed({ goLoginActivity() - return - } - binding.ivQrCode.setImageBitmap( - QRCodeUtil.generateQRCode( - content = GlobalData.deviceId, - size = 200 - ) - ) - binding.btnInit.setOnClickListener { - deviceViewModel.getDeviceToken() - } + }, 1000) } override fun registerDataChange() { super.registerDataChange() - lifecycleScope.launch { - deviceViewModel.deviceInfoResult.collect { it -> - if (it == true) { - goLoginActivity() - } - } - } +// lifecycleScope.launch { +// deviceViewModel.deviceInfoResult.collect { it -> +// if (it == true) { +// goLoginActivity() +// } +// } +// } } private fun goLoginActivity() { 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 6efff03..d6a569a 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -79,7 +79,10 @@ class LoginByFaceActivity : BaseActivity(), initArcView() openRectInfoDraw = true recognizeViewModel.setDrawRectInfoTextValue(true) - viewModel.generateToken() + //viewModel.generateToken() + viewModel.activeEngine() + viewModel.getUserFaceCache() + binding.llToPwd.setOnClickListener { val intent = Intent(this, LoginByPwdActivity::class.java) startActivity(intent) @@ -169,7 +172,7 @@ class LoginByFaceActivity : BaseActivity(), recognizeViewModel.recognizeUserId.observe(this, Observer { userId: String? -> Timber.i("recognizeUserId observe userId = $userId") - viewModel.getUserInfoById(memberId = userId?.toInt() ?: 0) + viewModel.getUserInfoById(memberId = userId?.toIntOrNull()) }) recognizeViewModel.drawRectInfoText.observe(this, Observer { info -> diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt index 4f8038e..3033930 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt @@ -5,6 +5,7 @@ import com.sw.plate.utils.ToastUtils import com.sw.platecabinet.databinding.ActivityLoginByPwdBinding import com.sw.platecabinet.databinding.ItemTitleTimeBinding import com.sw.platecabinet.dialog.BalanceNotEnoughDialog +import com.sw.platecabinet.model.request.LoginParam import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.utils.KeyboardUtils @@ -29,7 +30,12 @@ class LoginByPwdActivity : BaseActivity() { ToastUtils.showToast("手机或校验码不能为空") return@setOnClickListener } - viewModel.loginWithPwd(phone = phone, password = pwd) + val loginParam = LoginParam( + //equipmentId = equipmentId, + phone = phone, + password = pwd + ) + viewModel.loginWithPwd(loginParam) KeyboardUtils.hideKeyboard(this) } binding.tvFaceRec.setOnClickListener { diff --git a/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt b/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt index 3f3c359..d449c3b 100644 --- a/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt +++ b/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt @@ -2,6 +2,7 @@ package com.sw.platecabinet.ext import android.content.res.Resources import android.util.TypedValue +import android.view.View import androidx.annotation.Dimension /** @@ -50,4 +51,16 @@ val Float.sp: Float fun formatNumber(num: String): String { return num.padStart(2, '0') +} + +fun View.visible() { + visibility = View.VISIBLE +} + +fun View.invisible() { + visibility = View.INVISIBLE +} + +fun View.gone() { + visibility = View.GONE } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt index f2257aa..84a946f 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt @@ -24,6 +24,8 @@ import com.sw.platecabinet.databinding.ItemSearchUserInfoBinding import com.sw.platecabinet.dialog.UserBindRemindDialog import com.sw.platecabinet.ext.maskName import com.sw.platecabinet.ext.maskPhone +import com.sw.platecabinet.model.ErrorInfo +import com.sw.platecabinet.model.request.BindParam import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.model.response.SearchResult import com.sw.platecabinet.utils.Debouncer @@ -188,13 +190,16 @@ class BindPlateFragment : BaseFragment( ToastUtils.showToast("选中的会员信息异常") return@setOnClickListener } - - viewModel.bindPlate( + val bindParam = BindParam( + equipmentId = info!!.equipmentId, equipmentCode = info!!.equipmentCode!!, equipmentBoxCode = info!!.equipmentBoxCode!!, memberId = checkedItem!!.id!!, plateNumber = plateNumber ) + viewModel.bindPlate(bindParam) { pair -> + updateBindState(pair) + } KeyboardUtils.hideKeyboard(requireActivity()) } binding.tvBack.setOnClickListener { activity?.finish() } @@ -210,41 +215,11 @@ class BindPlateFragment : BaseFragment( adapter.updateData(it) } } - lifecycleScope.launch { - viewModel.bindStateChange.collect { - if (it.first == null) return@collect // 解绑状态过滤 - val errorInfo = it.second - if (errorInfo.isSuccess()) { - if (errorInfo.equipmentUserInfo == null) { - ToastUtils.showToast("数据异常") - return@collect - } - if (errorInfo.equipmentUserInfo.isOtherEquipment() == true) { - MainActivity.start( - requireContext(), - pageType = PageType.PLATE_TIP, - equipmentUserInfo = errorInfo.equipmentUserInfo, - isAdmin = true - ) - } else { - SerialApi.openPlate( - errorInfo.equipmentUserInfo.equipmentBoxCode!!.toInt(), - object : SerialPortManager.SendCallback { - override fun onSuccess() { - ToastUtils.showToast("绑定成功") - activity?.finish() - } - - override fun onFail(e: Exception?) { - ToastUtils.showToast("绑定失败") - } - }) - } - } else { - ToastUtils.showToast(errorInfo.msg) - } - } - } +// lifecycleScope.launch { +// viewModel.bindStateChange.collect { +// updateBindState(it) +// } +// } } private fun createAdapter(): GenericItemAdapter { @@ -267,7 +242,7 @@ class BindPlateFragment : BaseFragment( //TODO 调用接口查询用户是否已绑盘 this@BindPlateFragment.equipmentBoxCode = null (activity as? MainActivity)?.showWaitingDialog("查询中,请稍后……") - userViewModel.getUserInfoById(memberId = item.id!!) { + userViewModel.getUserInfoById(memberId = item.id) { (activity as? MainActivity)?.hideWaitingDialog() this@BindPlateFragment.equipmentBoxCode = it?.equipmentBoxCode } @@ -285,4 +260,38 @@ class BindPlateFragment : BaseFragment( ) .show() } + + private fun updateBindState(pair: Pair){ + if (pair.first == null) return // 解绑状态过滤 + val errorInfo = pair.second + if (errorInfo.isSuccess()) { + if (errorInfo.equipmentUserInfo == null) { + ToastUtils.showToast("数据异常") + return + } + if (errorInfo.equipmentUserInfo.isOtherEquipment()) { + MainActivity.start( + requireContext(), + pageType = PageType.PLATE_TIP, + equipmentUserInfo = errorInfo.equipmentUserInfo, + isAdmin = true + ) + } else { + SerialApi.openPlate( + errorInfo.equipmentUserInfo.equipmentBoxCode!!.toInt(), + object : SerialPortManager.SendCallback { + override fun onSuccess() { + ToastUtils.showToast("绑定成功") + activity?.finish() + } + + override fun onFail(e: Exception?) { + ToastUtils.showToast("绑定失败") + } + }) + } + } else { + ToastUtils.showToast(errorInfo.msg) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt index 0758cf5..f55994c 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt @@ -47,12 +47,12 @@ class SettingListFragment : override fun registerDataChange() { super.registerDataChange() - lifecycleScope.launch { - viewModel.equipmentList.collect { it -> - Timber.d("registerDateChange updateAdapter it = $it") - updateAdapter(it) - } - } +// lifecycleScope.launch { +// viewModel.equipmentList.collect { it -> +// Timber.d("registerDateChange updateAdapter it = $it") +// updateAdapter(it) +// } +// } } override fun initialize() { @@ -80,7 +80,9 @@ class SettingListFragment : override fun onResume() { super.onResume() - viewModel.getEquipmentList() + viewModel.getEquipmentList{ + updateAdapter(it) + } } private fun createItemAdapter(): GenericItemAdapter { diff --git a/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt index b48bbb7..bb51b26 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt @@ -12,6 +12,7 @@ import com.sw.platecabinet.activity.UnBindDialogActivity import com.sw.platecabinet.databinding.FragmentUnbindPlateBinding import com.sw.platecabinet.ext.maskName import com.sw.platecabinet.ext.maskPhone +import com.sw.platecabinet.model.ErrorInfo import com.sw.platecabinet.model.response.EquipmentUserInfo import kotlinx.coroutines.launch @@ -38,16 +39,15 @@ class UnBindPlateFragment private constructor() : BaseFragment if (result.resultCode == Activity.RESULT_OK) { - viewModel.unbindPlate( - equipmentBoxCode = info!!.equipmentBoxCode!!, - equipmentCode = info!!.equipmentCode!! - ) + viewModel.unbindPlate(info!!.id!!) { pair -> + updateBindState(pair) + } } } override fun initialize() { - arguments?.let { - info = it.getParcelable(ARG_PARAM1) + arguments?.let { args -> + info = args.getParcelable(ARG_PARAM1) info?.let { binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" binding.tvPlateNumberValue.text = it.plateNumber @@ -73,20 +73,23 @@ class UnBindPlateFragment private constructor() : BaseFragment){ + if (pair.first == null) return // 绑定状态过滤 + val errorInfo = pair.second + if (errorInfo.isSuccess()) { + ToastUtils.showToast("解绑成功") // activity?.finish() - // 关闭宿主 Activity - requireActivity().finish() - requireActivity().overridePendingTransition(0, 0) - } else { - ToastUtils.showToast(errorInfo.msg) - } - } + // 关闭宿主 Activity + requireActivity().finish() + requireActivity().overridePendingTransition(0, 0) + } else { + ToastUtils.showToast(errorInfo.msg) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/model/request/BindParam.kt b/app/src/main/java/com/sw/platecabinet/model/request/BindParam.kt index 6b49dc1..23799a2 100644 --- a/app/src/main/java/com/sw/platecabinet/model/request/BindParam.kt +++ b/app/src/main/java/com/sw/platecabinet/model/request/BindParam.kt @@ -12,28 +12,24 @@ import kotlinx.parcelize.Parcelize @Parcelize data class BindParam( /** - * app版本号 + * 设备Id */ - var appVersion: String = "", + val equipmentId: Int? = null, /** - * 设备ID + * 设备编号 */ - @SerializedName("equipmentCode") var equipmentCode: String = "", /** *设备盒子编号 */ - @SerializedName("equipmentBoxCode") val equipmentBoxCode: String? = null, /** * * 会员Id */ - @SerializedName("memberId") val memberId: Int? = null, /** *餐盘编号 */ - @SerializedName("plateNumber") val plateNumber: String? = null ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/model/request/LoginParam.kt b/app/src/main/java/com/sw/platecabinet/model/request/LoginParam.kt index 2c973fb..78eade1 100644 --- a/app/src/main/java/com/sw/platecabinet/model/request/LoginParam.kt +++ b/app/src/main/java/com/sw/platecabinet/model/request/LoginParam.kt @@ -11,27 +11,19 @@ import kotlinx.parcelize.Parcelize @Parcelize data class LoginParam( /** - * app版本号 + * 设备Id */ - var appVersion: String = "", - /** - * 设备ID - */ - @SerializedName("equipmentCode") - var equipmentCode: String = "", + val equipmentId: Int? = null, /** * 会员信息 */ - @SerializedName("memberId") val memberId: Int? = null, /** * 密码 */ - @SerializedName("password") val password: String? = null, /** * 手机号 */ - @SerializedName("phone") val phone: String? = null ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt b/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt index dfc695b..632a4ca 100644 --- a/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt +++ b/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt @@ -1,9 +1,8 @@ package com.sw.platecabinet.model.response - import android.os.Parcelable import android.text.TextUtils -import com.google.gson.annotations.SerializedName +//import com.google.gson.annotations.SerializedName import com.sw.platecabinet.GlobalData import kotlinx.parcelize.Parcelize @@ -13,55 +12,51 @@ import kotlinx.parcelize.Parcelize @Parcelize data class EquipmentUserInfo( /** - * 设备盒子编号 + * 主键 */ - @SerializedName("equipmentBoxCode") - var equipmentBoxCode: String? = "", - /** - * 设备编号 - */ - @SerializedName("equipmentCode") - var equipmentCode: String? = "", + val id: Int? = 0, /** * * 设备Id */ - @SerializedName("equipmentId") - val equipmentId: String? = "", + val equipmentId: Int? = 0, /** - * 设备名称 + * 设备编号 */ - @SerializedName("equipmentName") - val equipmentName: String? = "", + var equipmentCode: String? = "", /** - * 主键 + * 设备盒子编号 */ - @SerializedName("id") - val id: Int? = 0, + var equipmentBoxCode: String? = "", /** * 会员Id */ - @SerializedName("memberId") val memberId: Int? = 0, - - @SerializedName("name") - val name: String? = "", - @SerializedName("phone") - val phone: String? = "", /** * 餐盘编号 */ - @SerializedName("plateNumber") var plateNumber: String? = "", + /** + * 设备名称 + */ + val equipmentName: String? = "", + + val orderNo: String? = "", /** * * 更新时间 */ - @SerializedName("updateTime") val updateTime: String? = "", + val name: String? = "", + val phone: String? = "", + val faceUrl: String? = "", + val mealTime: String? = "", + val mealTimeInterval: String? = "", + val openTime: String? = "", + val openTimeInterval: String? = "", + val eatCount: Int? = 0, - @SerializedName("cardBalance") var cardBalance: Double? = 0.toDouble(), /** diff --git a/app/src/main/java/com/sw/platecabinet/model/response/SearchResult.kt b/app/src/main/java/com/sw/platecabinet/model/response/SearchResult.kt index 998b152..4c13bb5 100644 --- a/app/src/main/java/com/sw/platecabinet/model/response/SearchResult.kt +++ b/app/src/main/java/com/sw/platecabinet/model/response/SearchResult.kt @@ -49,33 +49,36 @@ data class SearchResult( ) : Parcelable { @Parcelize data class Member( - @SerializedName("cardBalance") - val cardBalance: String? = "", - @SerializedName("cardCode") - val cardCode: String? = "", - @SerializedName("consumptionCount") - val consumptionCount: Int? = 0, - @SerializedName("consumptionTotal") - val consumptionTotal: String? = "", - @SerializedName("createTime") - val createTime: String? = "", - @SerializedName("firstTopUpTime") - val firstTopUpTime: String? = "", - @SerializedName("id") +// @SerializedName("cardBalance") +// val cardBalance: String? = "", +// @SerializedName("cardCode") +// val cardCode: String? = "", +// @SerializedName("consumptionCount") +// val consumptionCount: Int? = 0, +// @SerializedName("consumptionTotal") +// val consumptionTotal: String? = "", +// @SerializedName("createTime") +// val createTime: String? = "", +// @SerializedName("firstTopUpTime") +// val firstTopUpTime: String? = "", +// @SerializedName("id") +// val id: Int? = 0, +// @SerializedName("integralBalance") +// val integralBalance: Int? = 0, +// @SerializedName("lastConsumptionTime") +// val lastConsumptionTime: String? = "", +// @SerializedName("memberFrom") +// val memberFrom: Int? = 0, +// @SerializedName("name") +// val name: String? = "", +// @SerializedName("phone") +// val phone: String? = "", +// @SerializedName("rewardBalance") +// val rewardBalance: String? = "", +// @SerializedName("topUpBalance") +// val topUpBalance: String? = "" val id: Int? = 0, - @SerializedName("integralBalance") - val integralBalance: Int? = 0, - @SerializedName("lastConsumptionTime") - val lastConsumptionTime: String? = "", - @SerializedName("memberFrom") - val memberFrom: Int? = 0, - @SerializedName("name") val name: String? = "", - @SerializedName("phone") val phone: String? = "", - @SerializedName("rewardBalance") - val rewardBalance: String? = "", - @SerializedName("topUpBalance") - val topUpBalance: String? = "" ) : Parcelable } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/model/response/UserFaceModel.kt b/app/src/main/java/com/sw/platecabinet/model/response/UserFaceModel.kt index 27593ad..53f7eb6 100644 --- a/app/src/main/java/com/sw/platecabinet/model/response/UserFaceModel.kt +++ b/app/src/main/java/com/sw/platecabinet/model/response/UserFaceModel.kt @@ -10,16 +10,21 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class UserFaceModel( - @SerializedName("faceFeature") - val faceFeature: String? = "", - @SerializedName("faceFeatureString") - val faceFeatureString: String? = "", - @SerializedName("faceType") - val faceType: String? = "", - @SerializedName("userFaceId") - val userFaceId: String? = "", - @SerializedName("userId") +// @SerializedName("faceFeature") +// val faceFeature: String? = "", +// @SerializedName("faceFeatureString") +// val faceFeatureString: String? = "", +// @SerializedName("faceType") +// val faceType: String? = "", +// @SerializedName("userFaceId") +// val userFaceId: String? = "", +// @SerializedName("userId") +// val userId: String? = "", +// @SerializedName("updateTimeStamp") +// val updateTimeStamp: Long = 0, + val userId: String? = "", - @SerializedName("updateTimeStamp") - val updateTimeStamp: Long = 0, + val faceFeatureStr: String? = "", + + val faceDeleted: Boolean?=false ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/network/api/ApiService.kt b/app/src/main/java/com/sw/platecabinet/network/api/ApiService.kt index bd58353..61fb8b2 100644 --- a/app/src/main/java/com/sw/platecabinet/network/api/ApiService.kt +++ b/app/src/main/java/com/sw/platecabinet/network/api/ApiService.kt @@ -11,6 +11,7 @@ import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.model.response.SearchResult import com.sw.platecabinet.model.response.UserFaceModel import retrofit2.http.Body +import retrofit2.http.Field import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.POST @@ -18,73 +19,109 @@ import retrofit2.http.Query import retrofit2.http.Url interface ApiService { - /** - * device获取token - */ - @GET("sys/getEquipmentToken") - suspend fun getDeviceToken( - @Query("qrcodeId") qrcodeId: String, - @Query("appVersion") appVersion: String = GlobalData.appVersion - ): ApiResponse - - /** - *获取配置信息 - */ - @GET("equipment/stEquipment/queryByEquipmentCode") - suspend fun getDeviceInfo( - @Query("equipmentCode") equipmentCode: String, - @Query("appVersion") appVersion: String = GlobalData.appVersion, - @Header("X-Access-Token") token: String - ): ApiResponse - - /** - * 生成token - */ - @GET//("/shuwei-zhct/scales/generateToken") - suspend fun generateToken( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/generateToken", - @Query("deviceId") deviceId: String, - @Query("appVersion") appVersion: String, - @Query("equipmentCode") equipmentCode: String - ): ApiResponse +// /** +// * device获取token +// */ +// @GET("sys/getEquipmentToken") +// suspend fun getDeviceToken( +// @Query("qrcodeId") qrcodeId: String, +// @Query("appVersion") appVersion: String = GlobalData.appVersion +// ): ApiResponse +// +// /** +// *获取配置信息 +// */ +// @GET("equipment/stEquipment/queryByEquipmentCode") +// suspend fun getDeviceInfo( +// @Query("equipmentCode") equipmentCode: String, +// @Query("appVersion") appVersion: String = GlobalData.appVersion, +// @Header("X-Access-Token") token: String +// ): ApiResponse +// +// /** +// * 生成token +// */ +// @GET//("/shuwei-zhct/scales/generateToken") +// suspend fun generateToken( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/generateToken", +// @Query("deviceId") deviceId: String, +// @Query("appVersion") appVersion: String, +// @Query("equipmentCode") equipmentCode: String +// ): ApiResponse /** * 获取人脸数据 */ - @GET//("/shuwei-zhct/scales/getUserFaceCache") +// @GET//("/shuwei-zhct/scales/getUserFaceCache") +// suspend fun getUserFaceCache( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/getUserFaceCache", +// @Query("appVersion") appVersion: String, +// @Query("equipmentCode") equipmentCode: String +// ): ApiResponse> + @POST suspend fun getUserFaceCache( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/getUserFaceCache", - @Query("appVersion") appVersion: String, - @Query("equipmentCode") equipmentCode: String + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/faceFeature/list", + @Body param: Map ): ApiResponse> - /** +// /** +// * 餐盘用户信息获取 +// */ +// @POST//("/shuwei-zhct/swEquipmentRelUser/equipmentBoxLogin") +// suspend fun equipmentBoxLogin( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/equipmentBoxLogin", +// @Body param: LoginParam +// ): ApiResponse + + /** * 餐盘用户信息获取 */ @POST//("/shuwei-zhct/swEquipmentRelUser/equipmentBoxLogin") suspend fun equipmentBoxLogin( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/equipmentBoxLogin", + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/getPlateBoxUserInfo", @Body param: LoginParam ): ApiResponse /** * 餐盘用户信息列表查询 */ - @POST//("/shuwei-zhct/swEquipmentRelUser/list") +// @POST//("/shuwei-zhct/swEquipmentRelUser/list") +// suspend fun getEquipmentList( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/list", +// @Body param: EquipmentParam +// ): ApiResponse> + + @GET suspend fun getEquipmentList( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/list", - @Body param: EquipmentParam + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/getYxMemberRefPlateByEquipmentCode", ): ApiResponse> +// /** +// * 餐盘用户信息绑定解绑 +// */ +// @POST//("/shuwei-zhct/swEquipmentRelUser/addOrEdit") +// suspend fun bindEquipment( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/addOrEdit", +// @Body param: BindParam +// ): ApiResponse /** - * 餐盘用户信息绑定解绑 + * 餐盘绑定 */ - @POST//("/shuwei-zhct/swEquipmentRelUser/addOrEdit") - suspend fun bindEquipment( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/addOrEdit", + @POST + suspend fun plateBind( + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/plateBinding", @Body param: BindParam ): ApiResponse + /** + * 餐盘解绑 + */ + @POST + suspend fun plateUnbind( + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/plateUnbind", + @Field("id") id: Int + ): ApiResponse + /** * 用户信息模糊搜索 */ @@ -94,23 +131,42 @@ interface ApiService { @Body param: SearchParam ): ApiResponse - /** +// /** +// * 通过餐盘号获取信息 +// */ +// @POST//("/shuwei-zhct/swEquipmentRelUser/findByPlateNumber") +// suspend fun findByPlateNumber( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/findByPlateNumber", +// @Body param: BindParam +// ): ApiResponse + + + /** * 通过餐盘号获取信息 */ - @POST//("/shuwei-zhct/swEquipmentRelUser/findByPlateNumber") + @GET suspend fun findByPlateNumber( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/swEquipmentRelUser/findByPlateNumber", - @Body param: BindParam + @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/getMemberRefPlateByPlateNumber", + @Query("plateNumber") plateNumber: String ): ApiResponse + + + /** * 获取人脸增量数据 * * @param timeDate 时间戳(毫秒级) */ - @GET//("/shuwei-zhct/scales/getHeartbeatInterface") - suspend fun getHeartbeatInterface( - @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/getHeartbeatInterface", - @Query("timeDate") timeDate: Long - ): ApiResponse> +// @GET//("/shuwei-zhct/scales/getHeartbeatInterface") +// suspend fun getHeartbeatInterface( +// @Url url: String = "${GlobalData.appBaseUrl}/shuwei-zhct/scales/getHeartbeatInterface", +// @Query("timeDate") timeDate: Long +// ): ApiResponse> + + /** + * 获取人脸增量数据 + */ + @POST("/terminal/neglect/common/app/faceFeature/increment/list") + suspend fun getFaceIncrementList(@Body param:Map): ApiResponse?> } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/network/interceptor/RequestInterceptor.kt b/app/src/main/java/com/sw/platecabinet/network/interceptor/RequestInterceptor.kt index 7886682..889da38 100644 --- a/app/src/main/java/com/sw/platecabinet/network/interceptor/RequestInterceptor.kt +++ b/app/src/main/java/com/sw/platecabinet/network/interceptor/RequestInterceptor.kt @@ -2,6 +2,7 @@ package com.sw.platecabinet.network.interceptor import com.sw.inbound.utils.SPUtil import com.sw.plate.App +import com.sw.platecabinet.GlobalData import com.sw.platecabinet.GlobalKey import okhttp3.Interceptor import okhttp3.Response @@ -17,6 +18,9 @@ class RequestInterceptor : Interceptor { .header("Accept", "application/json") // .header("Authorization", "Bearer ${getToken()}") .header("Authorization", getToken()) + .header("X-Access-Token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjYW50ZWVuSWQiOiJiZTE1NDgzMS0zNDY2LTNiYTItYTJlYS01NzY1MmM5MTlmZWQiLCJ0eXBlIjoiNCIsInVzZXJJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDEifQ.sN40cOC-O5WQFrF4IDUs8fFlkNdUKLbJt_rHyTsgYYM") + .header("X-DEVICE-CODE", GlobalData.deviceId) + .header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d") val newRequest = requestBuilder.build() diff --git a/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt b/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt index 15f097a..27c3908 100644 --- a/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt +++ b/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt @@ -47,58 +47,58 @@ class HeartBeatTask(appContext: Context, workerParams: WorkerParameters) : private val faceApi: FaceApi = FaceApi() private suspend fun performSync() { - withContext(Dispatchers.IO) { - val faceUpdateTimeStamp = PrefUtils.getLong(App.getContext(), "faceUpdateTimeStamp", 0) - if (faceUpdateTimeStamp == 0L) { - val timestamp = System.currentTimeMillis() - PrefUtils.setLong(App.getContext(), "faceUpdateTimeStamp", timestamp) - } - val resp = repository.getHeartbeatInterface( - PrefUtils.getLong( - App.getContext(), - "faceUpdateTimeStamp", - 0 - ) - ) - Timber.tag(TAG).d("performSync: ${GsonUtils.toJson(resp)}") - val list = resp.data - if (list.isNullOrEmpty()) { - return@withContext - } - val faceServer = FaceServer.getInstance() - val faceEngine: FaceEngine? = faceServer.faceEngine - - list.forEachIndexed { index, it -> - try { - if (index == list.size - 1) { - PrefUtils.setLong( - App.getContext(), - "faceUpdateTimeStamp", - it.updateTimeStamp - ) - } - if (it.faceType == "1") { - if (it.userId.isNullOrBlank().not()) { - //userId非空,根据userId删除人脸数据 - faceApi.deleteByUserName(it.userId) - faceEngine?.removeFaceFeature(it.userId.toInt()) - } - } else if (it.faceType == "0") { - //新增人脸数据 - val featureData = Base64.decode(it.faceFeature) - val insertEntity = FaceEntity(it.userId, null, featureData) - val faceId = faceApi.insert(insertEntity) - insertEntity.faceId = faceId -// faceServer.registerFaceFeatureInfoFromDb(insertEntity, faceEngine) - - EventBus.getDefault().post(insertEntity) -// callback(insertEntity) - } - } catch (e: Exception) { - e.printStackTrace() - } - } - } +// withContext(Dispatchers.IO) { +// val faceUpdateTimeStamp = PrefUtils.getLong(App.getContext(), "faceUpdateTimeStamp", 0) +// if (faceUpdateTimeStamp == 0L) { +// val timestamp = System.currentTimeMillis() +// PrefUtils.setLong(App.getContext(), "faceUpdateTimeStamp", timestamp) +// } +// val resp = repository.getHeartbeatInterface( +// PrefUtils.getLong( +// App.getContext(), +// "faceUpdateTimeStamp", +// 0 +// ) +// ) +// Timber.tag(TAG).d("performSync: ${GsonUtils.toJson(resp)}") +// val list = resp.data +// if (list.isNullOrEmpty()) { +// return@withContext +// } +// val faceServer = FaceServer.getInstance() +// val faceEngine: FaceEngine? = faceServer.faceEngine +// +// list.forEachIndexed { index, it -> +// try { +// if (index == list.size - 1) { +// PrefUtils.setLong( +// App.getContext(), +// "faceUpdateTimeStamp", +// it.updateTimeStamp +// ) +// } +// if (it.faceType == "1") { +// if (it.userId.isNullOrBlank().not()) { +// //userId非空,根据userId删除人脸数据 +// faceApi.deleteByUserName(it.userId) +// faceEngine?.removeFaceFeature(it.userId.toInt()) +// } +// } else if (it.faceType == "0") { +// //新增人脸数据 +// val featureData = Base64.decode(it.faceFeature) +// val insertEntity = FaceEntity(it.userId, null, featureData) +// val faceId = faceApi.insert(insertEntity) +// insertEntity.faceId = faceId +//// faceServer.registerFaceFeatureInfoFromDb(insertEntity, faceEngine) +// +// EventBus.getDefault().post(insertEntity) +//// callback(insertEntity) +// } +// } catch (e: Exception) { +// e.printStackTrace() +// } +// } +// } } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/repository/RemoteRepository.kt b/app/src/main/java/com/sw/platecabinet/repository/RemoteRepository.kt index e23addd..30725f7 100644 --- a/app/src/main/java/com/sw/platecabinet/repository/RemoteRepository.kt +++ b/app/src/main/java/com/sw/platecabinet/repository/RemoteRepository.kt @@ -19,50 +19,55 @@ class RemoteRepository constructor( private val apiService: ApiService ) : BaseRepository() { - /** - * 生成token - */ - suspend fun getDeviceToken(qrcodeId: String): ApiResponse { - return safeApiCall { - apiService.getDeviceToken( - qrcodeId - ) - } - } - - /** - * 获取设备信息 - */ - suspend fun getDeviceInfo(equipmentCode: String, token: String): ApiResponse { - return safeApiCall { - apiService.getDeviceInfo( - equipmentCode, - token = token - ) - } - } - - /** - * 生成token - */ - suspend fun generateToken(deviceId: String): ApiResponse { - return safeApiCall { - apiService.generateToken( - deviceId = deviceId, - appVersion = GlobalData.appVersion, - equipmentCode = GlobalData.globalEquipmentCode - ) - } - } +// /** +// * 生成token +// */ +// suspend fun getDeviceToken(qrcodeId: String): ApiResponse { +// return safeApiCall { +// apiService.getDeviceToken( +// qrcodeId +// ) +// } +// } +// +// /** +// * 获取设备信息 +// */ +// suspend fun getDeviceInfo(equipmentCode: String, token: String): ApiResponse { +// return safeApiCall { +// apiService.getDeviceInfo( +// equipmentCode, +// token = token +// ) +// } +// } +// +// /** +// * 生成token +// */ +// suspend fun generateToken(deviceId: String): ApiResponse { +// return safeApiCall { +// apiService.generateToken( +// deviceId = deviceId, +// appVersion = GlobalData.appVersion, +// equipmentCode = GlobalData.globalEquipmentCode +// ) +// } +// } /** * 获取人脸数据 */ - suspend fun getUserFaceCache(): ApiResponse> { + suspend fun getUserFaceCache( + pageNum: Int, + pageSize: Int = 100, + ): ApiResponse> { return safeApiCall { apiService.getUserFaceCache( - appVersion = GlobalData.appVersion, - equipmentCode = GlobalData.globalEquipmentCode + param = mapOf( + "pageNum" to pageNum, + "pageSize" to pageSize + ) ) } } @@ -77,15 +82,23 @@ class RemoteRepository constructor( /** * 获取设备绑定用户列表 */ - suspend fun getEquipmentList(param: EquipmentParam): ApiResponse> { - return safeApiCall { apiService.getEquipmentList(param = param) } + suspend fun getEquipmentList(): ApiResponse> { + return safeApiCall { apiService.getEquipmentList() } } - /** - * 餐盘用户信息绑定解绑 - */ - suspend fun bindEquipment(param: BindParam): ApiResponse { - return safeApiCall { apiService.bindEquipment(param = param) } +// /** +// * 餐盘用户信息绑定解绑 +// */ +// suspend fun bindEquipment(param: BindParam): ApiResponse { +// return safeApiCall { apiService.bindEquipment(param = param) } +// } + + suspend fun plateBind(param: BindParam): ApiResponse { + return safeApiCall { apiService.plateBind(param = param) } + } + + suspend fun plateUnbind(id: Int): ApiResponse { + return safeApiCall { apiService.plateUnbind(id = id) } } /** @@ -98,8 +111,8 @@ class RemoteRepository constructor( /** * 通过餐盘编号获取绑定信息 */ - suspend fun findByPlateNumber(param: BindParam): ApiResponse { - return safeApiCall { apiService.findByPlateNumber(param = param) } + suspend fun findByPlateNumber(plateNumber: String): ApiResponse { + return safeApiCall { apiService.findByPlateNumber(plateNumber = plateNumber) } } /** @@ -107,7 +120,23 @@ class RemoteRepository constructor( * * @param timeDate 时间戳(毫秒级) */ - suspend fun getHeartbeatInterface(timeDate: Long): ApiResponse> { - return safeApiCall { apiService.getHeartbeatInterface(timeDate = timeDate) } +// suspend fun getHeartbeatInterface(timeDate: Long): ApiResponse> { +// return safeApiCall { apiService.getHeartbeatInterface(timeDate = timeDate) } +// } + + suspend fun getFaceIncrementList( + pageNum: Long, + pageSize: Long = 100L, + timestamp: Long + ): ApiResponse?> { + return safeApiCall { + apiService.getFaceIncrementList( + param = mapOf( + "pageNum" to pageNum, + "pageSize" to pageSize, + "timestamp" to timestamp + ) + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/utils/IntervalExecutor.kt b/app/src/main/java/com/sw/platecabinet/utils/IntervalExecutor.kt new file mode 100644 index 0000000..230994a --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/IntervalExecutor.kt @@ -0,0 +1,66 @@ +package com.sw.platecabinet.utils + +import kotlinx.coroutines.* +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch + +class IntervalExecutor { + + /** + * 启动定时任务 + * @param delayMillis 延迟时间(毫秒) + * @param action 要执行的方法 + * @return Job 可用于取消任务 + */ + fun startIntervalTask(delayMillis: Long, action: suspend () -> Unit): Job { + return CoroutineScope(Dispatchers.Default).launch { + while (isActive) { + action() + delay(delayMillis) + } + } + } + + /** + * 启动定时任务(带初始延迟) + * @param initialDelay 初始延迟时间(毫秒) + * @param delayMillis 后续执行间隔(毫秒) + * @param action 要执行的方法 + * @return Job 可用于取消任务 + */ + fun startIntervalTaskWithInitialDelay( + initialDelay: Long, + delayMillis: Long, + action: suspend () -> Unit + ): Job { + return CoroutineScope(Dispatchers.Default).launch { + delay(initialDelay) + while (isActive) { + action() + delay(delayMillis) + } + } + } +} + +// 使用示例 +fun main() = runBlocking { + val executor = IntervalExecutor() + + // 示例1:每隔10秒执行一次 + val job1 = executor.startIntervalTask(10000) { + println("定时任务执行: ${System.currentTimeMillis()}") + // 这里可以执行你的业务逻辑 + } + + // 示例2:先延迟5秒,然后每隔3秒执行一次 + val job2 = executor.startIntervalTaskWithInitialDelay(5000, 3000) { + println("带初始延迟的定时任务: ${System.currentTimeMillis()}") + } + + // 运行30秒后取消任务 + delay(30000) + job1.cancel() + job2.cancel() + println("所有定时任务已取消") +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/utils/SpTool.java b/app/src/main/java/com/sw/platecabinet/utils/SpTool.java new file mode 100644 index 0000000..e6ab899 --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/SpTool.java @@ -0,0 +1,20 @@ +package com.sw.platecabinet.utils; + +import com.sw.inbound.utils.SPUtil; +import com.sw.platecabinet.MyApp; + +public class SpTool { + + public static final String LAST_FACE_TIMESTAMP = "faceTimestamp"; + + public static long getLastFaceTimestamp() { + return SPUtil.Companion.getInstance(MyApp.getContext(), "default_sp").get(LAST_FACE_TIMESTAMP, 0L); + } + + public static void setLastFaceTimestamp(long timestamp) { + SPUtil.Companion.getInstance(MyApp.getContext(), "default_sp").put(LAST_FACE_TIMESTAMP, timestamp); + } + + + +} diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/BaseViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/BaseViewModel.kt index 1eabb62..7ced9c2 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/BaseViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/BaseViewModel.kt @@ -67,10 +67,10 @@ abstract class BaseViewModel() : ViewModel() { fun parseEquipmentInfo(equipmentInfo: EquipmentInfo) { // GlobalData.appBaseUrl = equipmentInfo.appPackageUrl!! - GlobalData.appBaseUrl="https://vip.shuziweidao.com" +// GlobalData.appBaseUrl="https://vip.shuziweidao.com" // GlobalData.sdkKey = equipmentInfo.arcsoftSdkKey!! // GlobalData.appId = equipmentInfo.arcsoftAppId!! // GlobalData.activeKey = equipmentInfo.arcsoftActiveKey!! - GlobalData.restId = equipmentInfo.canteenId!! +// GlobalData.restId = equipmentInfo.canteenId!! } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/DeviceViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/DeviceViewModel.kt index e31fde6..f5a498a 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/DeviceViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/DeviceViewModel.kt @@ -1,68 +1,68 @@ -package com.sw.platecabinet.viewmodel - -import com.sw.inbound.utils.GsonUtils -import com.sw.inbound.utils.SPUtil -import com.sw.platecabinet.GlobalData -import com.sw.platecabinet.GlobalKey -import com.sw.platecabinet.model.response.EquipmentInfo -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import timber.log.Timber -import kotlin.jvm.java - -/** - * 初始化的viewmodel - */ -class DeviceViewModel : BaseViewModel() { - private val _deviceInfoResult = MutableStateFlow(null) - val deviceInfoResult: StateFlow = _deviceInfoResult - - /** - * 获取token - */ - fun getDeviceToken(deviceId: String = GlobalData.deviceId) { - launchWithLoading { - val response = repository.getDeviceToken(deviceId) - if (parseResponse(response)) { - val response1 = repository.getDeviceInfo(deviceId, response.result!!) - - if (parseResponse(response1)) { - val equipmentInfo = response1.result - if (equipmentInfo == null) return@launchWithLoading - try { - parseEquipmentInfo(equipmentInfo) - SPUtil.getInstance() - .put(GlobalKey.KEY_EQUIPMENT_INFO, GsonUtils.toJson(equipmentInfo)) - _deviceInfoResult.value = true - } catch (e: Exception) { - Timber.e(e) - } - } - } - } - } - - /** - * 检查缓存数据 - */ - fun checkEquipmentInfo(): Boolean { - val equipmentInfoStr = SPUtil.getInstance().get(GlobalKey.KEY_EQUIPMENT_INFO, "") - if (equipmentInfoStr == null) { - Timber.e("获取缓存设备信息失败") - return false - } - val equipmentInfo = - GsonUtils.fromJson(equipmentInfoStr, EquipmentInfo::class.java) - if (equipmentInfo == null) { - Timber.e("解析缓存设备信息失败") - return false - } - try { - parseEquipmentInfo(equipmentInfo) - return true - } catch (e: Exception) { - Timber.e(e) - return false - } - } -} \ No newline at end of file +//package com.sw.platecabinet.viewmodel +// +//import com.sw.inbound.utils.GsonUtils +//import com.sw.inbound.utils.SPUtil +//import com.sw.platecabinet.GlobalData +//import com.sw.platecabinet.GlobalKey +//import com.sw.platecabinet.model.response.EquipmentInfo +//import kotlinx.coroutines.flow.MutableStateFlow +//import kotlinx.coroutines.flow.StateFlow +//import timber.log.Timber +//import kotlin.jvm.java +// +///** +// * 初始化的viewmodel +// */ +//class DeviceViewModel : BaseViewModel() { +// private val _deviceInfoResult = MutableStateFlow(null) +// val deviceInfoResult: StateFlow = _deviceInfoResult +// +// /** +// * 获取token +// */ +// fun getDeviceToken(deviceId: String = GlobalData.deviceId) { +// launchWithLoading { +// val response = repository.getDeviceToken(deviceId) +// if (parseResponse(response)) { +// val response1 = repository.getDeviceInfo(deviceId, response.result!!) +// +// if (parseResponse(response1)) { +// val equipmentInfo = response1.result +// if (equipmentInfo == null) return@launchWithLoading +// try { +// parseEquipmentInfo(equipmentInfo) +// SPUtil.getInstance() +// .put(GlobalKey.KEY_EQUIPMENT_INFO, GsonUtils.toJson(equipmentInfo)) +// _deviceInfoResult.value = true +// } catch (e: Exception) { +// Timber.e(e) +// } +// } +// } +// } +// } +// +// /** +// * 检查缓存数据 +// */ +// fun checkEquipmentInfo(): Boolean { +// val equipmentInfoStr = SPUtil.getInstance().get(GlobalKey.KEY_EQUIPMENT_INFO, "") +// if (equipmentInfoStr == null) { +// Timber.e("获取缓存设备信息失败") +// return false +// } +// val equipmentInfo = +// GsonUtils.fromJson(equipmentInfoStr, EquipmentInfo::class.java) +// if (equipmentInfo == null) { +// Timber.e("解析缓存设备信息失败") +// return false +// } +// try { +// parseEquipmentInfo(equipmentInfo) +// return true +// } catch (e: Exception) { +// Timber.e(e) +// return false +// } +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt index da8fef2..268eb05 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt @@ -9,16 +9,21 @@ import com.sw.platecabinet.model.request.EquipmentParam import com.sw.platecabinet.model.request.SearchParam import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.model.response.SearchResult +import com.sw.platecabinet.model.response.UserFaceModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import timber.log.Timber /** * 管理员操作viewmodel */ class SettingViewModel : BaseViewModel() { // 设备绑定列表 - private val _equipmentList = MutableStateFlow>(emptyList()) - val equipmentList: StateFlow> = _equipmentList +// private val _equipmentList = MutableStateFlow>(emptyList()) +// val equipmentList: StateFlow> = _equipmentList private val _searchMemberList = MutableStateFlow>(emptyList()) val searchMemberList: StateFlow> = _searchMemberList @@ -33,27 +38,36 @@ class SettingViewModel : BaseViewModel() { /** * 绑定/解绑状态 <绑定/解绑, 错误信息,> */ - private val _bindStateChange = MutableStateFlow>(null to ErrorInfo()) - val bindStateChange: StateFlow> = _bindStateChange +// private val _bindStateChange = MutableStateFlow>(null to ErrorInfo()) +// val bindStateChange: StateFlow> = _bindStateChange /** * 获取设备绑定用户信息列表 */ - fun getEquipmentList(equipmentCode: String = globalEquipmentCode) { +// fun getEquipmentList(equipmentCode: String = globalEquipmentCode) { +// launchWithLoading { +// val param = +// EquipmentParam(appVersion = GlobalData.appVersion, equipmentCode = equipmentCode) +// val response = repository.getEquipmentList(param) +// if (parseResponse(response)) { +// _equipmentList.value = response.data ?: emptyList() +// } +// } +//// val list = mutableListOf() +//// for (i in 1 .. 30){ +//// list.add(EquipmentUserInfo(id = i, equipmentBoxCode = i.toString())) +//// } +//// _equipmentList.value = list +// } + fun getEquipmentList(block: (List) -> Unit) { launchWithLoading { - val param = - EquipmentParam(appVersion = GlobalData.appVersion, equipmentCode = equipmentCode) - val response = repository.getEquipmentList(param) + val response = repository.getEquipmentList() if (parseResponse(response)) { - _equipmentList.value = response.data ?: emptyList() + val list = response.data ?: emptyList() + block(list) } } -// val list = mutableListOf() -// for (i in 1 .. 30){ -// list.add(EquipmentUserInfo(id = i, equipmentBoxCode = i.toString())) -// } -// _equipmentList.value = list } /** @@ -86,52 +100,81 @@ class SettingViewModel : BaseViewModel() { } } - fun bindPlate( - equipmentBoxCode: String, - equipmentCode: String = globalEquipmentCode, - memberId: Int, - plateNumber: String - ) { - _bindStateChange.value = null to ErrorInfo() +// fun bindPlate( +// equipmentBoxCode: String, +// equipmentCode: String = globalEquipmentCode, +// memberId: Int, +// plateNumber: String +// ) { +// _bindStateChange.value = null to ErrorInfo() +// launchWithLoading { +// val bindParam = BindParam( +// appVersion = GlobalData.appVersion, +// equipmentBoxCode = equipmentBoxCode, +// equipmentCode = equipmentCode, +// memberId = memberId, +// plateNumber = plateNumber +// ) +// val response = repository.bindEquipment(bindParam) +// if (parseResponse(response)) { +// var userInfo = response.data +// if (userInfo == null) { +// userInfo = EquipmentUserInfo() +// userInfo.equipmentBoxCode = equipmentBoxCode +// userInfo.plateNumber = plateNumber +// userInfo.equipmentCode = equipmentCode +// } +// _bindStateChange.value = true to ErrorInfo(equipmentUserInfo = userInfo) +// } else { +// _bindStateChange.value = true to ErrorInfo(response.code, response.msg.toString()) +// } +// } +// } +// fun unbindPlate( +// equipmentBoxCode: String, +// equipmentCode: String = globalEquipmentCode +// ) { +// launchWithLoading { +// val bindParam = BindParam( +// appVersion = GlobalData.appVersion, +// equipmentBoxCode = equipmentBoxCode, +// equipmentCode = equipmentCode +// ) +// val response = repository.bindEquipment(bindParam) +// if (parseResponse(response)) { +// _bindStateChange.value = false to ErrorInfo() +// } else { +// _bindStateChange.value = false to ErrorInfo(response.code, response.msg.toString()) +// } +// } +// } + + fun unbindPlate(id: Int, block:(Pair)-> Unit) { + block(null to ErrorInfo()) launchWithLoading { - val bindParam = BindParam( - appVersion = GlobalData.appVersion, - equipmentBoxCode = equipmentBoxCode, - equipmentCode = equipmentCode, - memberId = memberId, - plateNumber = plateNumber - ) - val response = repository.bindEquipment(bindParam) + val response = repository.plateUnbind(id) if (parseResponse(response)) { - var userInfo = response.data - if (userInfo == null) { - userInfo = EquipmentUserInfo() - userInfo.equipmentBoxCode = equipmentBoxCode - userInfo.plateNumber = plateNumber - userInfo.equipmentCode = equipmentCode - } - _bindStateChange.value = true to ErrorInfo(equipmentUserInfo = userInfo) + block(false to ErrorInfo()) } else { - _bindStateChange.value = true to ErrorInfo(response.code, response.msg.toString()) + block(false to ErrorInfo(response.code, response.msg.toString())) } } } - fun unbindPlate( - equipmentBoxCode: String, - equipmentCode: String = globalEquipmentCode - ) { + fun bindPlate(bindParam: BindParam, block:(Pair)-> Unit) { launchWithLoading { - val bindParam = BindParam( - appVersion = GlobalData.appVersion, - equipmentBoxCode = equipmentBoxCode, - equipmentCode = equipmentCode - ) - val response = repository.bindEquipment(bindParam) + val response = repository.plateBind(bindParam) if (parseResponse(response)) { - _bindStateChange.value = false to ErrorInfo() + var userInfo = response.data + if (userInfo == null) { + userInfo = EquipmentUserInfo() + userInfo.equipmentBoxCode = bindParam.equipmentBoxCode + userInfo.plateNumber = bindParam.plateNumber + userInfo.equipmentCode = bindParam.equipmentCode + } + block(true to ErrorInfo(equipmentUserInfo = userInfo)) } else { - _bindStateChange.value = false to ErrorInfo(response.code, response.msg.toString()) + block(true to ErrorInfo(response.code, response.msg.toString())) } } } @@ -142,12 +185,8 @@ class SettingViewModel : BaseViewModel() { ) { _searchUserInfo.value = null launchWithLoading { - val bindParam = BindParam( - appVersion = GlobalData.appVersion, - plateNumber = plateNumber, - equipmentCode = equipmentCode - ) - val response = repository.findByPlateNumber(bindParam) +// val bindParam = BindParam(plateNumber = plateNumber) + val response = repository.findByPlateNumber(plateNumber) if (response.code == 200) { _searchUserInfo.value = response.data } else { @@ -159,4 +198,31 @@ class SettingViewModel : BaseViewModel() { } } } + + val PAGE_SIZE = 100 + + /** + * 获取人脸数据 + */ + fun getFaceIncrementList( + pageNo: Int = 1, + pageSize: Int = PAGE_SIZE, + timestamp: Long, + block: (List) -> Unit + ) { + launch { + val response = repository.getFaceIncrementList( + pageNum = pageNo.toLong(), + pageSize = pageSize.toLong(), + timestamp = timestamp + ) + if (parseResponse(response)) { + withContext(Dispatchers.Default) { + val list: List = response.data ?: emptyList() + block(list) + } + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt index d9cc770..fdd3e9c 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt @@ -14,6 +14,7 @@ import com.sw.platecabinet.GlobalKey import com.sw.platecabinet.model.request.LoginParam import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.model.response.UserFaceModel +import com.sw.platecabinet.utils.SpTool import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -25,6 +26,11 @@ import timber.log.Timber * 用户viewmodel */ class UserViewModel : BaseViewModel() { + + companion object { + const val PAGE_SIZE = 100 + } + // 通过人脸获取到的用户信息 private val _currentUserInfo = MutableStateFlow(null) val currentUserInfo: StateFlow = _currentUserInfo @@ -34,36 +40,46 @@ class UserViewModel : BaseViewModel() { /** * 获取token */ - fun generateToken(deviceId: String = "SWSN:88:12:AC:4E:D9:CC") { - launchWithLoading { - val response = repository.generateToken(deviceId) - if (parseResponse(response)) { - // 缓存token - SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, response.data) - // 首次运行获取人脸数据 - if (SPUtil.getInstance().get(GlobalKey.KEY_FIRST_RUN, false) != true) { - getUserFaceCache() - } - } - } - } +// fun generateToken(deviceId: String = "SWSN:88:12:AC:4E:D9:CC") { +// launchWithLoading { +// val response = repository.generateToken(deviceId) +// if (parseResponse(response)) { +// // 缓存token +// SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, response.data) +// // 首次运行获取人脸数据 +// if (SPUtil.getInstance().get(GlobalKey.KEY_FIRST_RUN, false) != true) { +// getUserFaceCache() +// } +// } +// } +// } /** * 获取人脸数据 */ - fun getUserFaceCache(index: Int = 0) { + fun getUserFaceCache(pageNo: Int = 1, pageSize: Int = PAGE_SIZE) { + var currentPageNo = pageNo launchWithLoading { - val response = repository.getUserFaceCache() + val response = repository.getUserFaceCache(pageNum = pageNo, pageSize = pageSize) if (parseResponse(response)) { // 获取成功一次后缓存状态 SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true) val list: List = response.data ?: emptyList() - val faceEntity = list.map { - FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString)) + if (list.isEmpty()) { + return@launchWithLoading + } + + SpTool.setLastFaceTimestamp(System.currentTimeMillis()) + val faceEntityList = list.map { + FaceEntity(it.userId, null, Base64.decode(it.faceFeatureStr)) } withContext(Dispatchers.Default) { - faceApi.updateFaceData(index, faceEntity) - activeEngine() + faceApi.updateFaceData(pageNo, faceEntityList) + if (list.size >= pageSize) { + currentPageNo++ + getUserFaceCache(currentPageNo) + } + //activeEngine() } } } @@ -112,14 +128,8 @@ class UserViewModel : BaseViewModel() { /** * 校验码登录 */ - fun loginWithPwd(equipmentCode: String = globalEquipmentCode, phone: String, password: String) { + fun loginWithPwd(loginParam: LoginParam) { launchWithLoading { - val loginParam = LoginParam( - appVersion = GlobalData.appVersion, - equipmentCode = equipmentCode, - phone = phone, - password = password - ) val response = repository.equipmentBoxLogin(loginParam) if (parseResponse(response)) { _currentUserInfo.value = response.data @@ -130,14 +140,10 @@ class UserViewModel : BaseViewModel() { /** * 通过用户id获取用户信息 */ - fun getUserInfoById(equipmentCode: String = globalEquipmentCode, memberId: Int, action:(EquipmentUserInfo?)->Unit={}) { + fun getUserInfoById(memberId: Int?, action:(EquipmentUserInfo?)->Unit={}) { _currentUserInfo.value = null launchWithLoading { - val loginParam = LoginParam( - appVersion = GlobalData.appVersion, - equipmentCode = equipmentCode, - memberId = memberId - ) + val loginParam = LoginParam(memberId = memberId) val response = repository.equipmentBoxLogin(loginParam) if (parseResponse(response)) { _currentUserInfo.value = response.data diff --git a/lib_face/build.gradle.kts b/lib_face/build.gradle.kts index 8ff6f19..82ea7ec 100644 --- a/lib_face/build.gradle.kts +++ b/lib_face/build.gradle.kts @@ -55,7 +55,7 @@ dependencies { implementation("com.licheedev:android-serialport:2.1.5") val roomVersion = "2.2.5" - implementation("androidx.room:room-runtime:$roomVersion") + api("androidx.room:room-runtime:$roomVersion") annotationProcessor("androidx.room:room-compiler:$roomVersion") implementation("io.reactivex.rxjava2:rxandroid:2.0.1") diff --git a/lib_face/src/main/java/com/sw/plate/utils/arcface/FaceApi.java b/lib_face/src/main/java/com/sw/plate/utils/arcface/FaceApi.java index 6af7ba9..acd2b22 100644 --- a/lib_face/src/main/java/com/sw/plate/utils/arcface/FaceApi.java +++ b/lib_face/src/main/java/com/sw/plate/utils/arcface/FaceApi.java @@ -33,7 +33,7 @@ public class FaceApi { public void updateFaceData(int index, List list) { Log.d(TAG, "updateFaceData: index = " + index + ", listSize = " + list.size()); FaceDao faceDao = FaceDatabase.getInstance(App.getContext()).faceDao(); - if (index == 0) { + if (index == 1) { faceDao.deleteAll(); faceDao.resetId(); }