feat(mqtt): 增加人脸库 MQTT 实时变更同步功能

- 新增 MQTT 客户端依赖及配置,实现设备端实时接收人脸变化推送
- 实现 FaceMqttSubscriber 单例,启动时解析环境选择对应 MQTT 配置
- 实现消息解析、乱序过滤及本地人脸库数据实时更新逻辑
- 设备端订阅人脸变更主题,连接/重连成功触发 HTTP 增量补拉兜底机制
- 在 LoginByFaceActivity 中订阅 MQTT 事件,实时刷新识别引擎内存
- MQTT 连接管理器 MqttManager 负责连接、重连、订阅及消息分发,实现完整生命周期管理
- 新增环境选择弹窗,优化初始化界面布局和按钮样式
- 配置激活码硬编码修正,避免测试环境激活码错误导致的问题
- 日志与错误提示等细节优化,提升稳定性与用户体验
This commit is contained in:
mazengfei
2026-09-02 14:57:35 +08:00
parent 04b0c85482
commit 1bd57e0680
18 changed files with 658 additions and 36 deletions
@@ -48,7 +48,9 @@ class DeviceInitActivity : BaseActivity<ActivityDeviceInitBinding>() {
}
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
// 测试设备后台下发的激活码不正确,手动硬编码覆盖为正确值(后台修复后可回退为下行)
// GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
GlobalData.activeKey = "085F-118G-Q4V1-THBP"
hideWaitingDialog()
goLoginActivity()
}
@@ -35,6 +35,8 @@ import com.sw.platecabinet.member.R
import com.sw.platecabinet.member.databinding.ActivityLoginFaceBinding
import com.sw.platecabinet.member.databinding.ItemTitleTimeBinding
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.mqtt.FaceChangedEvent
import com.sw.platecabinet.mqtt.FaceSyncTriggerEvent
import com.sw.platecabinet.network.task.TaskManager
import com.sw.platecabinet.utils.PermissionHelper
import org.greenrobot.eventbus.EventBus
@@ -143,6 +145,35 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
Timber.tag("performSync over").e("-time=%s", insertEntity.registerTime)
}
/**
* MQTT 实时同步后的人脸库已落库,防抖重载识别引擎内存(合并短时间内连续变更)
*/
private val faceRefreshHandler = Handler(Looper.getMainLooper())
private val faceRefreshRunnable = Runnable { recognizeViewModel.refreshFaceList() }
@Subscribe(threadMode = ThreadMode.MAIN)
fun onFaceChanged(event: FaceChangedEvent) {
Timber.d("onFaceChanged 收到人脸实时变更,2s 后刷新引擎内存")
faceRefreshHandler.removeCallbacks(faceRefreshRunnable)
faceRefreshHandler.postDelayed(faceRefreshRunnable, 2000)
}
/**
* MQTT 连接/重连成功,补拉一次 HTTP 增量兜底(设备离线期间漏收的变更)
*/
@Subscribe(threadMode = ThreadMode.MAIN)
fun onFaceSyncTrigger(event: FaceSyncTriggerEvent) {
val timestamp = SpTool.getLastFaceTimestamp()
if (timestamp == 0L) {
Timber.d("onFaceSyncTrigger 水位为 0,跳过增量补拉")
return
}
Timber.d("onFaceSyncTrigger MQTT 已连接,执行 HTTP 增量补拉 timestamp=$timestamp")
netViewModelV2.getFaceIncrementList(pageNo = 1, timestamp = timestamp) {
recognizeViewModel.refreshFaceList()
}
}
override fun onLeftDoubleClick() {
finish()
}