package ru.rsatu.ius;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* @author pavel
*/
public class Chart extends JFrame{
private static JPanel drawingField;
private static List<Integer> tempList;
private static List<Integer> fanList;
static int valuesOnScreen = 500;
public Chart(JPanel panel) {
drawingField = panel;
tempList = new LinkedList<>();
fanList = new LinkedList<>();
}
private static void drawData(List<Integer> data, Color color){
int firstElementIndex = data.size() > valuesOnScreen? data.size() - valuesOnScreen -1: 0;
int visibleValuesCount = data.size() > valuesOnScreen? valuesOnScreen: data.size();
//y boundaries
int max = 0;
int min = 9999;
for(int i=firstElementIndex; i<data.size(); i++){
if(data.get(i) > max) max = data.get(i);
if(data.get(i) < min) min = data.get(i);
}
int height = drawingField.getHeight();
double scale = (double)height/256.0;
Graphics g = drawingField.getGraphics();
g.setColor(color);
Point2D.Double prev = new Point2D.Double(0, data.get(firstElementIndex) * scale);
for(int i = 1; i<visibleValuesCount; i++){
Point2D.Double cur = new Point2D.Double(i, data.get(firstElementIndex+i) * scale);
drawLine(g,prev,cur);
prev = cur;
}
//last value
if(data.size()>2)
g.drawString(String.valueOf(data.get(data.size()-1)),visibleValuesCount, (int)((-prev.y + drawingField.getHeight())* scale));
}
private static void drawLimit(Integer data, Color color, String label){
int height = drawingField.getHeight();
double scale = (double)height/256.0;
Graphics g = drawingField.getGraphics();
g.setColor(color);
Point2D.Double prev = new Point2D.Double(0, data * scale);
for(int i = 1; i<500; i++){
Point2D.Double cur = new Point2D.Double(i, prev.y);
drawLine(g,prev,cur);
prev = cur;
}
//value
g.drawString(label+" = "+String.valueOf(data),250, (int)((-prev.y + drawingField.getHeight() - 5)* scale));
}
private static void drawLine(Graphics g, Point2D.Double prev, Point2D.Double cur){
g.drawLine((int)(prev.x), (int)(-prev.y + drawingField.getHeight()), (int)(cur.x), (int)(-cur.y + drawingField.getHeight()));
}
public static void addData(Integer temp, Integer fan){
if(temp==null) tempList.add(0);
else tempList.add(temp);
if(fan==null) fanList.add(0);
else fanList.add(fan);
Graphics g = drawingField.getGraphics();
g.clearRect(0, 0, drawingField.getWidth(), drawingField.getHeight());
//temp
drawData(tempList, Color.red);
//fan
drawData(fanList, Color.blue);
//target
byte value = ParamsStorage.getTarget_temp();
Integer targetValue = value & 0xff;
drawLimit(targetValue, Color.GREEN, "target");
//shutdownTemp
value = ParamsStorage.getShutdown_temp();
Integer shutdownValue = value & 0xff;
drawLimit(shutdownValue, Color.black, "shutdown");
}
}
package ru.rsatu.ius;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextArea;
/**
*
* @author pavel
*/
public class ComLogger {
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
private static JTextArea logBox;
private static StringBuilder logToSave;
/**
* указать место вывода
* @param lb
*/
public static void init(JTextArea lb){
logBox = lb;
logToSave = new StringBuilder();
}
/**
* вывод строки в textarea
* @param text
*/
public static void logLine(String text){
StringBuilder message = new StringBuilder();
message.append(dtf.format(LocalDateTime.now())).append(": ");
message.append(text);
logToSave.append("\n"+message.toString());
logBox.append("\n"+message.toString());
logBox.setCaretPosition(logBox.getDocument().getLength());
}
public static void saveLogToFile(){
try {
String s = new Date().toString().replaceAll(":", "-");
FileOutputStream FOS = new FileOutputStream(s+".log");
FOS.write(logToSave.toString().getBytes());
FOS.close();
} catch (IOException ex) {
Logger.getLogger(ComLogger.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
package ru.rsatu.ius;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
/**
*
* @author pavel
*/
public class ComTranciever {
private static SerialPort serialPort;
private static Thread writingThread;
private static int commandCounter;
private static List<Byte> curPacket;
private static boolean packetReady = false;
private static boolean packetStarted = false;
private static Queue<byte[]> outputCommandQueue;
private static byte[] prevCommand;
private static boolean sendLock;
private static List<byte[]> sentCommands;
/**
*
* @param name
* @throws jssc.SerialPortException
*/
public static void openPort(String name) throws SerialPortException {
commandCounter = 0;
curPacket = new LinkedList<>();
outputCommandQueue = new LinkedTransferQueue<>();
sendLock = false;
sentCommands = new LinkedList<>();
serialPort = new SerialPort(name);
serialPort.openPort();
serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
serialPort.addEventListener(new EventListener());
writingThread = new WritingThread();
writingThread.start();
}
/**
*
* @throws jssc.SerialPortException
*/
public static void closePort() throws SerialPortException {
if(serialPort!=null)
if(serialPort.isOpened())
serialPort.closePort();
}
/**
*
* @param command
* @throws SerialPortException
*/
public static void writeCommand(byte[] command) throws SerialPortException {
command[2] = (byte) (commandCounter % 16 * 17); //0x??
byte sum = 0;
for (int i = 1; i < command.length - 2; i++) {
sum = (byte) ((sum + command[i]) % 256);
}
command[command.length - 2] = sum;
outputCommandQueue.add(command);
}
private static class EventListener implements SerialPortEventListener {
@Override
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR() && event.getEventValue() >= 20) {
try {
try {
Thread.sleep(20);
System.out.println(event.getEventValue());
} catch (InterruptedException ex) {
Logger.getLogger(ComTranciever.class.getName()).log(Level.SEVERE, null, ex);
}
boolean ready = readUartPacket(event.getEventValue());
if(ready){
CommandParser.receiveCommand(curPacket);
curPacket = new LinkedList<>();
}
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
}
private static boolean readUartPacket(int bufferSize) throws SerialPortException {
for (int i = 0; i < bufferSize; i++) {
//read c
byte[] b = serialPort.readBytes(1);
//определение начала пакета
if (!packetStarted) {
if (b[0] == (byte)0xbb) {
packetStarted = true;
curPacket.add(b[0]);
}
} //данные или конец пакета
else {
//добавить в пакет
curPacket.add(b[0]);
//предыдущий символ
int index = curPacket.size() - 2;
//не пустой
if (index >= 0) {
//ищем конец пакета
if (curPacket.get(index) == (byte)0x00 && //конец кадра
b[0] == (byte)0x81) { //конец пакета
//проверка длины пакета
boolean sizeControl = packetSizeControl();
//пакет завершен
if (sizeControl) {
packetReady = true;
packetStarted = false;
return packetReady;
}
}
}
}
}
return packetReady;
}
private static boolean packetSizeControl() {
if (curPacket.get(0)!= (byte)0xbb) { //packet start
return false;
}
int index = 1;
boolean correct = true;
//перебор пакетов
while (index < curPacket.size()) {
//frame start
if (curPacket.get(index)!= (byte) 0xff) {
//конец и нет других данных
if(curPacket.get(index) == (byte)0x81 & index == curPacket.size()-1){
break;
}
else{
correct = false;
break;
}
}
index++;
index = getNextFrameEndPos(index); //param == commandID
//frame end
if (curPacket.get(index)!= (byte) 0x00) {
correct = false;
break;
}
index++;
}
return correct;
}
private static int getNextFrameEndPos(int curCommandIdIndex) {
byte b = curPacket.get(curCommandIdIndex);
int offset = 0;
switch (b) {
//command not accepted
case (byte)0x33: //frame start, >> comId <<, counter, control, frame end
offset = 3;
break;
//command accepted
case (byte)0xcc: //frame start, >> comId <<, counter, control, frame end
offset = 3;
break;
//param input
case (byte)0x66: //frame start, >> comId <<, counter, param id, value1,... valueN, control, frame end
offset = 4 + getValueBytesLength(curCommandIdIndex + 2);
break;
//sensor data
case (byte)0x99: //frame start, >> comId <<, sensor id, value, control, frame end
offset = 4;
break;
}
return curCommandIdIndex + offset;
}
private static int getValueBytesLength(int paramIdIndex) {
byte c = curPacket.get(paramIdIndex);
int length = 0;
switch (c) {
case (byte)0x33: //kp, float
length = 4;
break;
case (byte)0x55: //ki, float
length = 4;
break;
case (byte)0x99: //kd, float
length = 4;
break;
case (byte)0xaa: //tt, byte
length = 1;
break;
case (byte)0x66: //st, byte
length = 1;
break;
case (byte)0xcc: //ar, byte
length = 1;
break;
}
return length;
}
public static void unlock(){
sendLock = false;
}
public static void repeatCommand(byte comCounter){
for(byte[] com: sentCommands){
if(com[2]==comCounter){
try {
serialPort.writeBytes(com);
break;
} catch (SerialPortException ex) {
Logger.getLogger(ComTranciever.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public static void removeCommandFromList(byte comCounter){
for(byte[] com: sentCommands){
if(com[2]==comCounter){
sentCommands.remove(com);
break;
}
}
}
private static class WritingThread extends Thread {
@Override
public void run() {
int counter = 0;
while(true){
if(!sendLock & outputCommandQueue.size()>0){
sendLock = true;
prevCommand = outputCommandQueue.poll();
sentCommands.add(prevCommand);
try {
serialPort.writeBytes(prevCommand);
} catch (SerialPortException ex) {
Logger.getLogger(ComTranciever.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(sendLock){
counter++;
try {
sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(ComTranciever.class.getName()).log(Level.SEVERE, null, ex);
}
if(counter>200){
unlock();
counter = 0;
System.out.println("---");
}
}
}
}
}
}
package ru.rsatu.ius;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedTransferQueue;
/**
*
* @author pavel
*/
public class CommandParser {
private static Queue<List<Byte>> commandQueue;
private static Thread commandParserThread;
private static List<Byte> curCommand = null;
public static void init() {
commandQueue = new LinkedTransferQueue<>();
commandParserThread = new CommandParserThread();
commandParserThread.start();
}
public static void receiveCommand(List<Byte> command) {
commandQueue.add(command);
}
private static class CommandParserThread extends Thread {
@Override
public void run() {
while (true) {
if (!commandQueue.isEmpty()) {
if(curCommand==null){
curCommand = commandQueue.poll();
parse();
curCommand=null;
}
}
}
}
private void parse() {
//
Integer curTemp = null;
Integer curFan = null;
//0 -packet start, 1 frame start
int curFrameComIDIndex = 2;
while (curFrameComIDIndex < curCommand.size()) {
byte curFrameComID = curCommand.get(curFrameComIDIndex);
switch (curFrameComID) {
//command not accepted
case (byte) 0x33:
ComLogger.logLine("not accepted");
ComTranciever.repeatCommand(curCommand.get(curFrameComIDIndex+1));
break;
//command accepted
case (byte) 0xcc:
ComLogger.logLine("accepted");
ComTranciever.removeCommandFromList(curCommand.get(curFrameComIDIndex+1));
ComTranciever.unlock();
break;
//param input
case (byte) 0x66:
ComLogger.logLine("param input");
break;
//sensor data
case (byte) 0x99:
//ComLogger.logLine("sensor data");
if(!(curFrameComIDIndex+1<curCommand.size())) break;
byte curFrameSensorID = curCommand.get(curFrameComIDIndex+1);
switch(curFrameSensorID){
case (byte) 0xfa: //temp
{
if(!(curFrameComIDIndex+2<curCommand.size())) break;
curTemp = (int)curCommand.get(curFrameComIDIndex+2);
if(curTemp<0)
curTemp+=256;
//ComLogger.logLine("temp = "+curTemp);
break;
}
case (byte) 0xaf: //fan
{
if(!(curFrameComIDIndex+2<curCommand.size())) break;
curFan = (int)curCommand.get(curFrameComIDIndex+2);
if(curFan<0)
curFan+=256;
//ComLogger.logLine("fan = "+curFan);
break;
}
}
break;
}
curFrameComIDIndex = getNextFrameEndPos(curFrameComIDIndex)+2;
}
Chart.addData(curTemp, curFan);
}
private static int getNextFrameEndPos(int curCommandIdIndex) {
byte b = curCommand.get(curCommandIdIndex);
int offset = 0;
switch (b) {
//command not accepted
case (byte) 0x33: //frame start, >> comId <<, counter, control, frame end
offset = 3;
break;
//command accepted
case (byte) 0xcc: //frame start, >> comId <<, counter, control, frame end
offset = 3;
break;
//param input
case (byte) 0x66: //frame start, >> comId <<, counter, param id, value1,... valueN, control, frame end
offset = 4 + getValueBytesLength(curCommandIdIndex + 2);
break;
//sensor data
case (byte) 0x99: //frame start, >> comId <<, sensor id, value, control, frame end
offset = 4;
break;
}
return curCommandIdIndex + offset;
}
private static int getValueBytesLength(int paramIdIndex) {
byte c = curCommand.get(paramIdIndex);
int length = 0;
switch (c) {
case (byte) 0x33: //kp, float
length = 4;
break;
case (byte) 0x55: //ki, float
length = 4;
break;
case (byte) 0x99: //kd, float
length = 4;
break;
case (byte) 0xaa: //tt, byte
length = 1;
break;
case (byte) 0x66: //st, byte
length = 1;
break;
case (byte) 0xcc: //ar, byte
length = 1;
break;
}
return length;
}
}
}
package ru.rsatu.ius;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.border.LineBorder;
import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortList;
/**
*
* @author pavel
*/
public class MainFrame extends javax.swing.JFrame {
/**
* Creates new form MainFrame
*/
private static SerialPort serialPort;
public MainFrame() {
initComponents();
//параметры
ParamsStorage.init();
KpTextField.setText(String.valueOf(ParamsStorage.getKp()));
KiTextField.setText(String.valueOf(ParamsStorage.getKi()));
KdTextField.setText(String.valueOf(ParamsStorage.getKd()));
RelayComboBox.setSelectedItem(String.valueOf(ParamsStorage.getActive_relay()));
ShutdownTempTextField.setText(String.valueOf((int)(ParamsStorage.getShutdown_temp() & 0xff)));
TargetTempTextField.setText(String.valueOf((int)(ParamsStorage.getTarget_temp() & 0xff)));
//график
JFrame jf = new Chart(ChartPanel);
//логгер
ComLogger.init(ComLogTextArea);
//обработчик команд
CommandParser.init();
String[] l = SerialPortList.getPortNames();
for(String s:l){
ComPortComboBox.addItem(s);
System.out.println(s);
ComLogger.logLine(s);
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
ChartPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
ComLogTextArea = new javax.swing.JTextArea();
jPanel2 = new javax.swing.JPanel();
ComPortComboBox = new javax.swing.JComboBox<>();
KpTextField = new javax.swing.JTextField();
KiTextField = new javax.swing.JTextField();
KdTextField = new javax.swing.JTextField();
TargetTempTextField = new javax.swing.JTextField();
ShutdownTempTextField = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
ApplyButton = new javax.swing.JButton();
PowerToggleButton = new javax.swing.JToggleButton();
RelayComboBox = new javax.swing.JComboBox<>();
jMenuBar1 = new javax.swing.JMenuBar();
OpenMenuItem = new javax.swing.JMenu();
SaveMenuItem = new javax.swing.JMenu();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
ChartPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
javax.swing.GroupLayout ChartPanelLayout = new javax.swing.GroupLayout(ChartPanel);
ChartPanel.setLayout(ChartPanelLayout);
ChartPanelLayout.setHorizontalGroup(
ChartPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 520, Short.MAX_VALUE)
);
ChartPanelLayout.setVerticalGroup(
ChartPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 262, Short.MAX_VALUE)
);
ComLogTextArea.setEditable(false);
ComLogTextArea.setColumns(20);
ComLogTextArea.setRows(5);
jScrollPane1.setViewportView(ComLogTextArea);
ComPortComboBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
ComPortComboBoxItemStateChanged(evt);
}
});
KpTextField.setText("jTextField1");
KpTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
KpTextFieldFocusLost(evt);
}
});
KiTextField.setText("jTextField2");
KiTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
KiTextFieldFocusLost(evt);
}
});
KdTextField.setText("jTextField3");
KdTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
KdTextFieldFocusLost(evt);
}
});
TargetTempTextField.setText("jTextField4");
TargetTempTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
TargetTempTextFieldFocusLost(evt);
}
});
ShutdownTempTextField.setText("jTextField5");
ShutdownTempTextField.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
ShutdownTempTextFieldFocusLost(evt);
}
});
jLabel1.setText("Kp");
jLabel2.setText("Ki");
jLabel3.setText("Kd");
jLabel4.setText("target temp");
jLabel6.setText("shutdown temp");
ApplyButton.setText("apply");
ApplyButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ApplyButtonActionPerformed(evt);
}
});
PowerToggleButton.setText("ВКЛ/ВЫКЛ");
PowerToggleButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
PowerToggleButtonActionPerformed(evt);
}
});
RelayComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "1", "2", "3" }));
RelayComboBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
RelayComboBoxItemStateChanged(evt);
}
});
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel3)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(PowerToggleButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(ComPortComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(27, 27, 27)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(KpTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jLabel4))
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(KiTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(KdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(RelayComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(TargetTempTextField)
.addComponent(ShutdownTempTextField)
.addComponent(ApplyButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ComPortComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(KpTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(TargetTempTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1)
.addComponent(jLabel4))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel6)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(KiTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(ShutdownTempTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(PowerToggleButton)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 10, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(KdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3)
.addComponent(ApplyButton)
.addComponent(RelayComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
OpenMenuItem.setText("Open log");
jMenuBar1.add(OpenMenuItem);
SaveMenuItem.setText("Save log");
SaveMenuItem.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
SaveMenuItemMouseClicked(evt);
}
});
SaveMenuItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
SaveMenuItemActionPerformed(evt);
}
});
jMenuBar1.add(SaveMenuItem);
setJMenuBar(jMenuBar1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ChartPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(22, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(15, 15, 15)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 295, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ChartPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void ApplyButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
//проверка ввода
if(inputCheck()){
//отправка команд на передачу измененных параметров
//kp
float fvalue = Float.valueOf(KpTextField.getText());
//новое
if(ParamsStorage.getKp()!= fvalue){
//сохранить
ParamsStorage.setKp(fvalue);
byte value[] = ByteBuffer.allocate(4).putFloat(fvalue).array();
byte buffer[] = new byte[10];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0x33; //ид параметра
buffer[4]= value[0];
buffer[5]= value[1];
buffer[6]= value[2];
buffer[7]= value[3];
buffer[8]=(byte)0x00; //сумма (любое)
buffer[9]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//ki
fvalue = Float.valueOf(KiTextField.getText());
//новое
if(ParamsStorage.getKi()!= fvalue){
//сохранить
ParamsStorage.setKi(fvalue);
byte value[] = ByteBuffer.allocate(4).putFloat(fvalue).array();
byte buffer[] = new byte[10];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0x55; //ид параметра
buffer[4]= value[0];
buffer[5]= value[1];
buffer[6]= value[2];
buffer[7]= value[3];
buffer[8]=(byte)0x00; //сумма (любое)
buffer[9]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//kd
fvalue = Float.valueOf(KdTextField.getText());
//новое
if(ParamsStorage.getKd()!= fvalue){
//сохранить
ParamsStorage.setKd(fvalue);
byte value[] = ByteBuffer.allocate(4).putFloat(fvalue).array();
byte buffer[] = new byte[10];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0x99; //ид параметра
buffer[4]= value[0];
buffer[5]= value[1];
buffer[6]= value[2];
buffer[7]= value[3];
buffer[8]=(byte)0x00; //сумма (любое)
buffer[9]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//tt
byte bvalue = (byte) (Integer.valueOf(TargetTempTextField.getText()) & 0xff);
//новое
if(ParamsStorage.getTarget_temp()!= bvalue){
//сохранить
ParamsStorage.setTarget_temp(bvalue);
byte buffer[] = new byte[7];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0xAA; //ид параметра
buffer[4]= bvalue;
buffer[5]=(byte)0x00; //сумма (любое)
buffer[6]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//st
bvalue = (byte) (Integer.valueOf(ShutdownTempTextField.getText()) & 0xff);
//новое
if(ParamsStorage.getShutdown_temp()!= bvalue){
//сохранить
ParamsStorage.setShutdown_temp(bvalue);
byte buffer[] = new byte[7];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0x66; //ид параметра
buffer[4]= bvalue;
buffer[5]=(byte)0x00; //сумма (любое)
buffer[6]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//ar
bvalue = Byte.valueOf(RelayComboBox.getSelectedItem().toString());
//новое
if(ParamsStorage.getActive_relay()!= bvalue){
//сохранить
ParamsStorage.setActive_relay(bvalue);
byte buffer[] = new byte[7];
buffer[0]=(byte)0xff; //начало кадра
buffer[1]=(byte)0x99; //передача параметра
buffer[2]=(byte)0x00; //ид команды (любое, пересчитывается)
buffer[3]=(byte)0xcc; //ид параметра
buffer[4]= bvalue;
buffer[5]=(byte)0x00; //сумма (любое)
buffer[6]=(byte)0x81; //конец кадра
//отправить
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//System.out.println(newKp);
}
/**
* проверка ввода
* @return
*/
private boolean inputCheck(){
boolean result = true;
//kp
try{
float newKp = Float.valueOf(KpTextField.getText());
KpTextField.setBorder(new LineBorder(Color.GRAY));
}
catch(NumberFormatException e){
result = false;
KpTextField.setBorder(new LineBorder(Color.RED));
};
//ki
try{
float newKi = Float.valueOf(KiTextField.getText());
KiTextField.setBorder(new LineBorder(Color.GRAY));
}
catch(NumberFormatException e){
result = false;
KiTextField.setBorder(new LineBorder(Color.RED));
};
//kd
try{
float newKd = Float.valueOf(KdTextField.getText());
KdTextField.setBorder(new LineBorder(Color.GRAY));
}
catch(NumberFormatException e){
result = false;
KdTextField.setBorder(new LineBorder(Color.RED));
};
//target temp
try{
int tt = Integer.valueOf(String.valueOf(Integer.valueOf(TargetTempTextField.getText())));
if(tt<0 | tt>255) throw new NumberFormatException();
TargetTempTextField.setBorder(new LineBorder(Color.GRAY));
}
catch(NumberFormatException e){
result = false;
TargetTempTextField.setBorder(new LineBorder(Color.RED));
};
//shutdown temp
try{
int st = Integer.valueOf(String.valueOf(Integer.valueOf(ShutdownTempTextField.getText())));
if(st<0 | st>255) throw new NumberFormatException();
ShutdownTempTextField.setBorder(new LineBorder(Color.GRAY));
}
catch(NumberFormatException e){
result = false;
ShutdownTempTextField.setBorder(new LineBorder(Color.RED));
};
return result;
}
private void PowerToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
byte buffer[] = new byte[5];
buffer[0]=(byte)0xff;
buffer[1]=(byte)0x66;
buffer[2]=(byte)0x00; //любое
buffer[3]=(byte)0x66; //любое
buffer[4]=(byte)0x81;
try {
ComTranciever.writeCommand(buffer);
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void ComPortComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {
// TODO add your handling code here:
if(evt.getStateChange() == ItemEvent.DESELECTED){
try {
System.out.println(ComPortComboBox.getSelectedItem());
ComTranciever.closePort();
ComTranciever.openPort((String)ComPortComboBox.getSelectedItem());
} catch (SerialPortException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void RelayComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {
// TODO add your handling code here:
if(evt.getStateChange() == ItemEvent.DESELECTED){
System.out.println(RelayComboBox.getSelectedItem());
}
}
private void KpTextFieldFocusLost(java.awt.event.FocusEvent evt) {
// TODO add your handling code here:
inputCheck();
}
private void KiTextFieldFocusLost(java.awt.event.FocusEvent evt) {
// TODO add your handling code here:
inputCheck();
}
private void KdTextFieldFocusLost(java.awt.event.FocusEvent evt) {
// TODO add your handling code here:
inputCheck();
}
private void TargetTempTextFieldFocusLost(java.awt.event.FocusEvent evt) {
// TODO add your handling code here:
inputCheck();
}
private void ShutdownTempTextFieldFocusLost(java.awt.event.FocusEvent evt) {
// TODO add your handling code here:
inputCheck();
}
private void SaveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
private void SaveMenuItemMouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
ComLogger.saveLogToFile();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info: javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton ApplyButton;
private javax.swing.JPanel ChartPanel;
private javax.swing.JTextArea ComLogTextArea;
private javax.swing.JComboBox<String> ComPortComboBox;
private javax.swing.JTextField KdTextField;
private javax.swing.JTextField KiTextField;
private javax.swing.JTextField KpTextField;
private javax.swing.JMenu OpenMenuItem;
private javax.swing.JToggleButton PowerToggleButton;
private javax.swing.JComboBox<String> RelayComboBox;
private javax.swing.JMenu SaveMenuItem;
private javax.swing.JTextField ShutdownTempTextField;
private javax.swing.JTextField TargetTempTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel6;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration
}
package ru.rsatu.ius;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author pavel
*/
public class ParamsStorage {
private static float kp;
private static float ki;
private static float kd;
private static byte active_relay;
private static byte shutdown_temp;
private static byte target_temp;
public static float getKp() {
return kp;
}
public static void setKp(float kp) {
ParamsStorage.kp = kp;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static float getKi() {
return ki;
}
public static void setKi(float ki) {
ParamsStorage.ki = ki;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static float getKd() {
return kd;
}
public static void setKd(float kd) {
ParamsStorage.kd = kd;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static byte getActive_relay() {
return active_relay;
}
public static void setActive_relay(byte active_relay) {
ParamsStorage.active_relay = active_relay;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static byte getShutdown_temp() {
return shutdown_temp;
}
public static void setShutdown_temp(byte shutdown_temp) {
ParamsStorage.shutdown_temp = shutdown_temp;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static byte getTarget_temp() {
return target_temp;
}
public static void setTarget_temp(byte target_temp) {
ParamsStorage.target_temp = target_temp;
try {
saveToFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void init(){
try {
if(!new File("parameters").exists())
saveToFile();
readFromFile();
} catch (IOException ex) {
Logger.getLogger(ParamsStorage.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void saveToFile() throws IOException{
FileWriter fileWriter = new FileWriter("parameters");
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.println(kp);
printWriter.println(ki);
printWriter.println(kd);
printWriter.println(active_relay);
printWriter.println(shutdown_temp);
printWriter.println(target_temp);
printWriter.close();
}
private static void readFromFile() throws IOException{
BufferedReader br = new BufferedReader(new FileReader("parameters"));
String st = br.readLine();
kp = Float.valueOf(st);
st = br.readLine();
ki = Float.valueOf(st);
st = br.readLine();
kd = Float.valueOf(st);
st = br.readLine();
active_relay = Byte.valueOf(st);
st = br.readLine();
shutdown_temp = Byte.valueOf(st);
st = br.readLine();
target_temp = Byte.valueOf(st);
}
}
package ru.rsatu.ius.analysis;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import ru.rsatu.ius.ParamsStorage;
/**
*
* @author pavel
*/
public class DataAnalyzer {
private static JPanel drawPanel;
private static JTextArea textOutput;
public static int XoffsetPercent;
private static int maxOverregulation;
private static StringBuilder warnings;
private static StringBuilder recomendations;
private static RecommendedParameters recommendedParameters;
/**
* инициализация
*/
public static void init(JPanel panel, JTextArea textArea){
drawPanel = panel;
textOutput = textArea;
}
/**
* Выполнить анализ
* @param data - показания температуры для анализа
* @param applyRecomendedChanges - применить рекомендуемые значения
*/
public static void AnalyzeData(int[] data, boolean applyRecomendedChanges){
maxOverregulation = 0;
warnings = new StringBuilder();
recomendations = new StringBuilder();
//некорректные показания
List<Integer> invalidData = sanityCheck(data);
//локальные мин/макс
List<Integer> extremumPoints = getExtremumPoints(data,invalidData);
//точка уставки
int lastExtremumPoint = extremumPoints.isEmpty()? 0: Math.abs(extremumPoints.get(extremumPoints.size()-1));
int heatEndPoint = getHeatEndPoint(data, lastExtremumPoint, invalidData);
//колебательность
bo