一、项目背景

去年接手了一个共享棋牌室的智能化改造项目。客户有8个包间,希望实现24小时无人值守运营。最初使用的是远程密码锁,但在实际运营中暴露出一系列问题。

本文从技术角度记录整个系统的设计思路、选型过程、架构实现及落地经验,希望对从事物联网、智能硬件或共享经济相关开发的同行有所参考。


二、原有系统痛点分析

2.1 密码锁的技术缺陷

原有密码锁本质是一个“静态凭证验证系统”。核心逻辑如下:

用户预订 → 系统生成密码 → 用户输入密码 → 锁具验证 → 开门

这种设计存在几个根本性问题:

1. 身份与凭证解耦
密码作为凭证,与用户身份没有任何绑定关系。只要密码有效,任何知晓密码的人都能开门。这导致密码被随意转发、多人共享,逃单率居高不下。

2. 无行为追溯能力
系统只记录“哪个密码在什么时间被使用”,不记录“谁使用了密码”。发生安全事故时,无法提供有效的审计线索。

3. 缺乏持续控制能力
用户进入后,系统失去对用户行为的控制能力。超时占用、夜间滞留等问题无法自动处理,需要人工干预。

4. 运维成本高
客户每天需要处理大量售后问题:密码失效、忘记密码、超时纠纷等,实际上充当了24小时客服。

2.2 技术层面的局限性

从系统架构角度看,密码锁方案存在以下技术局限:

  • 无用户态管理:无法建立用户身份体系

  • 权限模型简单:仅有“有效/无效”两种状态,无法支持精细化权限控制(如时段限制、次数限制)

  • 数据孤岛:通行数据无法与业务系统(订单、会员、财务)打通

  • 离线能力弱:依赖网络下发密码,断网时无法处理新订单


三、需求分析与技术选型

3.1 核心需求

经过与客户多轮沟通,梳理出以下核心需求:

需求类别 具体描述
身份识别 明确知道“谁”进了门,而非“哪个密码”进了门
行为追溯 完整记录进出时间,支持按用户、时间、设备多维度查询
权限自动化 会员到期自动失效,续费自动恢复;临时用户限时自动回收
多业态支持 不仅支持棋牌室,还要能扩展到景区、自习室等场景
集中管理 一个后台管理所有门店,支持多租户隔离
离线可用 网络中断时门禁仍能正常工作,数据本地缓存

3.2 技术方案选型

3.2.1 身份识别技术对比

技术方案 优点 缺点 适用场景
密码 成本低、部署简单 无身份绑定、易泄露 低安全要求场景
IC卡 成本适中 需发卡、易丢失、无生物特征 企业内部场景
二维码 灵活、成本低 依赖手机、需网络、可截图分享 临时访客场景
蓝牙 体验较好 需APP、配对复杂 社区门禁场景
人脸识别 体验好、不可伪造、无接触 成本相对高、受环境影响 共享空间、高安全场景

考虑到棋牌室对安全性和用户体验的要求,选择人脸识别作为主认证方式,同时保留身份证和二维码作为备选。

3.2.2 人脸识别算法选型

对比了市面上主流的人脸识别方案:

方案 识别速度 活体检测 离线支持 成本
虹软ArcFace <0.3s 支持 支持
商汤SenseTime <0.2s 支持 需联网
百度AI <0.3s 支持 需联网
海康自研 <0.5s 支持 支持

综合考虑成本、离线能力和部署灵活性,选择了虹软ArcFace SDK作为人脸识别引擎。

3.2.3 硬件选型

硬件层面主要考虑:

  • 处理器:RK3399/RK3568,性能足够,功耗适中

  • 摄像头:双目摄像头,支持红外活体检测

  • 屏幕:5寸/7寸IPS屏,户外场景需高亮屏

  • 通信:4G+WiFi双模,适应不同网络环境

  • 存储:8GB eMMC,可缓存5000+条通行记录

