AIDishRecognition 摄像头唯一标识与持久化设计说明

文档版本:V1.0 | 编制日期:2026-09-03 | 适用设备:FY-3576SE 及采用 Android USB/UVC + 外置 Camera2 HAL 的同类设备
当前状态:VID/PID 稳定标识、旧配置迁移、动态 Camera2 映射和友好名称展示已实现;同 VID/PID 双摄区分属于后续增强项

1. 核心结论

保存稳定标识,启动时重新枚举并解析运行时地址,界面只展示客户能理解的名称。

摄像头配置必须把以下三类信息分开管理:

  1. 持久化标识:用于保存“客户选择的是哪一台摄像头”。当前实现使用十进制 VID_PID,例如 1374_41357
  2. 客户显示名称:用于设置页下拉选择。当前显示“产品名称(厂商名称)”,例如“MC-500U(XC-TECH)”。
  3. 运行时地址:用于本次启动期间真正打开设备,包括 Android USB deviceId/dev/videoN 和 Camera2 ID。这些值可能在设备重启后变化,不能作为持久化唯一标识。

在当前 FY-3576SE 上,三台摄像头的 VID/PID 均不相同,因此可以稳定区分。程序重启或设备重启后,只要摄像头仍然连接且应用数据未被清除,就会按照保存的 VID/PID 恢复原选择。

2. 标题字段和用途

字段示例含义是否适合持久化
当前用途当前菜品识别业务角色,不是设备属性保存业务与设备的绑定关系
建议客户显示名称MC-500U(XC-TECH)产品名与厂商名,供客户选择只用于显示,不作为唯一标识
稳定标识 VID/PID1374_41357USB 厂商编号与产品编号的组合当前设备可作为持久化主键
序列号SN00151厂商写入设备的单机序列号可靠且唯一时,适合增强唯一性
USB 物理端口1-1.2摄像头连接的总线和端口路径可作为无序列号设备的绑定兜底
V4L2/dev/video0Linux 本次启动分配的视频节点不适合,重启或枚举顺序变化后可能改变
Camera2 ID100Android 外置相机 HAL 本次启动暴露的相机编号不适合,需在每次启动时重新计算
Android USB deviceId例如旧配置中的 1004Android 在当前 USB 连接期间分配的运行时编号不适合,重连或重启后可能改变

3. 当前设备摄像头清单

以下为 2026-09-03 在 FY-3576SE 上的设备快照:

建议显示名称当前稳定标识序列号USB 端口当前 V4L2当前 Camera2 ID
MC-500U(XC-TECH)1374_41357SN001511-1.2/dev/video0100
USB 2.0 Camera(Sonix Technology Co., Ltd.)3141_25440SN00011-1.6.1/dev/video2102
USB2.0_CAM1(Sonix Technology Co., Ltd.)11391_19040USB2.0_CAM11-1.6.2/dev/video28128

历史设备记录中,MC-500U 与 USB2.0_CAM1 曾分别对应 /dev/video28/dev/video0,与本次启动正好互换。这证明 V4L2 和 Camera2 编号只是运行时地址,写死映射会在重启后选错摄像头。

4. 当前持久化数据模型

4.1 菜品识别摄像头

配置项保存内容示例
usb_camera菜品摄像头稳定 VID/PID1374_41357
dish_camera_resolution_{VID_PID}该摄像头独立的分辨率dish_camera_resolution_1374_41357 = 1280x960

菜品摄像头的选择和分辨率都跟随稳定标识保存。因此,同一台摄像头重启后即使获得不同的 Android deviceId,仍能读取原来的选择和分辨率。

4.2 人脸识别摄像头

配置项保存内容生命周期
face_uvc_camera_id人脸摄像头稳定 VID/PID长期持久化,是恢复选择的依据
face_camera_id当前启动对应的 Camera2 ID运行时派生值,每次启动或使用前重新同步
face_camera_resolution人脸摄像头分辨率长期持久化
face_camera_rotation旋转角度长期持久化
face_camera_mirror镜像开关长期持久化

face_camera_id 虽然也写入配置,但它不是摄像头身份主键。真正的持久化依据是 face_uvc_camera_id;程序每次根据当前硬件拓扑重新得到新的 Camera2 ID。

5. 保存与恢复流程

5.1 用户保存选择

客户选择“产品名称(厂商名称)”
              ↓
程序读取该 UsbDevice 的 vendorId、productId
              ↓
生成稳定标识 VID_PID
              ↓
菜品相机写入 usb_camera
人脸相机写入 face_uvc_camera_id
              ↓
分辨率等参数按稳定标识或业务配置单独保存

5.2 程序重新启动

  1. SharedPreferences 读取已保存的稳定标识。
  2. 枚举当前连接的 USB/UVC 摄像头。
  3. 根据每台设备的 vendorId、productId 重新生成稳定标识。
  4. 找到与已保存标识一致的设备并恢复菜品或人脸角色。
  5. 如果保存的是旧格式,先执行兼容迁移,再继续匹配。

5.3 整机重新启动

