当前位置: 首页 > article >正文

2. SpringBoot + MQTT 门禁设备对接实战

项目demo文件

源码地址: SynerTools 项目地址 (qq.com)


业务流程

首先,我们的 Spring Boot 服务充当一个客户端,而人脸识别设备的内置系统也作为另一个客户端。两个客户端通过 EMQX 服务端进行通信,负责指令的发送与接收


为什么使用MQTT而不是HTTP协议?

  1. 低带宽消耗:MQTT协议非常轻量级,设计之初就考虑到了低带宽网络环境,因此在传输数据时消耗的带宽非常少。相比之下,HTTP协议的数据包头较大,带宽消耗更高。
  2. 能效优化:MQTT协议设计简洁,特别适用于功耗敏感的物联网设备。HTTP协议因为连接开销大和数据包头大,通常会消耗更多的电能。
  3. 异步解耦: mqtt和rabbitmq是有相似之处, 都支持发布/订阅模式和异步通信,使消息发送者和接收者可以解耦,适合分布式系统应用,并且它们都提供消息可靠性保证和多语言支持

技术栈

  1. mica-mqtt(客户端) : mica-mqtt地址 (maven依赖引入即可)

Mica-MQTT 简化了 Spring Boot 项目中 MQTT 的集成,通过自动化配置和高度可扩展的设计,提供了便捷的消息发布和订阅功能。它支持多种 MQTT 客户端,具有高稳定性和可靠性,适用于生产环境。

  1. emqx开源版 (服务端) : 服务端下载地址

EMQX 开源版提供了高性能和高并发的 MQTT 消息处理能力,支持大规模设备连接。其用户友好的管理界面使页面管控方便,支持实时监控和配置管理。联调方面,丰富的调试工具和插件扩展功能简化了开发和测试过程。


设备对接业务流程

设备名称: 人脸识别机

MQTT协议对接文档 : 【免费】MQTT协议设备对接文档资源-CSDN文库


设备消息的推送与接收

根据人脸录入流程图可以看出,我们的系统实际上是一个基于 Spring Boot 的考勤客户端。为了实现消息推送功能,我们需要借助 mica-mqtt 客户端来进行消息推送。

1. 推送消息

这里我们以向设备推送人脸消息为例

这里的 deviceNo(设备编号 ,一般在贴在设备的背面)就是指设备的 SN 号。我们需要将其替换为对应的编号,才能向指定设备推送消息。确认好发送的主题后,剩下的 JSON 内容我们只需按照文档里的要求来编写即可。

/**
 * @author wsq
 */
@Service
public class MainService {
    private static final Logger logger = LoggerFactory.getLogger(MainService.class);
    @Autowired
    private MqttClientTemplate client;

    public boolean publish() {
        client.publish("pass/002024041590421/request", "对应的人脸信息JSON数据".getBytes(StandardCharsets.UTF_8));
        return true;
    }

}

推送消息演示 :

2. 接收消息

以为监听同行记录上报为例

这里的 deviceNo(设备编号) 就是指的设备sn号, 如果你想监听多台设备的话就可以 用 "+" (单层通配符)代替

如果想了解更多通配符可以参考这篇文章 : 通过案例理解 MQTT 主题与通配符 | EMQ (emqx.com)

所以对应我们的主题名称为 @MqttClientSubscribe("/face/+/request")

@Service
public class MqttClientSubscribeListener {
    private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class);

    @MqttClientSubscribe("/face/+/request")
    public void subQos0(String topic, byte[] payload) {
        logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8));
    }
}

接收消息演示:


客户端页面

在设备和客户端启动后,以及Spring Boot客户端成功运行时,您可以在EMQX的管理界面上看到它们的状态显示。访问地址 : http://127.0.0.1:18083


设备对接的坑点和注意事项

  1. emqx 的消息体内容大小太大, 导致服务端和客户端断开连接 解决办法 : 调整报文大小5M基本合适

  1. 苹果手机上传后照片是歪着的, 导致设备无法提取人脸特征值 解决办法: 判断宽高width > height 则使照片顺时针旋转90度, 代码如下
    /**
     * 根据图片URL,先进行压缩处理,再将其转换为Base64编码字符串。
     *
     * @return Base64编码的字符串,若输入URL为空或无效,则返回null
     */
    public static String compressAndEncodeToBase64(BufferedImage image) throws Exception {
        if (image == null) {
            return null;
        }
        System.out.println(image.getHeight() + ":" + image.getWidth());
        // 检查图像是否需要旋转
        if (image.getWidth() > image.getHeight()) {
            image = rotateImage90DegreesClockwise(image);
        }

        BufferedImage compressedImage = Thumbnails.of(image)
                .imageType(BufferedImage.TYPE_INT_RGB)
                .size(image.getWidth() / 4, image.getHeight() / 4)
                .keepAspectRatio(true)
                .asBufferedImage();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(compressedImage, "jpg", baos);
        byte[] bytes = baos.toByteArray();
        return java.util.Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 照片旋转90操作 为解决苹果手机上传后转base64图片歪着的问题
     */
    private static BufferedImage rotateImage90DegreesClockwise(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        BufferedImage rotatedImage = new BufferedImage(height, width, image.getType());
        Graphics2D g2d = rotatedImage.createGraphics();
        g2d.translate((height - width) / 2.0, (height - width) / 2.0);
        g2d.rotate(Math.toRadians(90), height / 2.0, width / 2.0);
        g2d.drawRenderedImage(image, null);
        g2d.dispose();
        return rotatedImage;
    }
  1. 设备自己也需要连接一个mqtt服务端(本文使用的EMQX), 一般是内网地址登录设备的ip就能设置(一定要让设备先联网!)

  1. 厂家有提供他们的说明文档,先把文档大致看下,然后再和厂家沟通;


http://www.kler.cn/a/402492.html

相关文章:

  • 【分治】--- 快速选择算法
  • 公网弹性绑定负载均衡收费吗?
  • 桥梁、隧道、道路、铁路、结构、岩土,哪个发展更好?
  • Linux的开发工具(三)
  • Android Binder技术概览
  • 拥塞控制算法的 Utility-Function
  • Kafka Stream实战教程
  • 深入解析小程序组件:view 和 scroll-view 的基本用法
  • 测试使用vite搭建的uni-app打包app区分开发环境和生产环境
  • linux 中mysql查看慢日志
  • 51c自动驾驶~合集31
  • 用Rust中byteorder包高效处理字节序列
  • 第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇
  • 项目管理交流会 | 产品研发项目管理主题会议成功举办
  • Cesium 加载B3DM模型
  • 枫清科技亮相 2024 中国 5G+工业互联网大会,推动 AI 赋能新型工业化
  • Spring Boot教程之四:在IntelliJ IDEA 以及 Eclips IDE中创建和配置Spring Boot
  • 根据条件 控制layui的table的toolbar的按钮 显示和不显示
  • 【Redis】实现点赞功能
  • 5.tree of thought 源码 (prompts 类)
  • 零基础入门Flink,掌握基本使用方法
  • 华为openEuler考试真题演练(附答案)
  • # TCP、UDP、HTTP、Socket
  • 无人机CAN总线基础——CKESC电调小课堂14
  • 平价鼠标推荐-英菲克PW1有线鼠标
  • 【Spring boot】微服务项目的搭建整合swagger的fastdfs和demo的编写