3.2.4 平台架构选型

  • 后端:Spring Boot + MyBatis Plus,MySQL主从 + Redis缓存

  • 前端管理端:Vue3 + Element Plus

  • 用户端:微信小程序

  • 设备通信:MQTT协议 + HTTP API双通道

  • 部署:阿里云ECS + RDS + OSS

3.3 供应商选择

对比了3家供应商后,最终选择了中优云联的方案。主要原因:

  1. 完整的SaaS平台:支持多门店、多设备集中管理

  2. 断网离线存储:满足棋牌室地下室网络不稳定的需求

  3. 人证核验能力:符合后续扩展需求

  4. 开放API:支持与现有业务系统对接


四、系统架构设计

4.1 整体架构

系统采用典型的三层架构:

┌─────────────────────────────────────────────────┐
│                   应用层                         │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│  │用户小程序│ │管理后台 │ │数据大屏 │        │
│  └──────────┘ └──────────┘ └──────────┘        │
├─────────────────────────────────────────────────┤
│                   平台层                         │
│  ┌──────────────────────────────────────┐       │
│  │          SaaS管理平台                 │       │
│  │  设备管理│用户管理│权限管理│数据统计 │       │
│  └──────────────────────────────────────┘       │
│  ┌──────────────────────────────────────┐       │
│  │           设备接入层                  │       │
│  │  MQTT Broker │ HTTP API │ 数据同步  │       │
│  └──────────────────────────────────────┘       │
├─────────────────────────────────────────────────┤
│                   设备层                         │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│  │人脸识别终端│ │身份证阅读器│ │二维码扫描器│        │
│  └──────────┘ └──────────┘ └──────────┘        │
└─────────────────────────────────────────────────┘

4.2 核心模块设计

4.2.1 设备端架构

设备端采用分层设计:

┌─────────────────────────────────────┐
│              应用层                  │
│  ┌─────────────┐ ┌─────────────┐   │
│  │ 识别逻辑    │ │ 权限校验    │   │
│  └─────────────┘ └─────────────┘   │
├─────────────────────────────────────┤
│              服务层                  │
│  ┌─────────────┐ ┌─────────────┐   │
│  │ 人脸SDK封装 │ │ 通信模块    │   │
│  └─────────────┘ └─────────────┘   │
├─────────────────────────────────────┤
│              数据层                  │
│  ┌─────────────┐ ┌─────────────┐   │
│  │ SQLite     │ │ 本地文件系统│   │
│  └─────────────┘ └─────────────┘   │
├─────────────────────────────────────┤
│              硬件层                  │
│  │ 摄像头 │ 屏幕 │ 继电器 │ 4G模块│   │
└─────────────────────────────────────┘

4.2.2 权限模型设计

权限模型支持灵活的权限策略配置:

权限类型 说明 有效期 使用限制
会员权限 月卡/季卡用户 固定时间段 不限次
访客权限 临时体验用户 指定时长 单次有效
预约权限 景区预约用户 指定时段 时段内有效
管理员权限 运营管理人员 永久/临时 不限

权限表结构设计:

