package edu.tsinghua.kiosk.device;
import edu.tsinghua.kiosk.datapackage.PackageBP;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;
/**
* 遗留问题是当线程重建之前一定要确定串口是关闭的,如果上次使用了串口但是没有关闭就想再次使用,那是要出问题的!
* 血压串口处理类
* @param portID 定义串口ID对象
* @param serialPort 定义串口对象
* @param inputStream 定义输入流对象
* @param serialPort 定义缓冲区对象
* @param DeviceCommandBP dcBP 对程序与设备之间的交互进行同步的缓冲类,消费者生产者机制
* @param String mode 设备的状态 on/off ,前台触发开始测量,设备设置为on,开始发送“开始测量”命令
* @param boolean isOpen 端口的状态标志 true为打开,false为关闭
* @param byte[] readBuffer; 程序接收数据的缓冲区,多余部分为0
* @param byte[] tempBuffer; readBuffer去掉多余部分的0后转存在此字节数组,而后进行命令匹配
* @author liuwei
*
*/
public class CommBP implements SerialPortEventListener { //SerialPortEventListener 监听器,我的理解是独立开辟一个线程监听串口数据
static CommPortIdentifier portId; //串口通信管理类
InputStream inputStream; //从串口来的输入流
OutputStream outputStream;//向串口输出的流
SerialPort serialPort; //串口的引用
private String mode;//设备的状态,on/off
DeviceCommandBP dcBP;
boolean isOpen;
byte[] readBuffer;
byte[] tempBuffer;
public CommBP() {
dcBP = new DeviceCommandBP();
readBuffer = new byte[1000];
setMode("off");
isOpen = false;
}
public void init(){
if(isOpen){ //有待验证
close();
}
try {
portId = CommPortIdentifier.getPortIdentifier("/dev/ttyS0");
serialPort = (SerialPort) portId.open("myapp", 2000);//打开串口名字为myapp,延迟为2毫秒
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
serialPort.addEventListener(this); //给当前串口天加一个监听器
isOpen = true;
} catch (NoSuchPortException e) {
//没有这个串口
e.printStackTrace();
System.out.println("没有此串口");
}catch (PortInUseException e) {
//如果端口正在被使用,已成处理
}catch (TooManyListenersException e) {
//
}catch (IOException e) {
//
}
serialPort.notifyOnDataAvailable(true); //当有数据时通知
try {
serialPort.setSerialPortParams(9600, //端口波特率是9600bps
SerialPort.DATABITS_8,//数据位是8位
SerialPort.STOPBITS_1,//停止位是1位
SerialPort.PARITY_NONE);//没有校验位
} catch (UnsupportedCommOperationException e) {
//如果该端口操作不被支持,异常处理
}
}
public void serialEvent(SerialPortEvent event) {
//SerialPortEventListener 的方法,监听的时候会不断执行
switch (event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE://当有可用数据时读取数据,并且给串口返回数据
receiveData();
break;
}
}
public void receiveData(){
int numBytes = 0;
try {
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
System.out.println("ttyS0:程序读入的字节数是:"+numBytes);
}
} catch (IOException e) {}
tempBuffer = new byte[numBytes];
for(int i=0;i<numBytes;i++){
tempBuffer[i] = readBuffer[i];
}
dcBP.produce(); //设备返回上次命令的回应后,将flag设为ON,代表设备可以接收接下来的操作命令
}
/**
* 向设备输入“开始”命令,开始测量
* 第一个dcBP.consume(); 将DeviceCommand设置为OFF,代表等待设备回应
* 第二个dcBP.consume();等待设备回应信息,判断如果设备“开始测量”成功则返回true,否则返回false
*/
public boolean startMeasure(){
char[] ackc= {0x16,0x16,0x01,0x30,0x30,0x06};
byte[] ackb = new String(ackc).getBytes();
try {
dcBP.consume();
char[] startc= {0x16,0x16,0x01,0x30,0x30,0x02,0x53,0x54,0x03,0x07};
byte[] startb = new String(startc).getBytes();
outputStream.write(startb);
System.out.println("ttyS0:程序向设备发送启动命令"+new String(startb));
} catch (IOException e) {
e.printStackTrace();
}
dcBP.consume();
if(this.equal(tempBuffer,ackb,tempBuffer.length)){
System.out.println("ttyS0:程序部分确认匹配成功,开始发送接收数据命令");
return true;
}
else
return false;
}
/**
* 向设备发送“读取血压”命令,读取血压值数据
*/
public void readRB(){
try {
// dcBP.consume();
char[] readc= {0x16,0x16,0x01,0x30,0x30,0x02,0x52,0x42,0x03,0x10};
byte[] readb = new String(readc).getBytes();
outputStream.write(readb);
System.out.println("ttyS0:readRB向设备发送读取数据命令");
} catch (IOException e) {
e.printStackTrace();
}
dcBP.consume();//等待设备发送血压值数据
}
// /**
// * 向设备发送“读取脉压”命令,读取血压值数据
// */
// public void readRP(){
// try {
// dcBP.consume();
// char[] a= {0x16,0x16,0x01,0x30,0x30,0x02,0x52,0x50,0x03,0x02};
// byte[] b = new String(a).getBytes();
// outputStream.write(b);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
/**
* 向设备输入"停止测量"命令,结束测量
* “停止测量”命令属于强制命令,不管flag处于何种状态,都可以发送命令
* 并且把flag设为ON,使设备可以接收下次的“开始测量”命令
*/
public void stopMeasure(){
try {
// dcBP.consume();
char[] a= {0x16,0x16,0x01,0x30,0x30,0x02,0x53,0x50,0x03,0x03};
byte[] b = new String(a).getBytes();
outputStream.write(b);
dcBP.produce();
} catch (IOException e) {
e.printStackTrace();
}
}
public PackageBP pack(){
//解析
// int pre = 0;
// for(int i=0;i<1000;i++){
// if(((char)this.readBuffer[i]) == 'a' && pre != (i-1)){
// pre = i;
// }else if(((char)this.readBuffer[i]) == 'a' && pre == (i-1)){
// break;
// }
// }
//打包
System.out.println("ttyS0:pack程序打包完成");
this.setMode("off");
System.out.println("本次测量结束,程序停止发送命令,直到下次触发");
return new PackageBP(1,1,1);
}
/**
* 判断设备发送过来的确认信息
*
*/
public boolean equal(byte[] a,byte[] b,int length){
for(int i=0;i<length;i++){
if(a[i] != b[i]){
return false;
}
}
return true;
}
/**
* 能否实现线程异常终止后进行重建时,关闭上次未关闭的串口,未找到合适的触发条件,有待验证
*/
public void close(){
serialPort.notifyOnDataAvailable(false);
serialPort.removeEventListener();
if (isOpen){
try{
inputStream.close();
outputStream.close();
serialPort.close();
isOpen = false;
} catch (IO
fxly0401
- 粉丝: 9
- 资源: 7
最新资源
- 永磁同步电机直接转矩控制DTC仿真模型,三相PMSM直接转矩控制matlab仿真算法,基于matlab simulink搭建 附参考资料,简单电子资料
- 2025年春节烟花特效html
- Python_利用AI大模型一键生成高清短视频 Generate short videos with one clic.zip
- Python_连接到任何数据源,轻松可视化仪表板和共享您的数据.zip
- Python_利用GDB开发和逆向工程变得容易.zip
- 永磁同步电机PMSMsimulink仿真,模型参考自适应方法在线辩识转动惯量,可选变增益,纯手工搭建,附参考资料
- Python_领先的ETL ELT数据管道数据集成平台,从api数据库文件到数据仓库、数据湖、数据湖,包括自托管和云托.zip
- Python_令人敬畏的开源启动替代知名SaaS产品列表.zip
- Python_流氓接入点框架.zip
- Python_马尔:口齿不清.zip
- Python_免费超快副驾驶替代Vim和Neovim.zip
- Python_麦考夫核心麦考夫人工智能平台.zip
- Python_每个人的开源机器学习框架.zip
- Python_免费的计算机编程类中文书籍欢迎投稿.zip
- 光伏逆变器仿真模型,boost加NPC拓扑结构,基于MATLAB Simulink建模仿真 具备中点平衡SVPWM控制,正负序分离控制,可以进行功率调度仿真 仿真模型使用MATLAB 2017b搭
- Python_免费和开源企业资源规划ERP.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