设备重启后,USB deviceId、V4L2 节点和 Camera2 ID 都允许变化。恢复过程如下:

读取 face_uvc_camera_id
          ↓
扫描 /sys/class/video4linux/video*/device
          ↓
从视频节点追溯 USB 父设备,读取 VID/PID
          ↓
建立 VID_PID → 主 V4L2 节点映射
          ↓
读取 Camera2 中 hardware level = EXTERNAL 的相机 ID
          ↓
推导且校验唯一、一致的 Camera2/V4L2 编号偏移
          ↓
生成本次启动的 face_camera_id

当前设备表现为 Camera2 ID 与主 V4L2 节点存在统一偏移,例如 /dev/video0 → 100/dev/video2 → 102/dev/video28 → 128。程序通过当次枚举结果推导这个偏移,不再把 100102128 与具体型号写死绑定。

6. 旧配置兼容与迁移

旧版菜品配置曾使用 deviceId_VID_PID,例如 1004_1374_41357。新版读取时取最后两段并规范化为 1374_41357

如果发现旧分辨率键 fbl_旧ID,程序会把值复制到新的 dish_camera_resolution_{VID_PID}。旧键暂不删除,便于升级过渡和问题回溯。

7. 不同场景下的预期行为

场景是否保持选择程序行为
退出后重新打开程序SharedPreferences 读取稳定标识并重新匹配
Android 整机重启忽略变化后的运行时编号,重新解析 V4L2/Camera2 对应关系
USB 枚举顺序变化按 VID/PID 匹配,不按 deviceId 或 Camera2 ID 匹配
摄像头短暂拔出后插回正常情况下是重新枚举后按稳定标识找回设备
保存的摄像头未连接否,等待设备恢复提示“已保存的摄像头不可用,请重新选择”,不静默改成第一台
清除应用数据SharedPreferences 被清除,需要重新设置
卸载后重新安装通常否Android 通常会删除应用私有配置,需要重新设置
覆盖升级 APK正常情况下是应用私有配置保留,同时执行旧格式迁移
同时连接两台相同 VID/PID 摄像头当前不能可靠区分必须使用序列号或物理端口增强标识

8. 客户可读名称设计

设置页不直接显示 1374_41357 之类的内部标识,当前采用“产品名称(厂商名称)”。

产品名称或厂商名称缺失时,界面使用“USB 摄像头”等兜底文案。名称只服务于客户识别,不参与底层唯一性判断。

9. 同型号双摄的增强方案

9.1 当前边界

VID/PID 是型号级标识,不是所有情况下的单机唯一编号。 两台完全相同的摄像头通常具有相同 VID/PID,因此当前实现无法在这种场景下保证一对一绑定。

9.2 推荐唯一标识优先级

  1. 可靠序列号优先VID + PID + serialNumber。只在序列号非空、非通用占位值且在当前设备列表中唯一时使用。
  2. USB 物理端口兜底VID + PID + physicalPort。摄像头必须固定插在指定接口;换口后提示重新绑定。
  3. VID/PID 仅作型号级标识:只能用于当前不存在重复 VID/PID 的场景。
usb:1374:41357:sn:SN00151
usb:3141:25440:port:1-1.6.1

9.3 同型号设备的界面名称

USB 2.0 Camera(Sonix · 尾号0001)
USB 2.0 Camera(Sonix · USB口1)
USB 2.0 Camera(Sonix · USB口2)

还可以增加客户自定义别名,例如“菜品台上方”“人脸支付屏”。别名只作为显示属性,底层仍保存稳定绑定标识。

10. 冲突与安全策略

11. 代码职责映射

组件职责
UvcCameraIdentity生成、规范化和比较稳定 VID/PID;兼容旧 deviceId_VID_PID
DishCameraSettings管理菜品摄像头和分辨率持久化;迁移旧配置
FaceCameraSettings管理人脸 UVC 稳定标识,并在使用前同步 Camera2 ID
ExternalCameraIdResolver从 sysfs 和 Camera2 获取当次启动的硬件拓扑
FaceCameraIdMapping校验并计算稳定标识对应的 Camera2 ID
CameraUsbUtils将保存的稳定标识解析成当前连接的 UsbDevice 并打开菜品摄像头
SettingsCameraFragment展示友好名称、保存选择、处理失联和角色冲突

12. 当前验证状态

13. 实机验收清单

13.1 程序重启

13.2 整机重启

13.3 异常场景

14. 最终规则摘要

  1. 持久化保存稳定身份,不保存运行时地址。
  2. 当前设备使用 VID/PID,可以覆盖程序重启、设备重启和枚举顺序变化。
  3. V4L2 与 Camera2 ID 每次启动重新解析,不维护型号到编号的硬编码表。
  4. 界面展示产品名和厂商名,技术标识只供程序内部使用。
  5. 同 VID/PID 双摄必须升级为序列号或物理端口绑定,不能把 VID/PID 误认为所有场景下的单机唯一编号。
  6. 失联或映射不明确时停止自动选择,提示客户处理,避免打开错误摄像头。