CREATE TABLE `device_permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(64) NOT NULL COMMENT '用户ID',
  `device_id` varchar(64) DEFAULT NULL COMMENT '设备ID,空表示全部门店',
  `permission_type` tinyint(4) NOT NULL COMMENT '1-会员 2-访客 3-预约 4-管理员',
  `start_time` datetime NOT NULL COMMENT '生效时间',
  `end_time` datetime NOT NULL COMMENT '失效时间',
  `max_uses` int(11) DEFAULT NULL COMMENT '最大使用次数,NULL表示不限',
  `used_count` int(11) DEFAULT '0' COMMENT '已使用次数',
  `status` tinyint(4) DEFAULT '0' COMMENT '0-有效 1-失效',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_device_id` (`device_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.2.3 通行记录表设计

CREATE TABLE `access_record` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `device_id` varchar(64) NOT NULL COMMENT '设备ID',
  `user_id` varchar(64) NOT NULL COMMENT '用户ID',
  `verify_type` tinyint(4) NOT NULL COMMENT '1-人脸 2-身份证 3-二维码',
  `verify_result` tinyint(4) NOT NULL COMMENT '1-通过 0-不通过',
  `face_image_url` varchar(512) DEFAULT NULL COMMENT '抓拍人脸照片URL',
  `idcard_info` json DEFAULT NULL COMMENT '身份证信息',
  `entry_time` datetime NOT NULL COMMENT '进门时间',
  `exit_time` datetime DEFAULT NULL COMMENT '出门时间',
  `duration_minutes` int(11) DEFAULT NULL COMMENT '停留时长(分钟)',
  `sync_status` tinyint(4) DEFAULT '0' COMMENT '0-未同步 1-已同步',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_device_id` (`device_id`),
  KEY `idx_entry_time` (`entry_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.3 断网离线存储方案

这是系统设计中的一个关键点。棋牌室多位于地下室,网络信号不稳定。我们设计了以下离线存储机制:

4.3.1 数据同步策略

┌─────────────────────────────────────────────────┐
│                   云端平台                       │
└─────────────────────────────────────────────────┘
                        ↑↓
              ┌───────────────────┐
              │   同步服务        │
              │  (增量同步)       │
              └───────────────────┘
                        ↑↓
┌─────────────────────────────────────────────────┐
│                  设备本地                        │
│  ┌─────────────┐      ┌─────────────┐          │
│  │ 权限表(本地)│      │ 记录表(本地)│          │
│  │ (SQLite)   │      │ (SQLite)   │          │
│  └─────────────┘      └─────────────┘          │
└─────────────────────────────────────────────────┘

4.3.2 离线识别流程

用户刷脸
    ↓
本地人脸识别
    ↓
查询本地权限表
    ↓
┌─────────────────────────────────────┐
│ 判断权限是否有效                     │
│ - 是否在有效期内                     │
│ - 是否超过使用次数                   │
└─────────────────────────────────────┘
    ↓
通过 → 开门 + 记录本地
不通过 → 拒绝开门

4.3.3 数据缓存策略

  • 权限数据:设备启动时同步全量权限,之后每5分钟增量同步

  • 通行记录:本地最多缓存5000条,超过后覆盖最旧记录

  • 同步机制:网络恢复后,批量上传本地记录,上传成功后删除本地记录


五、关键技术实现

5.1 人脸识别SDK集成

基于虹软ArcFace SDK的实现要点:

// 人脸识别服务封装
public class FaceRecognitionService {
    
    private FaceEngine faceEngine;
    
    // 初始化引擎
    public void init() {
        faceEngine = new FaceEngine();
        faceEngine.activeOnline(context, appId, sdkKey);
        faceEngine.setFaceLiveType(FaceEngine.FACE_LIVE_TYPE_RGB_IR);
    }
    
    // 1:1人脸比对
    public float compare(byte[] face1, byte[] face2) {
        FaceFeature feature1 = faceEngine.extractFaceFeature(face1);
        FaceFeature feature2 = faceEngine.extractFaceFeature(face2);
        return faceEngine.compareFaceFeature(feature1, feature2);
    }
    
    // 活体检测
    public boolean livenessCheck(byte[] rgbImage, byte[] irImage) {
        return faceEngine.checkLive(rgbImage, irImage) > 0;
    }
}

5.2 设备通信协议

采用MQTT + HTTP双通道设计:

  • MQTT:用于实时指令下发(如远程开门、权限同步)

  • HTTP:用于批量数据上报(如通行记录同步)

// MQTT消息格式
{
    "topic": "/device/{deviceId}/command",
    "payload": {
        "cmd": "sync_permission",
        "data": {
            "permissions": [...],
            "timestamp": 1700000000
        }
    }
}

5.3 人证核验实现

人证核验流程:

1. 用户刷身份证 → 读取身份证信息(姓名、证件号、照片)
2. 现场抓拍人脸
3. 调用1:1比对算法,比对现场人脸与身份证照片
4. 比对通过 → 记录身份证信息,开门
   比对不通过 → 拒绝开门

身份证信息读取使用公安部认证的二代身份证阅读器模组,通过串口通信。

5.4 SaaS平台多租户设计

// 多租户数据隔离 - MyBatis拦截器实现
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class TenantInterceptor implements Interceptor {
    
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        
        // 获取当前租户ID
        String tenantId = TenantContext.getCurrentTenant();
        
        // 动态拼接SQL,添加租户过滤条件
        String originalSql = statementHandler.getBoundSql().getSql();
        if (shouldAddTenantCondition(mappedStatement)) {
            String newSql = addTenantCondition(originalSql, tenantId);
            metaObject.setValue("delegate.boundSql.sql", newSql);
        }
        
        return invocation.proceed();
    }
}

六、系统部署与落地

6.1 部署架构

┌─────────────────────────────────────────────────┐
│                   阿里云ECS                      │
│  ┌─────────────┐ ┌─────────────┐               │
│  │ 应用服务器  │ │ 应用服务器  │ (多节点)       │
│  └─────────────┘ └─────────────┘               │
│  ┌─────────────┐ ┌─────────────┐               │
│  │   MySQL     │ │   Redis     │ (主从)         │
│  └─────────────┘ └─────────────┘               │
│  ┌─────────────┐ ┌─────────────┐               │
│  │   OSS      │ │  MQTT Broker│               │
│  └─────────────┘ └─────────────┘               │
└─────────────────────────────────────────────────┘
                        ↑
                    ┌───┴───┐
                    │  4G   │
                    └───┬───┘
        ┌───────────────┼───────────────┐
        ↓               ↓               ↓
   ┌─────────┐    ┌─────────┐    ┌─────────┐
   │ 门店1   │    │ 门店2   │    │ 门店3   │
   │ 8个设备 │    │ 6个设备 │    │ 10个设备│
   └─────────┘    └─────────┘    └─────────┘

6.2 实施步骤

  1. 硬件安装:替换原有密码锁,安装人脸识别终端,约30分钟/门

  2. 网络配置:设备配置WiFi或4G网络,确保云端连通

  3. 权限导入:导入现有会员数据,同步权限

  4. 灰度测试:先开放1-2个包间测试,稳定后全量切换

  5. 用户培训:现场指导用户使用,张贴使用说明

6.3 落地效果

系统上线3个月后的数据:

指标 改造前 改造后 变化
前台人力成本 48000元/年 0 -100%
逃单损失 ~8000元/年 0 -100%
客诉处理时间 2小时/天 0.2小时/天 -90%
超时纠纷 5-10次/月 0 -100%
通行数据可追溯率 0% 100% -

七、技术总结与展望

7.1 经验总结

1. 离线能力是共享场景的刚需

很多开发者容易忽略这一点,认为现在网络覆盖很好。但实际上地下室、电梯间等场景网络不稳定是常态。设备必须具备本地存储和本地判断能力。

2. 权限模型设计要足够灵活

不同业态对权限的要求差异很大。棋牌室需要按小时计费,景区需要按时段预约,自习室需要按次计费。设计一个通用的权限模型非常重要。

3. 人证核验不只是“刷脸+刷证”

实际使用中,老年人刷脸通过率低、光线影响大等问题都需要考虑。需要设计降级方案,比如允许管理员远程开门。

4. 数据同步要处理好冲突

断网期间产生的本地记录,恢复网络后可能遇到数据冲突(如用户权限已变更)。需要设计合理的冲突解决策略。

7.2 下一步规划

  1. 智能调度:基于包间使用数据,动态调整价格和促销策略

  2. 异常预警:超时未出、夜间异常进入等场景自动报警

  3. 客流分析:基于进出数据,分析用户行为,优化运营策略

  4. 边缘计算:在设备端实现更多本地计算,减少云端依赖


八、参考资料

  1. 虹软ArcFace人脸识别SDK开发文档

  2. 《人脸识别技术在门禁系统中的应用研究》

  3. MQTT协议规范v5.0

  4. Spring Boot多租户架构设计实践


本文首发于CSDN,欢迎技术交流。

标签:#人脸识别 #门禁系统 #物联网 #共享经济 #系统架构

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