Files
SmartPlateCabinet/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt
T
2026-01-22 15:49:36 +08:00

866 lines
33 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.sw.platecabinet.activity
import android.Manifest
import android.content.Intent
import android.graphics.Point
import android.hardware.Camera
import android.os.Build
import android.os.CountDownTimer
import android.util.DisplayMetrics
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.annotation.RequiresApi
import androidx.lifecycle.Observer
import com.arcsoft.face.ErrorInfo
import com.google.gson.Gson
import com.sw.platecabinet.socket.TcpClientListenerImpl
import com.sw.inbound.utils.DateTimeUtils
import com.sw.plate.utils.Base64
import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.arcface.ConfigUtil
import com.sw.plate.utils.arcface.ErrorCodeUtil
import com.sw.plate.utils.arcface.FaceRectTransformer
import com.sw.plate.utils.arcface.FaceRectView
import com.sw.plate.utils.arcface.FaceRectView.DrawInfo
import com.sw.plate.utils.arcface.PreviewConfig
import com.sw.plate.utils.arcface.camera.CameraListener
import com.sw.plate.utils.arcface.camera.DualCameraHelper
import com.sw.plate.utils.arcface.face.constants.LivenessType
import com.sw.plate.utils.arcface.face.model.CompareResult
import com.sw.plate.utils.arcface.face.model.FacePreviewInfo
import com.sw.plate.utils.arcface.face.model.RecognizeConfiguration
import com.sw.plate.utils.arcface.facedb.FaceDatabase
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
import com.sw.plate.utils.arcface.model.UserFaceInfo
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel.REGISTER_STATUS_READY
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.MyApp
import com.sw.platecabinet.R
import com.sw.platecabinet.databinding.ActivityLoginFaceBinding
import com.sw.platecabinet.databinding.ItemTitleTimeBinding
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.socket.LanServer
import com.sw.platecabinet.socket.LanServerListenerImpl
import com.sw.platecabinet.socket.TcpClient
import com.sw.platecabinet.utils.Debouncer
import com.sw.platecabinet.utils.PermissionHelper
import com.sw.platecabinet.utils.PlateUtils
import com.sw.platecabinet.utils.SoundPoolUtil
import com.sw.platecabinet.utils.SpTool
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import timber.log.Timber
/**
* 人脸识别
*/
class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
ViewTreeObserver.OnGlobalLayoutListener {
// private val recognizeViewModel by viewModels<RecognizeViewModel>()
private var countDownTimer: CountDownTimer? = null
private val CAMERA_PERMISSION_REQUEST_CODE = 100
private val REQUIRED_PERMISSIONS: Array<String> = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
override fun inflateViewBinding(): ActivityLoginFaceBinding {
return ActivityLoginFaceBinding.inflate(layoutInflater)
}
override fun inflateTitleBinding(): ItemTitleTimeBinding {
return binding.includeHeader
}
companion object {
private const val TAG = "LoginByFaceActivity"
private var instance: LoginByFaceActivity? = null
private const val COLLECT_SUCCESS = "collect_success"
private const val RECOGNIZE_SUCCESS = "recognize_success"
private const val NO_PLATE_REMIND = "no_plate_remind";
fun goInitActivity() {
instance?.goInitActivity()
}
}
// private var logList: MutableList<String> = mutableListOf()
// private val logAdapter by lazy { LogAdapter(logList) }
override fun initialize() {
instance = this
viewModel.activeEngine()
addSocketListener()
initCountTime()
initArcViewModel()
initArcView()
openRectInfoDraw = true
recognizeViewModel.setDrawRectInfoTextValue(true)
//viewModel.generateToken()
// viewModel.activeEngine()
// binding.llToPwd.setOnClickListener {
// val intent = Intent(this, LoginByPwdActivity::class.java)
// startActivity(intent)
// }
// TaskManager.startTask()
EventBus.getDefault().register(this)
// binding.btnCollectFace.setOnClickListener { collectFace() }
// binding.rvLogInfo.let {
// it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)
// it.adapter = logAdapter
// }
//
// binding.btnLogState.let {
// it.tag = false
// it.setImageResource(R.drawable.ic_log_show)
// it.setOnClickListener { v ->
// binding.rvLogInfo.run {
// val state = it.tag.toString().toBooleanStrictOrNull() ?: false
// if (state) visible() else gone()
// }
// val state = it.tag.toString().toBooleanStrictOrNull() ?: false
// it.tag = state
// it.setImageResource(
// if (state) R.drawable.ic_log_hide else R.drawable.ic_log_show
// )
// }
// }
val soundMap = hashMapOf<String, Int>()
soundMap[COLLECT_SUCCESS] = R.raw.collect_success
soundMap[RECOGNIZE_SUCCESS] = R.raw.recognize_success
soundMap[NO_PLATE_REMIND] = R.raw.no_plate_remind
SoundPoolUtil.getInstance().loadR(this, soundMap);
}
private fun checkCameraPermission() {
Timber.i("checkCameraPermission")
val permissionHelper =
PermissionHelper.with(this, REQUIRED_PERMISSIONS, CAMERA_PERMISSION_REQUEST_CODE)
.onGranted {
loadLogInfo("checkCameraPermission 权限已允许")
// 权限已授予
recognizeViewModel.init()
initRgbCamera()
resumeCamera()
}
.build()
registerPermissionHelper(permissionHelper)
permissionHelper.checkAndRequest()
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun getFaceEntity(insertEntity: FaceEntity) {
Timber.tag("performSync").e("-time=%s", insertEntity.registerTime)
recognizeViewModel.addFace(insertEntity)
Timber.tag("performSync over").e("-time=%s", insertEntity.registerTime)
}
override fun onLeftDoubleClick() {
finish()
}
private var isRecognition = false
private var rgbCameraHelper: DualCameraHelper? = null
private var rgbFaceRectTransformer: FaceRectTransformer? = null
private val livenessType = LivenessType.RGB
private var openRectInfoDraw = false
private fun initArcViewModel() {
recognizeViewModel.setLiveType(livenessType)
recognizeViewModel.prepareRegister()
recognizeViewModel.setOnRegisterFinishedCallback { facePreviewInfo, userFaceInfo ->
if (!isCollectFace) {
return@setOnRegisterFinishedCallback
}
if (this.userFaceInfo == null && userFaceInfo != null) {
recognizeViewModel.updateRegisterStatus(RecognizeViewModel.REGISTER_STATUS_DONE)
this.userFaceInfo = userFaceInfo
getFaceDataBlock { faceData ->
isCollectFace = false
Thread {
saveFaceInfo(faceData)
}.start()
}
return@setOnRegisterFinishedCallback
}
}
recognizeViewModel.ftInitCode.observe(this, Observer { ftInitCode: Int? ->
if (ftInitCode != ErrorInfo.MOK) {
val error: String? = getString(
R.string.specific_engine_init_failed, "ftEngine",
ftInitCode, ErrorCodeUtil.arcFaceErrorCodeToFieldName(ftInitCode!!)
)
Timber.e("ftInitCode observe = $error")
ToastUtils.showToast(error)
}
})
recognizeViewModel.frInitCode.observe(this, Observer { frInitCode: Int? ->
if (frInitCode != ErrorInfo.MOK) {
val error: String? = getString(
R.string.specific_engine_init_failed, "frEngine",
frInitCode, ErrorCodeUtil.arcFaceErrorCodeToFieldName(frInitCode!!)
)
Timber.e("frInitCode observe = $error")
ToastUtils.showToast(error)
}
})
recognizeViewModel.flInitCode.observe(this, Observer { flInitCode: Int? ->
if (flInitCode != ErrorInfo.MOK) {
val error: String? = getString(
R.string.specific_engine_init_failed, "flEngine",
flInitCode, ErrorCodeUtil.arcFaceErrorCodeToFieldName(flInitCode!!)
)
Timber.e("flInitCode observe = $error")
ToastUtils.showToast(error)
}
})
recognizeViewModel.recognizeConfiguration
.observe(this, Observer { recognizeConfiguration: RecognizeConfiguration? ->
Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
})
recognizeViewModel.recognizeNotice.observe(this, Observer { notice: String? ->
Timber.i("recognizeNotice observe notice = $notice")
})
recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? ->
loadLogInfo("collectFace,recognizeUserId observe userId = ${result?.faceEntity?.userName}")
if (faceUseSwitch) {
loadFaceRecognizeResult2(result)
return@Observer
}
loadFaceRecognizeResult(result)
})
recognizeViewModel.drawRectInfoText.observe(this, Observer { info ->
Timber.i("drawRectInfoText observe info = $info")
})
}
/**
* 人脸识别开关,true-loadFaceRecognizeResult2false-loadFaceRecognizeResult
*/
private var faceUseSwitch = true
/**
* 识别失败重试次数
*/
private var retryFailCount = 0
/**
* 识别失败最大次数
*/
private val maxFailCount = 5
/**
* 人脸失败阈值
*/
private val faceFailThreshold = 0.3
/**
* 配置阈值,默认值为0.8
*/
private val faceSuccessThreshold by lazy { ConfigUtil.getRecognizeThreshold(this) }
/**
* 根据相似度similar>设定阈值0.8作为识别成功判断,
* 如果similar<0.3作为识别失败判断,
* 如果similar>=0.3&&similar<=0.8时,暂时不作为失败情况,再识别5次如果similar<0.8则作为识别失败处理
*/
private fun loadFaceRecognizeResult2(result: CompareResult?) {
val similar = result?.similar ?: 0f
binding.tvSimilarValue.text = "$similar"
loadLogInfo("collectFace,recognizeUserId 人脸识别配置阈值为:${faceSuccessThreshold},失败阈值为:${faceFailThreshold},相似度为:${similar},失败次数为:${retryFailCount}")
if (similar > faceSuccessThreshold) {
//大 于识别阈值,作为识别成功判断
currentUserId = result?.faceEntity?.userName
Debouncer(5000).debounce { openPlate(currentUserId) }
return
}
loadLogInfo("collectFace,recognizeUserId 人脸识别相似度为:${similar},失败次数为:${retryFailCount}")
if (similar < faceFailThreshold || retryFailCount >= maxFailCount) {
//小于识别错误阈值,或者识别失败次数大于等于最大失败次数,作为识别失败判断
loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集")
isCollectFace = true
collectFace()
return
}
//满足similar >= faceFailThreshold && similar <= successThreshold时进行重试
retryFailCount++
loadLogInfo("collectFace,recognizeUserId 人脸识别失败次数为:${retryFailCount}")
}
/**
* 根据相似度similar>设定阈值0.8作为识别是否成功来加载人脸识别结果
*/
private fun loadFaceRecognizeResult(result: CompareResult?) {
val similar = result?.similar ?: 0f
binding.tvSimilarValue.text = "$similar"
val similarPass = result?.isSimilarPass ?: false
if (similarPass.not()) {
loadLogInfo("collectFace,recognizeUserId 未识别到人脸信息,开始采集")
isCollectFace = true
collectFace()
return
}
currentUserId = result?.faceEntity?.userName
if (tempUserId != currentUserId) {
SoundPoolUtil.getInstance().play("success", 0)
}
// plateEnable = true
Debouncer(5000).debounce { openPlate(currentUserId) }
}
/**
* 查询餐盘数据
*/
private fun getPlateData(block: (List<EquipmentUserInfo>) -> Unit) {
MyApp.plateList?.let {
block(it)
}
}
private var currentPlateInfo: EquipmentUserInfo? = null
private var plateEnable = false
/**
* 打开餐盘柜
*/
private fun openPlate(userId: String?) {
if (plateEnable.not()) return
loadLogInfo("collectFace,openPlate: userId=$userId")
getPlateData { items ->
loadLogInfo("collectFace,openPlate: items:${Gson().toJson(items)}")
// 未查询到当前用户,查询第一个未绑定的餐盘
val item = items.firstOrNull { it.plateNumber.isNullOrEmpty().not() }
loadLogInfo("collectFace,openPlate: item2:${item}")
if (item == null) {
//暂无餐盘
loadLogInfo("collectFace,openPlate: 暂无餐盘,请联系管理人员,isCollectFace=$isCollectFace")
//ToastUtils.showToast("暂无餐盘,请联系管理人员")
SoundPoolUtil.getInstance().play(NO_PLATE_REMIND, 0)
goInitActivity()
return@getPlateData
}
if (tempUserId != currentUserId) {
SoundPoolUtil.getInstance().play(RECOGNIZE_SUCCESS, 0)
} else {
SoundPoolUtil.getInstance().play(COLLECT_SUCCESS, 0)
}
loadLogInfo("collectFace,openPlate: item3:${item}")
item.faceId = userId
item.updateTime = DateTimeUtils.getDateTimeString()
item.plateNumber = null
plateEnable = false
Debouncer(5000).debounce {
//打开柜子
PlateUtils.open(this, item.equipmentBoxCode, false)
}
currentPlateInfo = item
MyApp.plateList = items
SpTool.savePlateData(items)
}
}
// private val debouncer by lazy { Debouncer(3000) }
private fun initArcView() {
//在布局结束后才做初始化操作
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().addOnGlobalLayoutListener(this)
recognizeViewModel.getCompareResultList().getValue()
}
override fun onDestroy() {
loadLogInfo("onDestroy")
instance = null
if (rgbCameraHelper != null) {
rgbCameraHelper!!.release()
rgbCameraHelper = null
}
recognizeViewModel.destroy()
EventBus.getDefault().unregister(this)
// getFaceScheduler?.shutdown()
// checkFaceScheduler?.shutdown()
super.onDestroy()
}
/**
* 调整View的宽高,使预览显示正常且采集框固定为380x380
*
* @param rgbPreview RGB预览View
* @param previewView 显示预览数据的view
* @param faceRectView 画框的view (380x380)
* @param previewSize 预览大小
* @param displayOrientation 相机旋转角度
* @param scale 缩放比例
* @return 调整后的LayoutParams
*/
private fun adjustPreviewViewSize(
rgbPreview: View,
previewView: View,
faceRectView: FaceRectView,
previewSize: Camera.Size,
displayOrientation: Int,
scale: Float
): ViewGroup.LayoutParams {
val layoutParams = previewView.layoutParams
val measuredWidth = previewView.measuredWidth
val measuredHeight = previewView.measuredHeight
var ratio = (previewSize.height.toFloat()) / previewSize.width.toFloat()
if (ratio > 1) {
ratio = 1 / ratio
}
if (displayOrientation % 180 == 0) {
layoutParams.width = measuredWidth
layoutParams.height = (measuredWidth * ratio).toInt()
} else {
layoutParams.height = measuredHeight
layoutParams.width = (measuredHeight * ratio).toInt()
}
if (scale < 1f) {
val rgbParam = rgbPreview.getLayoutParams()
layoutParams.width = (rgbParam.width * scale).toInt()
layoutParams.height = (rgbParam.height * scale).toInt()
} else {
layoutParams.width = (layoutParams.width * scale).toInt()
layoutParams.height = (layoutParams.height * scale).toInt()
}
val metrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
if (layoutParams.width >= metrics.widthPixels) {
val viewRatio = layoutParams.width / (metrics.widthPixels.toFloat())
layoutParams.width = (layoutParams.width / viewRatio).toInt()
layoutParams.height = (layoutParams.height / viewRatio).toInt()
}
if (layoutParams.height >= metrics.heightPixels) {
val viewRatio = layoutParams.height / (metrics.heightPixels.toFloat())
layoutParams.width = (layoutParams.width / viewRatio).toInt()
layoutParams.height = (layoutParams.height / viewRatio).toInt()
}
previewView.setLayoutParams(layoutParams)
faceRectView.setLayoutParams(layoutParams)
return layoutParams
}
private fun initRgbCamera() {
val cameraListener: CameraListener = object : CameraListener {
override fun onCameraOpened(
camera: Camera,
cameraId: Int,
displayOrientation: Int,
isMirror: Boolean
) {
loadLogInfo("initRgbCamera Rgb onCameraOpened: cameraId = $cameraId, displayOrientation = $displayOrientation")
runOnUiThread({
val previewSizeRgb = camera.getParameters().getPreviewSize()
val layoutParams = adjustPreviewViewSize(
binding.dualCameraTexturePreviewRgb,
binding.dualCameraTexturePreviewRgb, binding.dualCameraFaceRectView,
previewSizeRgb, displayOrientation, 0.6f
)
loadLogInfo("initRgbCamera previewSizeRgb = ${previewSizeRgb.width}-${previewSizeRgb.height}")
loadLogInfo("initRgbCamera layoutParams = ${layoutParams.width}-${layoutParams.height}")
loadLogInfo(
"initRgbCamera isMirror = ${isMirror}, isDrawRgbRectHorizontalMirror = ${
ConfigUtil.isDrawRgbRectHorizontalMirror(
context
)
}, isDrawRgbRectVerticalMirror = ${
ConfigUtil.isDrawRgbRectVerticalMirror(
context
)
}"
)
rgbFaceRectTransformer = FaceRectTransformer(
previewSizeRgb.width,
previewSizeRgb.height,
layoutParams.width,
layoutParams.height,
90,
cameraId,
isMirror,
true,
true
)
recognizeViewModel.onRgbCameraOpened(camera)
recognizeViewModel.setRgbFaceRectTransformer(rgbFaceRectTransformer)
})
}
@RequiresApi(api = Build.VERSION_CODES.Q)
override fun onPreview(nv21: ByteArray?, camera: Camera?) {
if (!isRecognition) {
return
}
binding.dualCameraFaceRectView.clearFaceInfo()
facePreviewInfoList = recognizeViewModel.onPreviewFrame(nv21, true)
if (facePreviewInfoList != null && rgbFaceRectTransformer != null) {
drawPreviewInfo(facePreviewInfoList)
}
if (facePreviewInfoList.isNullOrEmpty()) {
currentPlateInfo = null
currentUserId = null
userFaceInfo = null
}
recognizeViewModel.clearLeftFace(facePreviewInfoList)
}
override fun onCameraClosed() {
Timber.i("initRgbCamera onCameraClosed: ")
}
override fun onCameraError(e: java.lang.Exception) {
Timber.i("initRgbCamera onCameraError: %s", e.message)
e.printStackTrace()
}
override fun onCameraConfigurationChanged(cameraID: Int, displayOrientation: Int) {
Timber.i("initRgbCamera onCameraConfigurationChanged: threadName = ${Thread.currentThread().name}")
if (rgbFaceRectTransformer != null) {
rgbFaceRectTransformer!!.cameraDisplayOrientation = displayOrientation
}
Timber.i("initRgbCamera onCameraConfigurationChanged: $cameraID $displayOrientation")
}
}
val previewConfig: PreviewConfig = recognizeViewModel.previewConfig
rgbCameraHelper = DualCameraHelper.Builder()
.previewViewSize(
Point(
binding.dualCameraTexturePreviewRgb.measuredWidth,
binding.dualCameraTexturePreviewRgb.measuredHeight
)
)
.rotation(windowManager.defaultDisplay.rotation)
.additionalRotation(0) // 角度
.previewSize(recognizeViewModel.loadPreviewSize())
.specificCameraId(previewConfig.rgbCameraId)
.isMirror(true)
.previewOn(binding.dualCameraTexturePreviewRgb)
.cameraListener(cameraListener)
.build()
rgbCameraHelper!!.init()
rgbCameraHelper!!.start()
}
/**
* 绘制RGB、IR画面的实时人脸信息
*
* @param facePreviewInfoList RGB画面的实时人脸信息
*/
private fun drawPreviewInfo(facePreviewInfoList: MutableList<FacePreviewInfo>?) {
if (rgbFaceRectTransformer != null) {
val rgbDrawInfoList: MutableList<DrawInfo>? = recognizeViewModel.getDrawInfo(
facePreviewInfoList, LivenessType.RGB, openRectInfoDraw
)
// 识别成功
binding.dualCameraFaceRectView.drawRealtimeFaceInfo(rgbDrawInfoList)
}
}
fun openRectInfoDraw(view: View?) {
openRectInfoDraw = !openRectInfoDraw
recognizeViewModel.setDrawRectInfoTextValue(openRectInfoDraw)
}
override fun onGlobalLayout() {
loadLogInfo("onGlobalLayout")
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().removeOnGlobalLayoutListener(this)
// 请求权限
checkCameraPermission()
}
private fun resumeCamera() {
isRecognition = true
if (rgbCameraHelper != null && rgbCameraHelper!!.isStopped) {
loadLogInfo("collectFace,resumeCamera: ")
rgbCameraHelper!!.start()
} else {
recognizeViewModel.onPreviewFrame(ByteArray(1382400), true)
}
}
/**
* 临时用户id
*/
private var tempUserId: String = ""
override fun onResume() {
super.onResume()
try {
if (isFirstOpen) {
goInitActivity()
binding.root.postDelayed({
isFirstOpen = false
}, 1000)
return
}
retryFailCount = 0
binding.tvSimilarValue.text = ""
isCollectFace = false
plateEnable = true
collectCount = 0
tempUserId = "${System.currentTimeMillis()}"
resumeCamera()
viewModel.resetUserInfo()
countDownTimer?.let {
it.cancel()
it.start()
}
// initFaceScheduler()
// checkFaceState()
} catch (e: Exception) {
e.printStackTrace()
}
}
private var isFirstOpen = true
protected override fun onPause() {
pauseCamera()
super.onPause()
countDownTimer?.cancel()
}
private fun pauseCamera() {
isRecognition = false
recognizeViewModel.onPreviewFrame(ByteArray(1382400), true)
}
override fun handleLoginSuccess(equipmentUserInfo: EquipmentUserInfo, isAdmin: Boolean) {
super.handleLoginSuccess(equipmentUserInfo, isAdmin)
// goInitActivity()
}
private val totalTimeInMillis = 15 * 1000L
fun initCountTime() {
countDownTimer = object : CountDownTimer(totalTimeInMillis, 1000) {
override fun onTick(millisUntilFinished: Long) {
loadLogInfo("initCountTime onTick = ${(millisUntilFinished / 1000).toInt()}")
binding.tvToInit.text = "${(millisUntilFinished / 1000).toInt() + 1}"
}
override fun onFinish() {
goInitActivity()
}
}
}
fun goInitActivity() {
val intent = Intent(context, InitActivity::class.java)
startActivity(intent)
}
private fun collectFace() {
loadLogInfo("collectFace: -----------1,开始采集人脸,开始时间:${DateTimeUtils.getDateTimeString()}----------")
if (isFirstOpen) return
loadLogInfo("collectFace: ----------2,isFirstOpen=false-----------")
loadLogInfo("collectFace: ----------4,检测到人脸信息-----------")
currentUserId = null
userFaceInfo = null
recognizeViewModel.updateRegisterStatus(REGISTER_STATUS_READY)
loadLogInfo("collectFace: ----------5,人脸采集中-----------")
}
private fun sendFaceData(faceData: String) {
loadLogInfo("collectFace,sendFaceData: ----------11,发送人脸数据-----------")
// 给某个客户端发送
val jsonObject = JSONObject().also {
it.put("type", "faceFeature")
it.put("content", faceData)
}
tcpClient?.send(jsonObject)
}
// private var getFaceScheduler: ScheduledExecutorService? = null
// private var checkFaceScheduler: ScheduledExecutorService? = null
//
// private fun initFaceScheduler() {
//// getFaceScheduler = Executors.newScheduledThreadPool(1)
// checkFaceScheduler = Executors.newScheduledThreadPool(1)
// }
private fun getFaceDataBlock(block: (String) -> Unit) {
if (userFaceInfo == null || userFaceInfo?.faceFeature?.featureData == null) {
return
}
val faceData: String? = Base64.encode(userFaceInfo?.faceFeature?.featureData)
if (faceData.isNullOrBlank()) {
return
}
loadLogInfo("collectFace,getFaceData: ----------7,拿到人脸提取特征数据-----------")
block(faceData)
}
private fun loadLogInfo(msg: String) {
Timber.tag(TAG).d(msg)
}
private var facePreviewInfoList: MutableList<FacePreviewInfo>? = null
private var userFaceInfo: UserFaceInfo? = null
private var currentUserId: String? = null
private fun saveFaceInfo(faceData: String) {
try {
sendFaceData(faceData)
loadLogInfo("collectFace,saveFaceInfo: ----------12,人脸数据发送完成时间:${DateTimeUtils.getDateTimeString()}-----------")
// runOnUiThread {
// openPlate(tempUserId)
// }
loadLogInfo("collectFace,saveFaceInfo: ----------8,保存人脸取特征数据-----------")
val faceDao = FaceDatabase.getInstance(this).faceDao()
val faceEntity = FaceEntity(
tempUserId,
null,
Base64.decode(faceData)
).also {
it.userType = "2"
}
faceDao.insert(faceEntity)
loadLogInfo("collectFace,saveFaceInfo: ----------10,人脸数据保存完成-----------")
recognizeViewModel.refreshFaceList()
loadLogInfo("collectFace,saveFaceInfo: ----------11,刷新人脸数据-----------")
runOnUiThread { recognizeViewModel.onPreviewFrame(ByteArray(1382400), true) }
loadLogInfo("---------------------------------")
collectCount = 0
} catch (e: Exception) {
e.printStackTrace()
loadLogInfo("collectFace,saveFaceInfo: ----------13,人脸采集异常:${e.message}-----------")
collectCount++
loadLogInfo("collectFace,saveFaceInfo: ----------14,${collectCount}次人脸采集异常:${e.message}-----------")
ToastUtils.showToast("人脸采集异常:${e.message}")
}
}
private var collectCount = 0;
private var tcpClient: TcpClient? = null
private fun addSocketListener() {
// val ipAddress = NetworkUtils.getIPAddress(true)
// loadLogInfo( "addSocketListener,ipAddress: $ipAddress");
tcpClient = TcpClient(
"192.168.1.95",
5000,
GlobalData.deviceId, // clientId
5000, // connectTimeoutMs
10 * 1000, // heartbeatIntervalMs
30 * 1000 // heartbeatTimeoutMs
)
tcpClient?.setListener(object : TcpClientListenerImpl() {
override fun onSendSuccess(json: JSONObject?) {
super.onSendSuccess(json)
loadLogInfo("collectFace,TcpClientListener发送成功:$json")
// toast("发送成功")
}
override fun onSendFailed(json: JSONObject?, e: java.lang.Exception?) {
super.onSendFailed(json, e)
ToastUtils.showToast("发送失败${e?.message}")
loadLogInfo("collectFace,TcpClientListener人脸数据发送失败:${e?.message}")
}
override fun onMessage(json: JSONObject?) {
super.onMessage(json)
loadLogInfo("collectFace,TcpClientListener收到消息:$json")
val type = json?.getInt("type")
// 根据服务端消息类型处理删除新增临时用户人脸数据---------------------
when (type) {
LanServer.TYPE_ADD_FACE_DATA -> {
//采集设备id自己生成,不接收服务端的,在本地只判断是否存在同一人脸数据
loadLogInfo("collectFace,TcpClientListener收到消息,新增用户:采集设备id自己生成,不接收服务端的,在本地只判断是否存在同一人脸数据")
}
LanServer.TYPE_CLEAR_FACE_DATA -> {
clearFaceData()
}
else -> {}
}
}
})
tcpClient?.start()
try {
LanServer.getInstance().let {
it.setListener(object : LanServerListenerImpl() {
override fun onMessageReceived(clientId: String?, message: JSONObject?) {
super.onMessageReceived(clientId, message)
ToastUtils.showToast("收到消息clientId=$clientId")
}
})
it.start()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun clearFaceData() {
Thread {
val faceDao = FaceDatabase.getInstance(this).faceDao()
faceDao.deleteTempUserFaceData()
recognizeViewModel.refreshFaceList()
loadLogInfo("collectFace,TcpClientListener收到消息,已删除并刷新人脸数据")
}.start()
}
// private val WAITING_TIME = 3 * 1000L
// private var checkStartTime = 0L
private fun checkFaceState() {
// checkStartTime = System.currentTimeMillis()
//
// checkFaceScheduler?.scheduleWithFixedDelay(
// {
// checkFaceBlock()
// }, 5L, 5L, TimeUnit.MILLISECONDS
// )
}
private var isCollectFace = false
// private fun checkFaceBlock() {
// loadLogInfo("collectFace,currentUserId=${currentUserId}")
// if (currentUserId.isNullOrBlank().not()) {
// isCollectFace = false
//
// checkFaceScheduler?.shutdown()
// return
// }
//// if (System.currentTimeMillis() - checkStartTime >= WAITING_TIME) {
//// //超过1秒采集人脸并识别
//// checkFaceScheduler?.shutdown()
//// isCollectFace = true
//// collectFace()
//// }
// }
}