java 实现串口通讯

news2024/11/18 0:18:53

1、引入依赖

<dependency>
	<groupId>org.scream3r</groupId>
	<artifactId>jssc</artifactId>
	<version>2.8.0</version>
</dependency>

2、配置启动串口

@Component
public class ContextHolder implements ApplicationContextAware{
	
	private static ApplicationContext applicationContext = null;
	
	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		if(ContextHolder.applicationContext == null){
			ContextHolder.applicationContext  = arg0;
	    }
		System.out.println("========ApplicationContext配置成功,ContextHolder.getAppContext()获取applicationContext对象,applicationContext="+ ContextHolder.applicationContext+"========");
	}
	
	//获取applicationContext
    public static ApplicationContext getApplicationContext() {
       return applicationContext;
    }
    //通过name获取 Bean.
    public static Object getBean(String name){
       return getApplicationContext().getBean(name);
    }
    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
       return getApplicationContext().getBean(clazz);
    }
    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
       return getApplicationContext().getBean(name, clazz);
    }

}
@Slf4j
@Component
public class SerialPortCanContext{
    //串口映射
    public static Map<String, SerialPort> serialPortMap = new ConcurrentHashMap<>();


    @PostConstruct
    public void initSerialPort() throws Exception{
        String portName = "COM2";
        startSerialPort(portName);
    }
    /**
     * 初始化串口
     * @param portName
     */
    public synchronized void startSerialPort(String portName){
        //如果有之前的串口就关闭
        SerialPort serialPort1 = serialPortMap.get(portName);
        if (serialPort1 != null){
            try {
                serialPort1.removeEventListener();
                serialPort1.closePort();
            } catch (SerialPortException e) {
                log.error(e.getMessage());
            }
        }
        //生成新的串口并打开
        SerialPort serialPort = new SerialPort(portName);
        try {
            serialPort.openPort();
            serialPort.setParams(SerialPort.BAUDRATE_256000,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_EVEN);
            serialPort.addEventListener(new HhdSerialPortListener());
        } catch (SerialPortException e) {
            log.error(e.getMessage());
        }
        serialPortMap.put(portName,serialPort);
    }
}
/**
 * @author fangyuan
 * @description 串口监听器
 * @date 2023年11月7日09:08:43
 **/
public class SerialPortListener implements SerialPortEventListener {
    private static Logger logger= LoggerFactory.getLogger(HhdSerialPortListener.class);
    private SerialPortCanContext serialPortCanContext;
    public SerialPortListener() {
        this.serialPortCanContext = ContextHolder.getBean(SerialPortCanContext.class);
    }

    @Override
    public void serialEvent(SerialPortEvent serialPortEvent) {
        String portName = serialPortEvent.getPortName();
        if (StringUtils.isBlank(portName)){
            return;
        }
        //通过缓存拿到串口 没有就生成一下
        SerialPort serialPort = SerialPortCanContext.serialPortMap.get(portName);
        if (serialPort == null){
            serialPortCanContext.startSerialPort(portName);
        }
        try {
            String body = serialPort.readString();
            if (StringUtils.isBlank(body)){
                return;
            }
            logger.info("SerialPort : {}  received : {}",portName,body);
            int size = body.length() / 2;
            ByteBuf buf = Unpooled.buffer(size);
            buf.writeBytes(hexToBytes(body));
            //todo 再将buf数据进行后续处理
        } catch (SerialPortException e) {
            logger.error(e.getMessage());
        }
    }



    /**
     * 将16进制字符串转换为byte[]
     * @param hexStr
     * @return
     */
    public static byte[] hexToBytes(String hexStr) {
        int len = hexStr.length();
        hexStr = hexStr.toUpperCase();
        byte[] des;
        if (len % 2 != 0 || len == 0) {
            return null;
        } else {
            int halfLen = len / 2;
            des = new byte[halfLen];
            char[] tempChars = hexStr.toCharArray();
            for (int i = 0; i < halfLen; ++i) {
                char c1 = tempChars[i * 2];
                char c2 = tempChars[i * 2 + 1];
                int tempI = 0;
                if (c1 >= '0' && c1 <= '9') {
                    tempI += ((c1 - '0') << 4);
                } else if (c1 >= 'A' && c1 <= 'F') {
                    tempI += (c1 - 'A' + 10) << 4;
                } else {
                    return null;
                }
                if (c2 >= '0' && c2 <= '9') {
                    tempI += (c2 - '0');
                } else if (c2 >= 'A' && c2 <= 'F') {
                    tempI += (c2 - 'A' + 10);
                } else {
                    return null;
                }
                des[i] = (byte) tempI;
                // system.out.println(des[i]);
            }
            return des;
        }
    }
}

