调整了个人营养数据计算逻辑,修复了摄像头逻辑
This commit is contained in:
@@ -8,8 +8,6 @@ import android.graphics.Bitmap
|
||||
import android.graphics.Outline
|
||||
import android.graphics.Point
|
||||
import android.hardware.Camera
|
||||
import android.hardware.camera2.CameraDevice
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
@@ -68,8 +66,6 @@ class SecondaryScreenPresentation(
|
||||
val recognizeViewModel: RecognizeViewModel
|
||||
) : Presentation(context, display), ViewTreeObserver.OnGlobalLayoutListener {
|
||||
private lateinit var binding: PresentationSecondaryScreenBinding
|
||||
private lateinit var cameraManager: CameraManager
|
||||
private var cameraIdList: Array<String> = arrayOf()
|
||||
|
||||
// 当前食物信息
|
||||
private var currentFood: FoodInfo? = null
|
||||
@@ -82,7 +78,7 @@ class SecondaryScreenPresentation(
|
||||
// 上一次的计算热量结果
|
||||
private var lastCalcResultInfo: UserNutritionUtils.CalcResultInfo? = null
|
||||
private var lastWeight = 0.0
|
||||
private val debouncer = Debouncer(2000)
|
||||
private val debouncer = Debouncer(500)
|
||||
private var faceTime: Long = 0L // 人脸识别时的时间
|
||||
private var recognitionWeight: Double = 0.0 // 人脸识别时的重量
|
||||
private var lastFaceTrackId: Int = 0 // 上一次的人脸信息
|
||||
@@ -113,7 +109,7 @@ class SecondaryScreenPresentation(
|
||||
itemUserNutritionBinding.tvRecommendHeat.text =
|
||||
"推荐热量:${it.recommendMin}-${it.recommendMax}"
|
||||
|
||||
updateWeight(lastWeight)
|
||||
updateWeight(lastWeight / 1000)
|
||||
}
|
||||
}
|
||||
activity.lifecycleScope.launch {
|
||||
@@ -246,89 +242,95 @@ class SecondaryScreenPresentation(
|
||||
}
|
||||
|
||||
fun updateWeight(weight: Double) {
|
||||
Timber.d("updateWeight weight = $weight")
|
||||
lastWeight = weight
|
||||
lastWeight = weight * 1000 // 将千克转成克
|
||||
Timber.d("updateWeight lastWeight = $weight")
|
||||
if (currentFood == null) {
|
||||
Timber.e("updateWeight currentFood is null")
|
||||
return
|
||||
}
|
||||
if (userNutritionData == null) {
|
||||
Timber.e("updateWeight userNutritionData is null")
|
||||
return
|
||||
}
|
||||
if (currentFood == null) {
|
||||
Timber.e("updateWeight currentFood is null")
|
||||
return
|
||||
}
|
||||
if (userNutritionData == null) {
|
||||
Timber.e("updateWeight userNutritionData is null")
|
||||
return
|
||||
}
|
||||
if (dinnerTypeInfo == null) {
|
||||
Timber.e("updateWeight dinnerType is null")
|
||||
return
|
||||
}
|
||||
// 重量和 当前食物都没变,则不再计算
|
||||
if (lastFood == currentFood) {
|
||||
// Timber.e("updateWeight 物品未改变")
|
||||
return
|
||||
}
|
||||
lastFood = currentFood
|
||||
debouncer.debounce {
|
||||
val dinnerType = dinnerTypeInfo!!.dinnerType!!.dinnerType!!
|
||||
Timber.d("updateWeight foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
|
||||
val calcResultInfo = UserNutritionUtils.calculateNutrition(
|
||||
currentFood!!,
|
||||
userNutritionData!!,
|
||||
weight,
|
||||
dinnerType = dinnerType
|
||||
)
|
||||
Timber.d("updateWeight calcResultInfo = $calcResultInfo")
|
||||
if (lastCalcResultInfo == calcResultInfo) {
|
||||
Timber.d("updateWeight 与上次计算结果无变化")
|
||||
return@debounce
|
||||
}
|
||||
lastCalcResultInfo = calcResultInfo
|
||||
activity.runOnUiThread {
|
||||
val totalKcal = calcResultInfo.totalKcal
|
||||
val grain = calcResultInfo.grain
|
||||
val fruits = calcResultInfo.fruits
|
||||
val meat = calcResultInfo.meat
|
||||
// 设置热量
|
||||
itemUserNutritionBinding.customKcalColumn.setImageDrawable(
|
||||
true,
|
||||
totalKcal.first < totalKcal.second
|
||||
)
|
||||
itemUserNutritionBinding.totalKcalTv.text = totalKcal.second.format2String()
|
||||
itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent(
|
||||
(totalKcal.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置主食
|
||||
itemUserNutritionBinding.customFoodColumn.setImageDrawable(
|
||||
false,
|
||||
grain.first < grain.second
|
||||
)
|
||||
itemUserNutritionBinding.totalFoodTv.text = grain.second.format2String()
|
||||
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(
|
||||
(grain.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置果蔬
|
||||
itemUserNutritionBinding.customVegetableColumn.setImageDrawable(
|
||||
false,
|
||||
fruits.first < fruits.second
|
||||
)
|
||||
itemUserNutritionBinding.totalVegetableTv.text = fruits.second.format2String()
|
||||
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(
|
||||
(fruits.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置肉蛋
|
||||
itemUserNutritionBinding.customMeatColumn.setImageDrawable(
|
||||
false,
|
||||
meat.first < meat.second
|
||||
)
|
||||
itemUserNutritionBinding.totalMeatTv.text = meat.second.format2String()
|
||||
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(
|
||||
(meat.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
}
|
||||
calculateNutrition(recognitionWeight - lastWeight)
|
||||
}
|
||||
|
||||
private fun calculateNutrition(weight: Double) {
|
||||
debouncer.debounce {
|
||||
Timber.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
||||
val dinnerType = dinnerTypeInfo!!.dinnerType!!.dinnerType!!
|
||||
Timber.d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
|
||||
val calcResultInfo = UserNutritionUtils.calculateNutrition(
|
||||
currentFood!!,
|
||||
userNutritionData!!,
|
||||
weight,
|
||||
dinnerType = dinnerType
|
||||
)
|
||||
Timber.d("calculateNutrition calcResultInfo = $calcResultInfo")
|
||||
if (lastCalcResultInfo == calcResultInfo) {
|
||||
Timber.d("calculateNutrition 与上次计算结果无变化")
|
||||
return@debounce
|
||||
}
|
||||
lastCalcResultInfo = calcResultInfo
|
||||
val columnMax = UserNutritionUtils.getMaxInt(calcResultInfo)
|
||||
|
||||
activity.runOnUiThread {
|
||||
val totalKcal = calcResultInfo.totalKcal
|
||||
val grain = calcResultInfo.grain
|
||||
val fruits = calcResultInfo.fruits
|
||||
val meat = calcResultInfo.meat
|
||||
// 设置热量
|
||||
itemUserNutritionBinding.customKcalColumn.setImageDrawable(
|
||||
true,
|
||||
totalKcal.max < totalKcal.current
|
||||
)
|
||||
var maxKcal = totalKcal.max
|
||||
Timber.d("maxKcal = $maxKcal")
|
||||
if (maxKcal <= 0.0) {
|
||||
maxKcal = 100.0
|
||||
}
|
||||
Timber.d("maxKcal 1 = $maxKcal")
|
||||
itemUserNutritionBinding.totalKcalTv.text = totalKcal.current.format2String()
|
||||
itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent(
|
||||
(totalKcal.current / maxKcal).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置主食
|
||||
itemUserNutritionBinding.customFoodColumn.setImageDrawable(
|
||||
false,
|
||||
grain.max < grain.current
|
||||
)
|
||||
itemUserNutritionBinding.totalFoodTv.text = grain.current.format2String()
|
||||
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(
|
||||
(grain.current / columnMax).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置果蔬
|
||||
itemUserNutritionBinding.customVegetableColumn.setImageDrawable(
|
||||
false,
|
||||
fruits.max < fruits.current
|
||||
)
|
||||
itemUserNutritionBinding.totalVegetableTv.text = fruits.current.format2String()
|
||||
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(
|
||||
(fruits.current / columnMax).toFloat(),
|
||||
true
|
||||
)
|
||||
// 设置肉蛋
|
||||
itemUserNutritionBinding.customMeatColumn.setImageDrawable(
|
||||
false,
|
||||
meat.max < meat.current
|
||||
)
|
||||
itemUserNutritionBinding.totalMeatTv.text = meat.current.format2String()
|
||||
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(
|
||||
(meat.current / columnMax).toFloat(),
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openCamera() {
|
||||
@@ -340,50 +342,22 @@ class SecondaryScreenPresentation(
|
||||
return
|
||||
}
|
||||
try {
|
||||
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
// 获取摄像头列表
|
||||
cameraIdList = cameraManager.cameraIdList
|
||||
if (cameraIdList.isEmpty()) {
|
||||
ToastUtils.showToast("没有可用的摄像头")
|
||||
return
|
||||
}
|
||||
if (cameraIdList.size < 3) {
|
||||
val cameraCount = Camera.getNumberOfCameras()
|
||||
if (cameraCount < 3){
|
||||
ToastUtils.showToast("摄像头数量异常")
|
||||
return
|
||||
}
|
||||
|
||||
cameraIdList.forEach {
|
||||
Timber.d("摄像头id列表 = $it")
|
||||
recognizeViewModel.init(
|
||||
PreviewConfig(
|
||||
2, 1, 90, 90
|
||||
)
|
||||
)
|
||||
initRgbCamera()
|
||||
if (DualCameraHelper.hasDualCamera() && livenessType === LivenessType.IR) {
|
||||
initIrCamera()
|
||||
}
|
||||
val cameraId = cameraIdList.last()
|
||||
Timber.d("openCamera cameraId = $cameraId")
|
||||
val c1 = cameraIdList[0]
|
||||
val c2 = cameraIdList[1]
|
||||
val c3 = cameraIdList[2]
|
||||
cameraManager.openCamera(c3, object : CameraDevice.StateCallback() {
|
||||
override fun onOpened(device: CameraDevice) {
|
||||
recognizeViewModel.init(
|
||||
PreviewConfig(
|
||||
c3.toInt(), c2.toInt(), 90, 90
|
||||
)
|
||||
)
|
||||
initRgbCamera()
|
||||
// resumeCamera()
|
||||
if (DualCameraHelper.hasDualCamera() && livenessType === LivenessType.IR) {
|
||||
initIrCamera()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisconnected(device: CameraDevice) {
|
||||
device.close()
|
||||
}
|
||||
|
||||
override fun onError(device: CameraDevice, error: Int) {
|
||||
device.close()
|
||||
}
|
||||
}, null)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Camera2", "打开摄像头失败", e)
|
||||
Timber.e(e, "打开摄像头失败")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,21 +415,24 @@ class SecondaryScreenPresentation(
|
||||
Timber.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
|
||||
})
|
||||
recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? ->
|
||||
Timber.i("recognizeNotice observe notice = $notice")
|
||||
// Timber.i("recognizeNotice observe notice = $notice")
|
||||
})
|
||||
|
||||
recognizeViewModel.recognizeUserId.observe(
|
||||
activity,
|
||||
Observer { compareResult: CompareResult ->
|
||||
Timber.i("recognizeUserId observe compareResult = $compareResult")
|
||||
Timber.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}")
|
||||
faceTime = System.currentTimeMillis()
|
||||
recognitionWeight = lastWeight
|
||||
lastFaceTrackId = compareResult.trackId
|
||||
val faceEntity = compareResult.faceEntity
|
||||
val userId = faceEntity.userName
|
||||
if (userId == null) return@Observer
|
||||
viewModel.getUserNutritionData(userId = userId, foodId = currentFood!!.id!!)
|
||||
})
|
||||
if (userId == null) return@Observer
|
||||
viewModel.getUserNutritionData(
|
||||
userId = userId,
|
||||
foodId = currentFood!!.id!!
|
||||
)
|
||||
})
|
||||
|
||||
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
||||
Timber.i("drawRectInfoText observe info = $info")
|
||||
@@ -727,6 +704,11 @@ class SecondaryScreenPresentation(
|
||||
}
|
||||
|
||||
fun postUserData() {
|
||||
Timber.d("postUserData")
|
||||
if (userNutritionData == null || currentFood == null) {
|
||||
Timber.d("postUserData userNutritionData = ${userNutritionData == null}, currentFood = ${currentFood == null}")
|
||||
return
|
||||
}
|
||||
val userNutritionParam = UserNutritionParam(
|
||||
userId = userNutritionData?.userId!!,
|
||||
foodId = currentFood?.id!!,
|
||||
|
||||
Reference in New Issue
Block a user