版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Miranda_ymz/article/details/86542594
不解释了直接贴代码。
(连接的仿真软件,也可以直接连接现实的串口,改一下发送和接收的数据形式就好了)
直接套用会有问题,1、环境配置问题 2、包的问题 3、数据库连接的是我自己数据库
调试了很久,然后在课设和实训中都用到了,主要是要耐心的读程序明白每个模块的功能。个人写的时候也是调了很久的bug,也配置了很多参数。从下java加包,修改代码,采集数据,发送控制命令,连接数据库等。
一些实验中的图片:
1、主程序
package serialPort;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import gnu.io.SerialPort;
import serialException.ExceptionWriter;
/**
* 主程序
* @author zhong
*
*/
public class Client extends Frame{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 800;
public static final int HEIGHT = 620;//程序界面高度
public static final int LOC_X = 200;//程序界面出现位置(横坐标)
public static final int LOC_Y = 70;//程序界面出现位置(纵坐标)
Color color = Color.WHITE;
Image offScreen = null; //用于双缓冲
//设置window的icon(这里我自定义了一下Windows窗口的icon图标,因为实在觉得哪个小咖啡图标不好看 = =)
Toolkit toolKit = getToolkit();
//Image icon = toolKit.getImage(Client.class.getResource("computer.png"));
Image background = toolKit.getImage("timg.jpg");
//持有其他类
DataView dataview = new DataView(this); //主界面类(显示监控数据主面板)
/**
* 主方法
* @param args
* //
*/
public static void main(String[] args) {
new Client().launchFrame();
}
/**
* 显示主界面
*/
public void launchFrame() {
this.setBounds(LOC_X, LOC_Y, WIDTH, HEIGHT); //设定程序在桌面出现的位置
this.setTitle("农业节能灌溉项目"); //设置程序标题
// this.setIconImage(icon);
this.setBackground(Color.white); //设置背景色
this.addWindowListener(new WindowAdapter() {
//添加对窗口状态的监听
public void windowClosing(WindowEvent arg0) {
//当窗口关闭时
System.exit(0); //退出程序
}
});
this.addKeyListener(new KeyMonitor()); //添加键盘监听器
this.setResizable(false); //窗口大小不可更改
this.setVisible(true); //显示窗口
new Thread(new RepaintThread()).start(); //开启重画线程
}
/**
* 画出程序界面各组件元素
*/
public void paint(Graphics g) {
Color c = g.getColor();
g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
g.setFont(new Font("", Font.BOLD, 40));
g.setColor(Color.black);
g.drawString("欢迎来到农业节水灌溉监控系统", 40, 280);
g.setFont(new Font("", Font.ITALIC, 26));
g.setColor(Color.BLACK);
g.drawString("Version:3.0 Author By:DeathY", 280, 340);
g.setFont(new Font("", Font.BOLD, 30));
g.setColor(color);
g.drawString("————点击Enter键进入实时数据区————", 100, 480);
//使文字 "————点击Enter键进入主界面————" 黑白闪烁
if (color == Color.WHITE) color = Color.black;
else if (color == color.BLACK) color = Color.white;
}
/**
* 双缓冲方式重画界面各元素组件
*/
public void update(Graphics g) {
if (offScreen == null) offScreen = this.createImage(WIDTH, HEIGHT);
Graphics gOffScreen = offScreen.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0, WIDTH, HEIGHT); //重画背景画布
this.paint(gOffScreen); //重画界面元素
gOffScreen.setColor(c);
g.drawImage(offScreen, 0, 0, null); //将新画好的画布“贴”在原画布上
}
/*
* 内部类形式实现对键盘事件的监听
*/
private class KeyMonitor extends KeyAdapter {
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_ENTER) { //当监听到用户敲击键盘enter键后执行下面的操作
setVisible(false); //隐去欢迎界面
dataview.setVisible(true); //显示监测界面
dataview.dataFrame(); //初始化监测界面
}
}
}
/*
* 重画线程(每隔250毫秒重画一次)
*/
private class RepaintThread implements Runnable {
public void run() {
while(true) {
//SerialTool.sendToPort(serialPort,"");//关闭排水管
repaint();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
//重画线程出错抛出异常时创建一个Dialog并显示异常详细信息
String err = ExceptionWriter.getErrorInfoFromException(e);
JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
}
2、数据显示以及处理
package serialPort;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.TooManyListenersException;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import USEFULL.Tran;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import serialException.*;
/**
* 监测数据显示类
*/
public class DataView extends Frame {
private static final long serialVersionUID = 1L;
Client client = null;
private List<String> commList = null; // 保存可用端口号
private SerialPort serialPort = null; // 保存串口对象
private controlJDQ JDQ;//
private Smoke smo;
private static Tran tran;
private Font font = new Font("", Font.BOLD, 25);
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
//private long last1=System。currentTimeMillis()
private Label tem = new Label("暂无数据", Label.CENTER); // 温度
private Label hum = new Label("暂无数据", Label.CENTER); // 湿度
private Label pa = new Label("暂无数据", Label.CENTER); // 压强
private Label moke = new Label("一切正常", Label.CENTER); // 雨量
private Label Photo = new Label("暂无数据", Label.CENTER); // 风速
private Label LED = new Label("暂无数据", Label.CENTER); // LED,显示
// JLabel location = new JLabel("地名:");
public TextField temup = new TextField("26℃");
public TextField temdown = new TextField("21℃");
public TextField humup = new TextField("60%");
public TextField humdown = new TextField("40%");
private Choice commChoice = new Choice(); // 串口选择(下拉框)
private Choice bpsChoice = new Choice(); // 波特率选择
private Button openSerialButton = new Button("打开串口");
Image offScreen = null; // 重画时的画布
// 设置window的icon
Toolkit toolKit = getToolkit();
// Image icon = toolKit.getImage(DataView.class.getResource("timg.jpg"));
Image background = toolKit.getImage("1.jpg");
/**
* 类的构造方法
*
* @param client
*/
public DataView(Client client) {
this.client = client;
commList = SerialTool.findPort(); // 程序初始化时就扫描一次有效串口
}
/**
* 主菜单窗口显示; 添加Label、按钮、下拉条及相关事件监听;
*/
public void dataFrame() {
this.setBounds(client.LOC_X, client.LOC_Y, client.WIDTH, client.HEIGHT);
this.setTitle("农业节水灌溉项目");
// this.setIconImage(icon);
this.setBackground(Color.white);
this.setLayout(null);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent arg0) {
if (serialPort != null) {
// 程序退出时关闭串口释放资源
SerialTool.closePort(serialPort);
}
System.exit(0);
}
});
tem.setBounds(140, 103, 225, 50);
tem.setBackground(Color.black);
tem.setFont(font);
tem.setForeground(Color.white);
add(tem);
hum.setBounds(520, 103, 225, 50);
hum.setBackground(Color.black);
hum.setFont(font);
hum.setForeground(Color.white);
add(hum);
pa.setBounds(140, 193, 225, 50);
pa.setBackground(Color.black);
pa.setFont(font);
pa.setForeground(Color.white);
add(pa);
moke.setBounds(520, 193, 225, 50);
moke.setBackground(Color.black);
moke.setFont(font);
moke.setForeground(Color.white);
add(moke);
Photo.setBounds(140, 283, 225, 50);
Photo.setBackground(Color.black);
Photo.setFont(font);
Photo.setForeground(Color.white);
add(Photo);
LED.setBounds(520, 283, 225, 50);// 改为led
LED.setBackground(Color.black);
LED.setFont(font);
LED.setForeground(Color.white);
add(LED);
temup.setBounds(110, 500, 90, 20);// 改为led
add(temup);
temdown.setBounds(110, 540, 90, 20);// 改为led
add(temdown);
humup.setBounds(650, 500, 90, 20);// 改为led
add(humup);
humdown.setBounds(650, 540, 90, 20);// 改为led
add(humdown);
// 添加串口选择选项
commChoice.setBounds(160, 397, 200, 200);
// 检查是否有可用串口,有则加入选项中
if (commList == null || commList.size() < 1) {
JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);
} else {
for (String s : commList) {
commChoice.add(s);
}
}
add(commChoice);
// 添加波特率选项
bpsChoice.setBounds(526, 396, 200, 200);
bpsChoice.add("1200");
bpsChoice.add("2400");
bpsChoice.add("4800");
bpsChoice.add("9600");
bpsChoice.add("14400");
bpsChoice.add("19200");
bpsChoice.add("115200");
add(bpsChoice);
// 添加打开串口按钮
openSerialButton.setBounds(250, 490, 300, 50);
openSerialButton.setBackground(Color.lightGray);
openSerialButton.setFont(new Font("微软雅黑", Font.BOLD, 20));
openSerialButton.setForeground(Color.darkGray);
add(openSerialButton);
// 添加打开串口按钮的事件监听
openSerialButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 获取串口名称
String commName = commChoice.getSelectedItem();
// 获取波特率
String bpsStr = bpsChoice.getSelectedItem();
// 检查串口名称是否获取正确
if (commName == null || commName.equals("")) {
JOptionPane.showMessageDialog(null, "没有搜索到有效串口!", "错误", JOptionPane.INFORMATION_MESSAGE);
} else {
// 检查波特率是否获取正确
if (bpsStr == null || bpsStr.equals("")) {
JOptionPane.showMessageDialog(null, "波特率获取错误!", "错误", JOptionPane.INFORMATION_MESSAGE);
} else {
// 串口名、波特率均获取正确时
int bps = Integer.parseInt(bpsStr);
try {
// 获取指定端口名及波特率的串口对象
serialPort = SerialTool.openPort(commName, bps);
// 在该串口对象上添加监听器
SerialTool.addListener(serialPort, new SerialListener());
// 监听成功进行提示
JOptionPane.showMessageDialog(null, "监听成功,稍后将显示监测数据!", "提示",
JOptionPane.INFORMATION_MESSAGE);
} catch (SerialPortParameterFailure | NotASerialPort | NoSuchPort | PortInUse
| TooManyListeners e1) {
// 发生错误时使用一个Dialog提示具体的错误信息
JOptionPane.showMessageDialog(null, e1, "错误", JOptionPane.INFORMATION_MESSAGE);
}
}
}
}
});
this.setResizable(false);
new Thread(new RepaintThread()).start(); // 启动重画线程
}
/**
* 画出主界面组件元素 加上设置值。温度上下限,湿度上下限
*/
public void paint(Graphics g) {
Color c = g.getColor();
g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 温度: ", 45, 130);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 湿度: ", 425, 130);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 水压: ", 45, 220);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 烟雾: ", 425, 220);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" 光照: ", 45, 310);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString(" LED: ", 425, 310);
g.setColor(Color.gray);
g.setFont(new Font("微软雅黑", Font.BOLD, 20));
g.drawString(" 串口选择: ", 45, 410);
g.setColor(Color.gray);
g.setFont(new Font("微软雅黑", Font.BOLD, 20));
g.drawString(" 波特率: ", 425, 410);
// 温度
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 15));
g.drawString(" 温度上限: ", 25, 510);
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 15));
g.drawString(" 温度下限: ", 25, 550);
// 湿度 是昂县
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 15));
g.drawString(" 湿度上限: ", 570, 510);
// 湿度下限
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.BOLD, 15));
g.drawString(" 湿度下限: ", 570, 550);
}
/**
* 双缓冲方式重画界面各元素组件
*/
public void update(Graphics g) {
if (offScreen == null)
offScreen = this.createImage(Client.WIDTH, Client.HEIGHT);
Graphics gOffScreen = offScreen.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.white);
gOffScreen.fillRect(0, 0, Client.WIDTH, Client.HEIGHT); // 重画背景画布
this.paint(gOffScreen); // 重画界面元素
gOffScreen.setColor(c);
g.drawImage(offScreen, 0, 0, null); // 将新画好的画布“贴”在原画布上
}
/**
*
* 字节数组转16进制
*
* @param bytes 需要转换的byte数组
*
* @return 转换后的Hex字符串
*
*/
/*
* 重画线程(每隔30毫秒重画一次)
*/
private class RepaintThread implements Runnable {
public void run() {
while (true) {
// 调用重画方法
try {
SerialTool.sendToPort(serialPort, "A53002FFFFFFFFFF5A");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
repaint();
// 扫描可用串口
commList = SerialTool.findPort();
if (commList != null && commList.size() > 0) {
// 添加新扫描到的可用串口
for (String s : commList) {
// 该串口名是否已存在,初始默认为不存在(在commList里存在但在commChoice里不存在,则新添加)
boolean commExist = false;
for (int i = 0; i < commChoice.getItemCount(); i++) {
if (s.equals(commChoice.getItem(i))) {
// 当前扫描到的串口名已经在初始扫描时存在
commExist = true;
break;
}
}
if (commExist) {
// 当前扫描到的串口名已经在初始扫描时存在,直接进入下一次循环
continue;
} else {
// 若不存在则添加新串口名至可用串口下拉列表
commChoice.add(s);
}
}
// 移除已经不可用的串口
for (int i = 0; i < commChoice.getItemCount(); i++) {
// 该串口是否已失效,初始默认为已经失效(在commChoice里存在但在commList里不存在,则已经失效)
boolean commNotExist = true;
for (String s : commList) {
if (s.equals(commChoice.getItem(i))) {
commNotExist = false;
break;
}
}
if (commNotExist) {
// System.out.println("remove" + commChoice.getItem(i));
commChoice.remove(i);
} else {
continue;
}
}
} else {
// 如果扫描到的commList为空,则移除所有已有串口
commChoice.removeAll();
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
String err = ExceptionWriter.getErrorInfoFromException(e);
JOptionPane.showMessageDialog(null, err, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
}
public static void wait_my() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/* 处理数据 */
private class SerialListener implements SerialPortEventListener {
/* 处理监控到的串口事件*/
public void serialEvent(SerialPortEvent serialPortEvent) {
Thread thread2 = new Thread (new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
SerialTool.sendToPort(serialPort, "A53002FFFFFFFFFF5A");
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//System.out.println("接收数据");
byte[] data = null;
try {
if (serialPort == null) {
JOptionPane.showMessageDialog(null, "串口对象为空!监听失败!", "错误", JOptionPane.INFORMATION_MESSAGE);
}
else {
data = SerialTool.readFromPort(serialPort); //读取数据 存入字节数组
//SerialTool.sendToPort(serialPort, "A54006FFFFFFFFFF5A"); //烟雾不灵敏每次单独发一下
//System.out.println(Tran.bytesToHex(data));
//data转为
// 自定义解析过程 你在实际使用过程中可以按照自己的需求在接收到数据后对数据进行解析
if (data == null || data.length < 1) { //检查数据是否读取正确
JOptionPane.showMessageDialog(null, "读取数据过程中未获取到有效数据!请检查设备或程序!", "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
else {
//十六进制
String dataOriginal =Tran.bytesToHex(data); //将字节数组数据转换位为保存了原始数据的字符串
String dataValid = ""; //有效数据 用来保存原始数据字符串去除最开头*号以后的字符串)
System.out.println("接收数据 "+dataOriginal);
//接收的数据不止18 位是18的倍数
int len=dataOriginal.length();
len=len/18;
while(len>0) {
len=len-1;
String dataOriginal1=dataOriginal.substring(len*18,len*18+18);
System.out.println(dataOriginal1);
String miao=temup.getText();
miao=miao.substring(0,miao.length()-1);
double tu=Double.parseDouble(miao);
miao=temdown.getText();
miao=miao.substring(0,miao.length()-1);
double td=Double.parseDouble(miao);
miao=humup.getText();
miao=miao.substring(0,miao.length()-1);
double hu=Double.parseDouble(miao);
miao=humdown.getText();
miao=miao.substring(0,miao.length()-1);
double hd=Double.parseDouble(miao);
//获取显示信息
miao=tem.getText(); //温度
double textTemp=0;
if(miao.matches("暂无数据")) textTemp=0;
else {
miao=miao.substring(0,miao.length()-1);
textTemp=Double.parseDouble(miao);
}
miao=hum.getText(); //湿度
double textHum=0;
if(miao.matches("暂无数据")) textHum=0;
else {
miao=miao.substring(0,miao.length()-1);
textHum=Double.parseDouble(miao);
}
miao=moke.getText(); //湿度
int textSmoke=0;
if(miao.matches("一切正常")) textSmoke=0;//没有问题
else {
textSmoke=1;//有问题
}
/*miao=Photo.getText(); //光照
double textPh=0;
if(miao.matches("暂无数据")) textPh=0;
else {
String str=miao.substring(0, miao.length()-3);
textPh=Double.parseDouble(str);
}*/ //暂时不处理
if (dataOriginal1.charAt(0) == 'b') { //当数据的第一个字符是*号时表示数据接收完成,开始解析
//发送给协调器 数据:A50000FFFFFFFFFF5A
//接收到B5200400000000FF5F--继电器的状态
//接收B53002001D0049FF5B--温湿度信息
String flag=dataOriginal1.substring(0,6);
//对于温湿度的处理
if(flag.matches("b53002")){
String temp=dataOriginal1.substring(8,10);//提取温度
String hump=dataOriginal1.substring(12,14);//提取湿度
Integer tt=Integer.parseInt(temp,16);
Integer hh=Integer.parseInt(hump, 16);
//System.out.println(tt);
if(tt<4000&&hh<10000) {
tem.setText(tt*1.0 + " ℃");//显示温度
hum.setText(hh*1.0 + " %");//显示湿度
String jdq=JDQ.tosend(serialPort,tt*1.0,hh*1.0,textSmoke,tu,td,hu,hd);
if(jdq!=null) LED.setText(jdq);
}
}
else if(flag.matches("eecc010201"))//关于光照的处理--暂时用不到
{//平均照度1000Lux以上。
String Ph=dataOriginal1.substring(10,14);
Integer pp=Integer.parseInt(Ph, 16);
if(pp>100) {
Photo.setText(pp+"Lux");
//这里可以对光强信息进行处理
}
}
//对于烟雾的处理
if(dataOriginal1.substring(0,8).matches("b5400601"))//接收的烟雾传感器的信息
{
startTime=endTime;
moke.setText("疑似烟雾,启动灭火");
smo.tosend(serialPort, textTemp, textHum, 1);
//System.out.println("光灯了");
}
else{
endTime=System.currentTimeMillis();
}
if(Math.abs(endTime-startTime)>=3000)
{
moke.setText("一切正常");
smo.tosend(serialPort,textTemp, textHum, 0);
}
}
}
}
}
} catch (ReadDataFromSerialPortFailure | SerialPortInputStreamCloseFailure e) {
JOptionPane.showMessageDialog(null, e, "错误", JOptionPane.INFORMATION_MESSAGE);
System.exit(0); //发生读取错误时显示错误信息后退出系统
} catch (SendDataToSerialPortFailure e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SerialPortOutputStreamCloseFailure e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread2.run();
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI: // 10 通讯中断
JOptionPane.showMessageDialog(null, "与串口设备通讯中断", "错误", JOptionPane.INFORMATION_MESSAGE);
break;
case SerialPortEvent.OE: // 7 溢位(溢出)错误
case SerialPortEvent.FE: // 9 帧错误
case SerialPortEvent.PE: // 8 奇偶校验错误
case SerialPortEvent.CD: // 6 载波检测
case SerialPortEvent.CTS: // 3 清除待发送数据
case SerialPortEvent.DSR: // 4 待发送数据准备好了
case SerialPortEvent.RI: // 5 振铃指示
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2 输出缓冲区已清空
break;
case SerialPortEvent.DATA_AVAILABLE: // 1 串口存在可用数据
break;
}
}
}
}
3、控制继电器(仿真软件带的,也可以不用自己将处理的数据,进行其他操作)
package serialPort;
import java.util.Arrays;
import OutFile.Connect;
import OutFile.ConnectWLW;
import gnu.io.SerialPort;
public class controlJDQ {
private static controlJDQ JDQ = null;
private static ConnectWLW con=new ConnectWLW();
static {
//在该类被ClassLoader 加载时就初始化一个SerialTool对象
if (JDQ == null) {
JDQ = new controlJDQ();
}
}
//私有化类ShowLED的构造方法,不允许其他类生成ShowLED对象
private controlJDQ() {}
public static void wait_my()
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static String tosend(SerialPort serialPort,double temp,double humm,int smoke,double tu,double td,double hu,double hd) throws Exception{
String str="A5200400000000FF5A"; //向继电器发送数据
String ans="";
char[] status = str.toCharArray();
//第七位风扇 第九位喷灌 第十一位灯光 第十三位窗户
if(humm<hd) {//湿度小了 打开喷灌
status[9]='1';
ans+="湿度过低";
}
else if(humm>hu) {//湿度大了 或者是 打开风扇和窗户
status[7]='1';
status[13]='1';
ans+="湿度过高";
}
if(temp>tu) {//温度大了 打开喷灌 打开风扇 打开天窗
status[9]='1';
status[7]='1';
status[13]='1';
ans+="温度过高";
}
else if(temp<td) { //会结冰的 主要是外界温度原因 此时要关掉窗户 打开灯光取暖
status[11]='1';
status[13]='0';
ans+="温度过低";
}
str=String.valueOf(status);//
int flag=con.redDate(temp,humm,smoke,status[7]-'0',status[9]-'0',status[11]-'0',status[13]-'0');
System.out.println(flag);
if(flag==1)//状态不一样
con.add(temp,humm,smoke,status[7]-'0',status[9]-'0',status[11]-'0',status[13]-'0');//t,h,l-----插入此刻执行的操作 打开12,浇水
SerialTool.sendToPort(serialPort,str);//关闭排水管
if(ans.matches("")) return "一切正常";
return ans;
}
}
3、连接数据库(关于sql中的日期对象和java中的日期对象的转换,以及插入读取等等)
package OutFile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
public class ConnectWLW {
// 定义数据库访问参数
static String url = "jdbc:sqlserver://localhost:1433;DatabaseName=MyJava";
static String user = "sa";
static String password = "miaomiaomiao";
static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
static Connection conn;
static Statement st;
// 1、加载驱动
static {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
System.out.println("驱动加载失败");
}
}
// 2、创建连接对象
public static Connection getConnection() throws SQLException{
conn=DriverManager.getConnection(url,user,password);
return conn;
}
public static int redDate(double t,double h,int s,int f,int p,int d,int w) //读取数据函数---读取最后一条数据的
{
try
{
String sql = "select * from My_WLW"; //这是sql语句中的查询某个表,注意后面的emp是表名!!!
st =getConnection().createStatement();
ResultSet rs = st.executeQuery(sql); //用于返回结果
double temp=0;
double humm = 0;
int smoke=0;
int feng = 0;
int pen=0;
int deng=0;
int win=0;
while(rs.next()){
temp = rs.getDouble("温度");
humm = rs.getDouble("湿度");
smoke=rs.getInt("烟雾");
feng = rs.getInt("风扇状态");
pen = rs.getInt("喷灌状态");
deng = rs.getInt("灯光状态");
win = rs.getInt("天窗状态");
//System.out.println(id + "\t\t" + job + "\t" + date);
}
rs.close();
int flag=0;
if(Math.abs(temp-t)>=3) flag=1;
if(Math.abs(humm-h)>=3) flag=1;
if(smoke!=s) flag=1;
if(feng!=f) flag=1;
if(pen!=p) flag=1;
if(deng!=d) flag=1;
if(win!=w) flag=1;
return flag;
}catch(SQLException e){
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("数据库数据读取成功!"+"\n");
}
return 0;
}
public void add(double t,double h,int s,int f,int p,int d,int w) throws ClassNotFoundException, SQLException {
String sql="insert into My_WLW (温度,湿度,烟雾,风扇状态,喷灌状态,灯光状态,天窗状态,日期)"+"values(?,?,?,?,?,?,?,?)";
PreparedStatement ps =getConnection().prepareStatement(sql); //用preparedStatement预处理来执行sql语句
ps.setDouble(1, t); //给其五个参量分别“赋值”
ps.setDouble(2, h); //给其五个参量分别“赋值”
ps.setInt(3, s);
ps.setInt(4, f);
ps.setInt(5, p);
ps.setInt(6, d);
ps.setInt(7, w);
Date date = new Date(); // 获取一个Date对象
Timestamp time = new Timestamp(date.getTime()); // 讲日期时间转换为数据库中的timestamp类型
ps.setTimestamp(8, time);
ps.executeUpdate(); //参数准备后执行语句
ps.close();
getConnection().close();
}
public void update() throws ClassNotFoundException, SQLException {
// 定义sql语句
String sql1="update My_WLW set grade=1 where grade=2";
// 3、创建语句对象
st =getConnection().createStatement();
st.executeUpdate(sql1);
// 4、遍历结果集:此处插入记录不需要
// 5、关闭资源对象
st.close();
getConnection().close();
}
public void delete() throws ClassNotFoundException, SQLException {
// 定义sql语句
String sql1="delete My_WLW where id='20121115'";
String sql2="delete My_WLW where id='20121116'";
// 3、创建语句对象
st =getConnection().createStatement();
st.executeUpdate(sql1);
st.executeUpdate(sql2);
// 4、遍历结果集:此处插入记录不需要
// 5、关闭资源对象
st.close();
getConnection().close();
}
}
4、能解决很多问题数据转换模块
package USEFULL;
public class Tran {
//字节转为字符串
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if(hex.length() < 2){
sb.append(0);
}
sb.append(hex);
}
return sb.toString();
}
/*字符串转为字节*/
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] achar = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
}
private static int toByte(char c) {
byte b = (byte) "0123456789ABCDEF".indexOf(c);
return b;
}
}
5、核心的打开串口,接收数据,发送数据的模块。
package serialPort;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import USEFULL.Tran;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import serialException.*;
/*串口服务类,提供打开、关闭串口,读取、发送串口数据等服务(采用单例设计模式)
*/
public class SerialTool {
private static SerialTool serialTool = null;
private static Tran tran;
static {
//在该类被ClassLoader加载时就初始化一个SerialTool对象
if (serialTool == null) {
serialTool = new SerialTool();
}
}
//私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象
private SerialTool() {}
/* 获取提供服务的SerialTool对象*/
public static SerialTool getSerialTool() {
if (serialTool == null) {
serialTool = new SerialTool();
}
return serialTool;
}
/*查找所有可用端口 */
public static final ArrayList<String> findPort() {
//获得当前所有可用串口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<>();
//将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
/**
* 打开串口
* @param portName 端口名称
* @param baudrate 波特率
* @return 串口对象
* @throws SerialPortParameterFailure 设置串口参数失败
* @throws NotASerialPort 端口指向设备不是串口类型
* @throws NoSuchPort 没有该端口对应的串口设备
* @throws PortInUse 端口已被占用
*/
public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NotASerialPort, NoSuchPort, PortInUse {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口,并给端口名字和一个timeout(打开操作的超时时间)
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
try {
//设置一下串口的波特率等参数
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
throw new SerialPortParameterFailure();
}
//System.out.println("Open " + portName + " sucessfully !");
return serialPort;
}
else {
//不是串口
throw new NotASerialPort();
}
} catch (NoSuchPortException e1) {
throw new NoSuchPort();
} catch (PortInUseException e2) {
throw new PortInUse();
}
}
/**
* 关闭串口
* @param serialport 待关闭的串口对象
*/
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
/**
* 往串口发送数据
* @param serialPort 串口对象
* @param order 待发送数据
* @throws SendDataToSerialPortFailure 向串口发送数据失败
* @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错
*/
public static void sendToPort(SerialPort serialPort,String data) throws Exception {
//System.out.println("data = " + data);
byte[] writerBuffer = null;
OutputStream out = null;
try {
writerBuffer = Tran.hexStringToByte(data);
//System.out.println(writerBuffer);
} catch (NumberFormatException e) {
throw new Exception("命令格式错误!");
}
try {
out = serialPort.getOutputStream();
out.write(writerBuffer);
out.flush();
} catch (IOException e) {
throw new SendDataToSerialPortFailure();
} finally {
try {
if (out != null) {
out.close();
out = null;
}
} catch (IOException e) {
throw new SerialPortOutputStreamCloseFailure();
}
}
}
/**
* 从串口读取数据
* @param serialPort 当前已建立连接的SerialPort对象
* @return 读取到的数据
* @throws ReadDataFromSerialPortFailure 从串口读取数据时出错
* @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错
*/
public static byte[] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailure, SerialPortInputStreamCloseFailure {
/*16进制*/
InputStream in = null;
byte[] bytes = null;
try {
in = serialPort.getInputStream();
int bufflenth = in.available(); //获取buffer里的数据长度
while (bufflenth != 0) {
bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
in.read(bytes);
bufflenth = in.available();
}
} catch (IOException e) {
throw new ReadDataFromSerialPortFailure();
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch(IOException e) {
throw new SerialPortInputStreamCloseFailure();
}
}
return bytes;
}
/**
* 添加监听器
* @param port 串口对象
* @param listener 串口监听器
* @throws TooManyListeners 监听类对象过多
*/
public static void addListener(SerialPort port, SerialPortEventListener listener) throws TooManyListeners {
try {
//给串口添加监听器
port.addEventListener(listener);
//设置当有数据到达时唤醒监听接收线程
port.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
throw new TooManyListeners();
}
}
}
6、报错处理模块(很多是差不多,可以自己写 只是tostring不一样)
package serialException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 负责将传入的Exception中的错误信息提取出来并转换成字符串;
* @author zhong
*
*/
public class ExceptionWriter {
/**
* 将Exception中的错误信息封装到字符串中并返回该字符串
* @param e 包含错误的Exception
* @return 错误信息字符串
*/
public static String getErrorInfoFromException(Exception e) {
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw);
e.printStackTrace(pw);
return "\r\n" + sw.toString() + "\r\n";
} catch (Exception e2) {
return "出错啦!未获取到错误信息,请检查后重试!";
} finally {
try {
if (pw != null) {
pw.close();
}
if (sw != null) {
sw.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}