3、 模拟串口发送消息

3、1 安装 Configure Virtual Serial Port Driver

链接:https://pan.baidu.com/s/1fQ76Fh07kzqPeKho9nb7CA?pwd=6533
提取码:6533
解压后安装,将安装后的 这两个文件复制到安装目录并覆盖之前的文件
在这里插入图片描述

在这里插入图片描述

增加映射串口
在这里插入图片描述
打开 我点电脑----> 右键属性 -------> 设备管理 --------->端口查看
有数据表示串口映射成功
在这里插入图片描述

3、2 安装打开 sscom

链接:https://pan.baidu.com/s/13csdZ5XEkZ-E9r5XRYXWVA?pwd=6533
提取码:6533

在这里插入图片描述

3、3 发送消息

在这里插入图片描述

接收消息
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1226555.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue2中的插槽

vue2中的插槽 props[数学公式]属性: 各种数据类型值。子组件接收到之后做不同的判断实现不同的效果来实现复用性。 插槽&#xff1a;HTML dom元素。 预留属性、预留插槽。 调用语法&#xff1a;单闭合/双闭合。需要传插槽&#xff0c;就用双闭合&#xff1b;不需要就单双都可以…

斯坦福机器学习 Lecture2 (假设函数、参数、样本等等术语,还有批量梯度下降法、随机梯度下降法 SGD 以及它们的相关推导,还有正态方程)

假设函数定义 假设函数&#xff0c;猜一个 x->y 的类型&#xff0c;比如 y ax b&#xff0c;随后监督学习的任务就是找到误差最低的 a 和 b 参数 有时候我们可以定义 x0 1&#xff0c;来让假设函数的整个表达式一致统一 如上图是机器学习中的一些术语 额外的符号&#xf…

【C++初阶】STL详解(三)vector的介绍与使用

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

Python学习(一)基础语法

文章目录 1. 入门1.1 解释器的作用1.2 下载1.3 基础语法输入输出语法与引号注释&#xff1a;变量&#xff1a; 数据类型与四则运算数据类型四则运算数据类型的查看type()数据类型的转换int()、int()、float() 流程控制格式化输出循环与遍历逻辑运算符list遍历字典dict遍历 跳出…

思维模型 鲶鱼效应

本系列文章 主要是 分享 思维模型 &#xff0c;涉及各个领域&#xff0c;重在提升认知。激发竞争&#xff0c;促进创新。 1 鲶鱼效应的应用 1.1 鲶鱼效应在组织管理中的应用 美国通用汽车公司是世界上最大的汽车制造企业之一&#xff0c;它曾经面临着生产效率低下、员工缺乏积…

JAVAEE---计算机是如何组成的

计算机软件硬件 硬件是冯诺依曼体系结构&#xff0c;这个结构的精髓在于将存储和执行分开。 这里存储器内存外存&#xff08;硬盘&#xff0c;u盘&#xff0c;光碟等&#xff09; cpu是计算机的大脑&#xff0c;是计算机最核心的地方。 cpu中央处理&#xff1a;进行算术运算…

【Linux】-进程间通信-匿名管道通信(以及模拟一个进程池)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

16.live555mediaserver-保活机制

live555工程代码路径 live555工程在我的gitee下&#xff08;doc下有思维导图、drawio图&#xff09;&#xff1a; live555 https://gitee.com/lure_ai/live555/tree/master 章节目录链接 0.前言——章节目录链接与为何要写这个&#xff1f; https://blog.csdn.net/yhb1206/art…

.Net中Redis的基本使用

前言 Redis可以用来存储、缓存和消息传递。它具有高性能、持久化、高可用性、扩展性和灵活性等特点&#xff0c;尤其适用于处理高并发业务和大量数据量的系统&#xff0c;它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等。 Redis的使用 安装包Ser…

Windows网络「SSL错误问题」及解决方案

文章目录 问题方案 问题 当我们使用了神秘力量加持网络后&#xff0c;可能会和国内的镜像源网站的之间发生冲突&#xff0c;典型的有 Python 从网络中安装包&#xff0c;如执行 pip install pingouin 时&#xff0c;受网络影响导致无法完成安装的情况&#xff1a; pip config…

