java-串口通讯-连接硬件

串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。典型地,串口用于ASCII码字符的传输。通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

上面说的,对于非专业人士来说,都是多余的话
一句话简单的说:串口通讯,一般情况下指windows电脑(或者一些安卓系统,单片机系统)和硬件进行数据交互的协议(方式)(硬件指,扫码抢,扫码盒子,刷卡机,继电器等一些硬件)。

这些硬件一般通过串口线,或者是USB线, 如果不带USB线也可以通过转换成USB线的方式,和电脑连接。

举例几个场景,一个windows 系统的柜式机器,控制开门关门。
一个windows机器的闸机,控制开门关门,或者开灯关灯
一个扫码枪,想要获取扫码数据并处理扫码获得的数据。等等各种情况
我这里主要是以 继电器 和 扫码器两种情况为例子。

场景一:windows电脑控制继电器的开关**

这种场景主要是,windows主动发送串口指令到硬件,控制硬件的状态
淘宝上买了一个继电器
在这里插入图片描述
话不多说,直接上串口通讯代码
POM 依赖包

<dependency><groupId>com.fazecast</groupId><artifactId>jSerialComm</artifactId><version>2.9.0</version></dependency>
package com.hzsmk.serial.service;import com.fazecast.jSerialComm.SerialPort;
import com.hzsmk.common.exception.BusinessException;
import com.hzsmk.common.util.RString;public class SerialHander {private static final byte[] open = new byte[] {(byte) 0xA0,0x01,0x01,(byte) 0xA2};private static final byte[] close = new byte[] {(byte) 0xA0,0x01,0x00,(byte) 0xA1};//private static final byte[] query = new byte[] {(byte) 0xA0,0x01,0x05,(byte) 0xA6};private static SerialPort connectPort(String portDescription,String systemPortName) {// 列举所有可用的串口SerialPort[] commPorts = SerialPort.getCommPorts();for (SerialPort port : commPorts) {String des = port.getPortDescription();System.out.println(des);if(RString.isNotBlank(portDescription) &&  !portDescription.equals(des)) {//端口描述不為空,需要检验 continue;}String portname = port.getSystemPortName();if(RString.isNotBlank(systemPortName) &&  !systemPortName.equals(portname)) {//端口不為空,需要检验 continue;}return port;}throw new BusinessException("未找到设备:"+portDescription+",端口"+systemPortName);}/*** 发送一个开关信号* @param portDescription* @param systemPortName* @throws InterruptedException */public static void hand(String portDescription,String systemPortName) {//获取可用端口SerialPort serialPort = connectPort(portDescription, systemPortName);try {//连接if(!serialPort.isOpen()) {boolean isopen = serialPort.openPort();if(!isopen) {//连接失败throw new BusinessException("连接设备失败,请重试,设备:"+portDescription+",端口"+systemPortName); }}//发送2个数据过去serialPort.writeBytes(open, open.length);Thread.sleep(300);//随眠200毫秒 关闭serialPort.writeBytes(close, close.length);}catch (InterruptedException e) {e.printStackTrace();} catch (BusinessException e) {throw e;} finally {// 关闭串口serialPort.closePort();}}}

1、核心代码是,查询出已经连接的串口设备,SerialPort.getCommPorts();

2、打开串口设备:serialPort.openPort();

3、发送串口数据:serialPort.writeBytes(close, close.length);

场景2,被动接受扫码器扫码获得的数据

这种场景主要是,串口支持被动获取数据。,
要解决的问题1: 要动态监测串口设备是否已失去连接,
2:串口设备支持自动重连。

package com.hzsmk.serial.service;import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;import com.fazecast.jSerialComm.SerialPort;
import com.hzsmk.common.exception.BusinessException;
import com.hzsmk.common.util.RString;@Service
public class ScanHander {private static SerialPort scanSerialPort = null;public static String scanSerialPortName = "";@Value("${serial.scanportdes}")String envScanPortdes;/*** 每5秒检查一次*/@Scheduled(cron = "0/5 * * * * *")public void scheduled(){System.out.println("定时检查设备是否运行中");if(scanSerialPort == null || !scanSerialPort.isOpen() || scanSerialPort.bytesAvailable() == -1) {//主要依赖  bytesAvailable 参数,  isopen基本无用scanSerialPortName = "";//重置信号参数synchronized (scanSerialPortName) {try {if(RString.isBlank(envScanPortdes)) {createListen("SM-2D PRODUCT USB UART","");}else {createListen(envScanPortdes,"");}} catch (Exception e) {e.printStackTrace();}}}}private static SerialPort connectPort(String portDescription,String systemPortName) {try {// 列举所有可用的串口SerialPort[] commPorts = SerialPort.getCommPorts();for (SerialPort port : commPorts) {String des = port.getPortDescription();System.out.println(des);if(RString.isNotBlank(portDescription) &&  !portDescription.equals(des)) {//端口描述不為空,需要检验 continue;}String portname = port.getSystemPortName();if(RString.isNotBlank(systemPortName) &&  !systemPortName.equals(portname)) {//端口不為空,需要检验 continue;}return port;}} catch (Exception e) {// TODO: handle exception}throw new BusinessException("获取设备异常,请重试");}public static void createListen(String portDescription,String systemPortName) {if(scanSerialPort != null) {//如果是断线重连scanSerialPort.closePort();}//获取可用端口scanSerialPort = connectPort(portDescription, systemPortName);try {scanSerialPortName = scanSerialPort.getSystemPortName()+":"+scanSerialPort.getPortDescription();scanSerialPort.addDataListener(new ScanDatLislen());boolean isopen = scanSerialPort.openPort();if(!isopen) {//连接失败throw new BusinessException("连接设备失败,请重试,设备:"+portDescription+",端口"+systemPortName); }System.out.println("open......");} catch (BusinessException e) {throw e;}  catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {//scanSerialPort.closePort();}}
}

##监听函数

package com.hzsmk.serial.service;import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.hzsmk.common.util.RString;import cn.hutool.core.swing.RobotUtil;public class ScanDatLislen implements SerialPortDataListener{@Overridepublic int getListeningEvents() {// TODO Auto-generated method stubreturn  SerialPort.LISTENING_EVENT_DATA_RECEIVED;}@Overridepublic void serialEvent(SerialPortEvent event) {System.out.println("监听执行 LISTENING_EVENT_DATA_RECEIVED");// 读取数据try {byte[] buffer = event.getReceivedData(); // 缓冲区大小if (buffer.length > 0) {// 将读取的字节转换为字符串String data = new String(buffer, 0, buffer.length, "UTF-8");if(!data.startsWith("QRCODE") || !data.startsWith("SRC")) {String code = RString.byte2hex(buffer);if(code.startsWith("810169")) {data = code;}}RobotUtil.keyPressString(data);}Thread.sleep(1000);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}}

核心逻辑,1、开启定时任务,定时检测设备是否在线

重点,重点,重点,重点,重点,重点,重点,重点,重点,重点,重点,重点,这里有一个比较恶心的API,SerialPort.isOpen() 这个API,在打开过端口之后,设备掉线或者插口拔掉后,它依然是open状态。 这里的OPEN时间上只能说是 本地开启的服务是否open ,并不能检测设备的在线状态。
所以实际上有用的 SerialPort.bytesAvailable() ,查看是否有byte数据可用。用这个检测设备是否在线

2、开启监听函数,可以监听端口或者数据接收的事件addDataListener

SerialPort.LISTENING_EVENT_DATA_RECEIVED; 有很多种状态,目前业务需求监听数据响应状态。

3、监听到数据后,可以把数据传输给第三方接口,或者保存下来,但是如果要和WEB界面交互,这里有一个小技巧,可以把数据张贴到键盘聚焦点,使用hutool工具RobotUtil.keyPressString(data); ,, 简单的说就是把串口通讯又转换为了 usb-kwb-hid通讯了。

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

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

相关文章

经典面试题之滑动窗口专题

class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {// 长度最小的子数组 // 大于等于 targetint min_len INT32_MAX;// 总和int sum 0;int start 0; // 起点for(int i 0; i< nums.size(); i) {sum nums[i];while(sum > targe…

拥抱新质生产力,助力新型工业化!CMM电子展暨IARS机器人展5月东莞盛大起航

2024年5月15-17日&#xff0c;东浩兰生会展集团旗下CMM电子展&#xff06;IARS机器人展将在广东现代国际展览中心&#xff08;东莞厚街&#xff09;举办。展会面积达50000平方米&#xff0c;展示品牌700余个&#xff0c;同期论坛峰会30余场&#xff0c;预计专业观众超50000人次…

error: pathspec ‘XXX‘ did not match any file(s) known to git

使用vscode&#xff0c;在本地开发切换分支时&#xff0c;报以下错误&#xff1a; error: pathspec XXX did not match any file(s) known to git 该问题是由于没有对应分支的原因。 首先使用一下命令&#xff0c;查看本地及远程的所有分支。 git branch -a 若没有对应的分…

极验4 一键解混淆

提示&#xff01;本文章仅供学习交流&#xff0c;严禁用于任何商业和非法用途&#xff0c;未经许可禁止转载&#xff0c;禁止任何修改后二次传播&#xff0c;如有侵权&#xff0c;可联系本文作者删除&#xff01; AST简介 AST&#xff08;Abstract Syntax Tree&#xff09;&a…

Linux专栏03:使用Xshell远程连接云服务器

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 使用Xshell远程连接云服务器 编号&#xff1a;03 文章目录 使用Xsh…

Jenkins集成Kubernetes 部署springboot项目

文章目录 准备部署的yml文件Harbor私服配置测试使用效果Jenkins远程调用参考文章 准备部署的yml文件 apiVersion: apps/v1 kind: Deployment metadata:namespace: testname: pipelinelabels:app: pipeline spec:replicas: 2selector:matchLabels:app: pipelinetemplate:metada…

软件设计师-应用技术-数据结构及算法题4

考题形式&#xff1a; 第一题&#xff1a;代码填空 4-5空 8-10第二题&#xff1a;时间复杂度 / 代码策略第三题&#xff1a;拓展&#xff0c;跟一组数据&#xff0c;把数据带入代码中&#xff0c;求解 基础知识及技巧&#xff1a; 1. 分治法&#xff1a; 基础知识&#xff1…

语音识别--降噪

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

uniapp的app端推送功能,不使用unipush

1&#xff1a;推送功能使用htmlPlus实现&#xff1a;地址HTML5 API Reference (html5plus.org) 效果图&#xff1a; 代码实现&#xff1a; <template><view class"content"><view class"text-area"><button click"createMsg&q…

什么是DDoS攻击?DDoS攻击的原理是什么?

一、DDoS攻击概念 DDoS攻击又叫“分布式拒绝服务”(Distributed DenialofService)攻击&#xff0c;它是一种通过控制大量计算机、物联网终端或网络僵尸&#xff08;Zombie&#xff09;来向目标网站发送大量请求&#xff0c;从而耗尽其服务器资源&#xff0c;导致正常用户无法访…

设计网页用什么软件

在设计网页时&#xff0c;可以使用多种软件来完成不同的任务。以下是一些常用的网页设计软件&#xff0c;以及它们的特点和用途。 1. Adobe Photoshop&#xff1a; Adobe Photoshop 是一款功能强大的图像编辑软件。在网页设计中&#xff0c;它常用于创建和编辑网页所需的图像、…

手动配置dns后网速变慢

之前因为自动的dns能上qq但打不开网页&#xff0c;就手动设置了一个&#xff0c;结果近些天时不时出现网页图片加载慢的问题&#xff0c;影响到我看美女图片了&#xff0c;是可忍熟不可忍 测了下网速&#xff0c;很快&#xff0c;下载上传都是三位数的&#xff0c;那显然不是网…

RabbitMQ是如何保证消息可靠性的?——Java全栈知识(16)

RabbitMQ 的消息不可靠也就是 RabbitMQ 消息丢失只会发生在以下几个方面&#xff1a; 生产者发送消息到 MQ 或者 Exchange 过程中丢失。Exchange 中的消息发送到 MQ 中丢失。消息在 MQ 或者 Exchange 中服务器宕机导致消息丢失。消息被消费者消费的过程中丢失。 大致就分为生…

Star-CCM+分配零部件至区域1-将所有零部件分配至区域

前言 Star-CCM中&#xff0c;在划分网格之前需要将零部件分配至区域&#xff0c;然后才可以划分网格。如下图1所示&#xff0c;分配零部件至区域需要选择创建区域的方式、创建边界的方式以及交界面的类型。 图1 将零部件分配至区域 1 创建区域的方式选择 如下图2所示&#x…

基于Spring Boot的家具网站设计与实现

基于Spring Boot的家具网站设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统前台主界面图&#xff0c;用户可进入家具网站可查看…

探索大模型能力--prompt工程

1 prompt工程是什么 1.1 什么是Prompt&#xff1f; LLM大语言模型终究也只是一个工具&#xff0c;我们不可能每个人都去训一个大模型&#xff0c;但是我们可以思考如何利用好大模型&#xff0c;让他提升我们的工作效率。就像计算器工具一样&#xff0c;要你算10的10倍&#x…

Java IO类之FilterOutputStream的研究与应用

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

RCE学习(一)

一.知识点 RCE&#xff1a;远程命令/代码执行漏洞&#xff0c;简称为RCE漏洞&#xff0c;可以直接向服务器后台远程注入操作系统的命令或者代码&#xff0c;从而拿到服务器后台的权限。RCE分为远程执行命令&#xff08;执行ping命令&#xff09;和远程代码执行eval 简单来说就…

VMware导入ova/ovf虚拟机文件

1.文件-打开-ova文件 2.为新虚拟机起名称 3.等待导入 4.导入完成&#xff0c;可以开始使用 参考链接&#xff1a;VMware导入ova/ovf虚拟机文件

浅谈Session和Cookie

各位大佬光临寒舍&#xff0c;希望各位能赏脸给个三连&#xff0c;谢谢各位大佬了&#xff01;&#xff01;&#xff01; 目录 1.Cookie 2.Sesssion&#xff08;会话&#xff09; 3.Session和Cookie的联系 4.总结 1.Cookie Cookie是客户端存储数据的机制&#xff0c;一般是…