【小沐学GIS】电子海图OpenCPN源代码编译和运行(VS2017 + Win10)

1、简介 免费的开源海图仪和船用GPS导航软件 https://opencpn.org/ 1.1 OpenCPN概述 OpenCPN是一款自由软件&#xff08;GPLv2&#xff09;&#xff0c;用于创建简洁的海图绘图仪和导航软件&#xff0c;可以在航行过程中使用或者作为计划工具。OpenCPN提供大量免费海图下载&a…

一文总结MySQL的指令是如何工作的

当你输入一条MySQL指令时候有没有想过会发生什么&#xff1f; 建立连接 首先你得先连到数据库上才行&#xff0c;这又分为长连接和短链接&#xff0c;短链接就是你查询一次就断开连接&#xff0c;长连接是你可以多次查询直到主动断开连接&#xff08;也可能被杀死进程&#x…

飞鼠异地组网工具实战之访问k8s集群内部服务

飞鼠异地组网工具实战之访问k8s集群内部服务 一、飞鼠异地组网工具介绍1.1 飞鼠工具简介1.2 飞鼠工具官网 二、本次实践介绍2.1 本次实践场景描述2.2 本次实践前提2.3 本次实践环境规划 三、检查本地k8s集群环境3.1 检查k8s各节点状态3.2 检查k8s版本3.3 检查k8s系统pod状态 四…

局域网内Ubuntu上搭建Git服务器

1.在局域网内选定一台Ubuntu电脑作为Git服务端&#xff1a; (1).新建用户如为fbc&#xff0c;执行如下命令&#xff1a;需设置密码&#xff0c;此为fbc sudo adduser fbc (2).切换到fbc用户&#xff1a;需密码&#xff0c;此前设置为fbc su fbc (3).建一个空目录作为仓…

消息通讯-MQTT WebHookSpringBoot案例

一、EMQX WebHook介绍 1、EMQX WebHook 是由 emqx_web_hook (opens new window)插件提供的将EMQX中的钩子事件通知到某个Web服务的功能。 2、WebHook 的内部实现是基于钩子&#xff0c;借助 Webhook 可以完成设备在线、上下线记录&#xff0c;订阅与消息存储、消息送达确认等诸…

【Spring Boot 源码学习】Banner 信息打印流程

Spring Boot 源码学习系列 Banner 信息打印流程 引言往期内容主要内容1. printBanner 方法2. 关闭 Banner 信息打印3. SpringApplicationBannerPrinter 类3.1 LOG 模式打印3.1.1 getBanner 方法3.1.1.1 新建 Banners3.1.1.2 添加 ImageBanner3.1.1.3 添加 ResourceBanner3.1.1.…

Flume的安装部署及常见问题解决

1.安装地址 &#xff08;1&#xff09; Flume官网地址&#xff1a;http://flume.apache.org/ &#xff08;2&#xff09;文档查看地址&#xff1a;http://flume.apache.org/FlumeUserGuide.html &#xff08;3&#xff09;下载地址&#xff1a;http://archive.apache.org/dist…

RVC从入门到......

RVC变声器官方教程&#xff1a;10分钟克隆你的声音&#xff01;一键训练&#xff0c;低配显卡用户福音&#xff01;_哔哩哔哩_bilibili配音&#xff1a;AI逍遥散人&#xff08;已授权&#xff09;关注UP主并私信"RVC"&#xff08;三个字母&#xff09;自动获取一键训…

PS 颜色取样器标尺工具 基本使用讲解

上文 PS 吸管工具基本使用方法 我们讲完了 吸管工具 那么 我们继续 打开ps先 接着 我们选择这个 颜色取样器工具 选择之后 我们鼠标在图像上随便点一下 就会出现一个标记 然后 我们可以点多几个地方 边上的信息面板就会输出 点1 和 点2 甚至 多个 点3 点4 的 颜色 RGB代码 …

Python 如何实现备忘录设计模式?什么是备忘录设计模式?Python 备忘录设计模式示例代码

什么是备忘录&#xff08;Memento&#xff09;设计模式&#xff1f; 备忘录&#xff08;Memento&#xff09;设计模式是一种行为型设计模式&#xff0c;用于捕获一个对象的内部状态&#xff0c;并在对象之外保存这个状态&#xff0c;以便在需要时恢复对象到先前的状态。这种模…