本文主要是介绍【论文代码】基于隐蔽带宽的汽车控制网路鲁棒认证-到达时间间隔通道的Java实现(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、USBtin 基类
- 1.1 CANSender 类
- 1.1.1 SimpleSender类
- 1.2 CANReceiver类
- 1.2.1 SimpleReceiver类
- 1.3 Noise_node类
- 二、CANMessageListener 接口
- 2.1 IAT_Monitor
- 2.2 BasicListener
- 2.3 DLC_Monitor
- 三、IATBitConverter 抽象类
- 3.1 OneBitConverter类
- 3.2 TwoBitConverter类
- 四、ErrorCorrectionCode 错误纠正码接口
- 4.1 SimpleCRC类
- 4.2 SimpleParity
此篇文章是对原有代码的注释进行翻译,尝试对其架构和实现方式进行理解。
项目结构
Java实现代码
如图UML类图:
从图中明显可见,其代码组织方式,各个代码文件的继承和实现的关系。
以下内容围绕UML类图,分别进行阐述。
一、USBtin 基类
USBtin家族
- USBtin是所有类的基类。
- CANSender 和CANReceiver 是USBtin的派生类,同时增加了抽象方法,固也是抽象类,必须有下一级派生类才能使用。
- SimpleSender 和 SimpleReceiver 分别是CANSender和CANReceiver抽象类的实现类。
- Noice_node是USBtin的派生类。
USBtin类
USBtin类中,有9个成员变量,18个成员方法。
USBtin的代码:
package USBtin;import jssc.*;import java.util.ArrayList;
import java.util.LinkedList;/*** 表示 USBtin.USBtin 设备.* 提供对USBtin.USBtin设备的虚拟访问* 串口.*/
public class USBtin implements SerialPortEventListener {/** USBtin连接的串口(虚拟) */protected SerialPort serialPort;/** 从USBtin中获取的字符被收集在这个StringBuilder中。 */protected StringBuilder incomingMessage = new StringBuilder();/** CAN消息监听器 */protected ArrayList<CANMessageListener> listeners = new ArrayList<CANMessageListener>();/** 传播FIFO(先进先出)链表 */protected LinkedList<CANMessage> fifoTX = new LinkedList<CANMessage>();/** USBtin.USBtin 固件版本 */protected String firmwareVersion;/** USBtin.USBtin 硬件版本 */protected String hardwareVersion;/** USBtin.USBtin 序列号 */protected String serialNumber;/** USBtin.USBtin 的响应超时是1s */protected static final int TIMEOUT = 1000;/** CAN通道的打开模式 */public enum OpenMode {/** 在CAN总线上可发送可接收 */ACTIVE,/** 只能监听,不能发送 */LISTENONLY,/** 回送发送的CAN消息,断开物理CAN总线连接 */LOOPBACK}/*** 获取固件版本字符串.* 在 connect() 期间,从 USBtin.USBtin 请求固件版本.** @return Firmware version*/public String getFirmwareVersion() {return firmwareVersion;}/*** 获取硬件版本字符串.* 在 connect()期间,从 USBtin.USBtin 请求硬件版本. ** @return Hardware version*/public String getHardwareVersion() {return hardwareVersion;}/*** 获取序列号字符出串.* 在 connect()期间,从 USBtin.USBtin 请求序列号. ** @return Serial number*/public String getSerialNumber() {return serialNumber;}/*** 连接指定端口的USBtin.* 打开串口,清除挂起字符并发送关闭命令以确保处于配置模式.** @param portName 虚拟串口名称* @throws USBtinException 连接USBtin.USBtin时可能出现的异常*/public void connect(String portName) throws USBtinException {try {// 创建串口对象serialPort = new SerialPort(portName);// 打开串口并且初始化serialPort.openPort();serialPort.setParams(115200, 8, 1, 0);// 清除端口并确保我们处于配置模式(关闭命令)serialPort.writeBytes("\rC\r".getBytes());Thread.sleep(100);serialPort.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);serialPort.writeBytes("C\r".getBytes());byte b;do {byte[] buffer = serialPort.readBytes(1, TIMEOUT);b = buffer[0];} while ((b != '\r') && (b != 7));// 获取版本信息this.firmwareVersion = this.transmit("v").substring(1);this.hardwareVersion = this.transmit("V").substring(1);this.serialNumber = this.transmit("N").substring(1);// 重置溢出的错误标志this.transmit("W2D00");} catch (SerialPortException e) {throw new USBtinException(e.getPortName() + " - " + e.getExceptionType());} catch (SerialPortTimeoutException e) {throw new USBtinException("Timeout! USBtin.USBtin doesn't answer. Right port?");} catch (InterruptedException e) {throw new USBtinException(e);}}/*** 断开连接.* 关闭串口连接** @throws USBtinException 关闭连接时的异常*/public void disconnect() throws USBtinException {try {serialPort.closePort();} catch (SerialPortException e) {throw new USBtinException(e.getExceptionType());}}/*** 打开CAN通道.* 给定模式下,设置波特率并打开CAN通道.** @param baudrate 波特率(bit/s)* @param mode CAN总线访问模式* @throws USBtinException 打开CAN通道时的异常*/public void openCANChannel(int baudrate, OpenMode mode) throws USBtinException {try {// 设置波特率char baudCh = ' ';switch (baudrate) {case 10000: baudCh = '0'; break;case 20000: baudCh = '1'; break;case 50000: baudCh = '2'; break;case 100000: baudCh = '3'; break;case 125000: baudCh = '4'; break;case 250000: baudCh = '5'; break;case 500000: baudCh = '6'; break;case 800000: baudCh = '7'; break;case 1000000: baudCh = '8'; break;}if (baudCh != ' ') {// 使用预设波特率this.transmit("S" + baudCh);} else {// 计算波特率寄存器设置final int FOSC = 24000000;int xdesired = FOSC / baudrate;int xopt = 0;int diffopt = 0;int brpopt = 0;// 遍历可能的位长度 (in TQ)for (int x = 11; x <= 23; x++) {// 得到波特率因子的下一个偶数值int xbrp = (xdesired * 10) / x;int m = xbrp % 20;if (m >= 10) xbrp += 20;xbrp -= m;xbrp /= 10;// 范围检查if (xbrp < 2) xbrp = 2;if (xbrp > 128) xbrp = 128;// 计算 diffint xist = x * xbrp;int diff = xdesired - xist;if (diff < 0) diff = -diff;// use this clock option if it is better than previous(使用这个时钟选项,如果它比以前更好)if ((xopt == 0) || (diff <= diffopt)) { xopt = x; diffopt = diff; brpopt = xbrp / 2 - 1;};}// CNF寄存器值的映射int cnfvalues[] = {0x9203, 0x9303, 0x9B03, 0x9B04, 0x9C04, 0xA404, 0xA405, 0xAC05, 0xAC06, 0xAD06, 0xB506, 0xB507, 0xBD07};this.transmit("s" + String.format("%02x", brpopt | 0xC0) + String.format("%04x", cnfvalues[xopt - 11]));System.out.println("No preset for given baudrate " + baudrate + ". Set baudrate to " + (FOSC / ((brpopt + 1) * 2) / xopt));}// 打开CAN通道char modeCh;switch (mode) {default:System.err.println("Mode " + mode + " not supported. Opening listen only.");case LISTENONLY: modeCh = 'L'; break;case LOOPBACK: modeCh = 'l'; break;case ACTIVE: modeCh = 'O'; break;}this.transmit(modeCh + "");// 注册串口事件监听器serialPort.setEventsMask(SerialPort.MASK_RXCHAR);serialPort.addEventListener(this);} catch (SerialPortException e) {throw new USBtinException(e);} catch (SerialPortTimeoutException e) {throw new USBtinException("Timeout! USBtin.USBtin doesn't answer. Right port?");}}/*** 关闭CAN通道.** @throws USBtinException 关闭CAN通道时的异常*/public void closeCANChannel() throws USBtinException {try {serialPort.removeEventListener();serialPort.writeBytes("C\r".getBytes());} catch (SerialPortException e) {throw new USBtinException(e.getExceptionType());}firmwareVersion = null;hardwareVersion = null;}/*** 从 USBtin.USBtin 读取响应** @return Response from USBtin.USBtin* @throws SerialPortException Error while accessing USBtin.USBtin 访问异常* @throws SerialPortTimeoutException Timeout of serial port 超时异常*/protected String readResponse() throws SerialPortException, SerialPortTimeoutException {StringBuilder response = new StringBuilder();while (true) {byte[] buffer = serialPort.readBytes(1, 1000);if (buffer[0] == '\r') {return response.toString();} else if (buffer[0] == 7) {throw new SerialPortException(serialPort.getPortName(), "transmit", "BELL signal");} else {response.append((char) buffer[0]);}}}/*** 将给定的命令发送到 USBtin** @param cmd 命令* @return Response from USBtin.USBtin 来自USBtin的响应* @throws SerialPortException Error while talking to USBtin.USBtin* @throws SerialPortTimeoutException Timeout of serial port*/public String transmit(String cmd) throws SerialPortException, SerialPortTimeoutException {String cmdline = cmd + "\r";serialPort.writeBytes(cmdline.getBytes());return this.readResponse();}/*** 处理串口事件.* 读取单个字节并检查结束符.* 如果到达行尾,解析命令并调度它.** @param event Serial port event 串口事件*/@Overridepublic void serialEvent(SerialPortEvent event) {// 检查字节是否可用 (RX = bytes in input buffer)if (event.isRXCHAR() && event.getEventValue() > 0) {try {byte buffer[] = serialPort.readBytes();for (byte b : buffer) {if ((b == '\r') && incomingMessage.length() > 0) {String message = incomingMessage.toString();char cmd = message.charAt(0);// 检查是否为CAN消息if (cmd == 't' || cmd == 'T' || cmd == 'r' || cmd == 'R') {// 从消息字符串创建CAN消息CANMessage canmsg = new CANMessage(message);// 把CAN消息发送给监听器for (CANMessageListener listener : listeners) {listener.receiveCANMessage(canmsg);}} else if ((cmd == 'z') || (cmd == 'Z')) {// 从发送fifo中删除第一条信息并发送下一条fifoTX.removeFirst();try {sendFirstTXFifoMessage();} catch (USBtinException ex) {System.err.println(ex);}}incomingMessage.setLength(0);} else if (b == 0x07) {// 从tx fifo重新发送第一个元素try {sendFirstTXFifoMessage();} catch (USBtinException ex) {System.err.println(ex);}} else if (b != '\r') {incomingMessage.append((char) b);}}} catch (SerialPortException ex) {System.err.println(ex);}}}/*** 添加消息监听器** @param listener Listener object 监听器对象*/public void addMessageListener(CANMessageListener listener) {listeners.add(listener);}/*** 移除消息监听器.** @param listener Listener object 监听器对象*/public void removeMessageListener(CANMessageListener listener) {listeners.remove(listener);}/*** 发送tx fifo中的第一个消息** @throws USBtinException On serial port errors 串口错误异常*/protected void sendFirstTXFifoMessage() throws USBtinException {if (fifoTX.size() == 0) {return;}CANMessage canmsg = fifoTX.getFirst();try {serialPort.writeBytes((canmsg.toString() + "\r").getBytes());} catch (SerialPortException e) {throw new USBtinException(e);}}/*** 发送指定CAN消息.** @param canmsg Can message to send CAN消息* @throws USBtinException On serial port errors*/public void send(CANMessage canmsg) throws USBtinException {fifoTX.add(canmsg);if (fifoTX.size() > 1) return;sendFirstTXFifoMessage();}/*** 写入指定的MCP2515寄存器* * @param register Register address 寄存器地址* @param value Value to write 写入值* @throws USBtinException On serial port errors 异常*/public void writeMCPRegister(int register, byte value) throws USBtinException {try {String cmd = "W" + String.format("%02x", register) + String.format("%02x", value);transmit(cmd);} catch (SerialPortException e) {throw new USBtinException(e);} catch (SerialPortTimeoutException e) {throw new USBtinException("Timeout! USBtin.USBtin doesn't answer. Right port?");}}/*** 将指定的掩码寄存器写入MCP2515** @param maskid Mask identifier (0 = RXM0, 1 = RXM1) 掩码标识符* @param registers Register values to write 要写入的寄存器值* @throws USBtinException On serial port errors 异常*/protected void writeMCPFilterMaskRegisters(int maskid, byte[] registers) throws USBtinException {for (int i = 0; i < 4; i++) {writeMCPRegister(0x20 + maskid * 4 + i, registers[i]);}}/*** 将给定的滤波器寄存器写入MCP2515** @param filterid Filter identifier (0 = RXF0, ... 5 = RXF5) 滤波器ID* @param registers Register values to write 要写入的寄存器值* @throws USBtinException On serial port errors 异常*/protected void writeMCPFilterRegisters(int filterid, byte[] registers) throws USBtinException {int startregister[] = {0x00, 0x04, 0x08, 0x10, 0x14, 0x18};for (int i = 0; i < 4; i++) {writeMCPRegister(startregister[filterid] + i, registers[i]);}}/*** 设置硬件滤波器.* 调用这个函数的调用时机在 connect() 之后,openCANChannel()之前!** @param fc 过滤器链(USBtin最多支持2个硬件过滤器链)* @throws USBtinException On serial port errors*/public void setFilter(FilterChain[] fc) throws USBtinException {/** MCP2515提供两个过滤器链。 每个链由一个掩码和一组过滤器组成:** RXM0 RXM1* | |* RXF0 RXF2* RXF1 RXF3* RXF4* RXF5*/// 如果没有指定过滤器链传入,则接收全部消息if ((fc == null) || (fc.length == 0)) {byte[] registers = {0, 0, 0, 0};writeMCPFilterMaskRegisters(0, registers);writeMCPFilterMaskRegisters(1, registers);return;}// 检查过滤器数量(范围)的最大值的大小if (fc.length > 2) {throw new USBtinException("Too many filter chains: " + fc.length + " (maximum is 2)!");}// 必要时交换通道,检查过滤器长度if (fc.length == 2) {if (fc[0].getFilters().length > fc[1].getFilters().length) {FilterChain temp = fc[0];fc[0] = fc[1];fc[1] = temp;}if ((fc[0].getFilters().length > 2) || (fc[1].getFilters().length > 4)) {throw new USBtinException("Filter chain too long: " + fc[0].getFilters().length + "/" + fc[1].getFilters().length + " (maximum is 2/4)!");}} else if (fc.length == 1) {if ((fc[0].getFilters().length > 4)) {throw new USBtinException("Filter chain too long: " + fc[0].getFilters().length + " (maximum is 4)!");}}// set MCP2515 filter/mask registers; walk through filter channels 设置MCP2515滤波器/掩码寄存器,遍历过滤通道int filterid = 0;int fcidx = 0;for (int channel = 0; channel < 2; channel++) {// set mask 设置掩码writeMCPFilterMaskRegisters(channel, fc[fcidx].getMask().getRegisters());// set filters 设置过滤器byte[] registers = {0, 0, 0, 0};for (int i = 0; i < (channel == 0 ? 2 : 4); i++) {if (fc[fcidx].getFilters().length > i) {registers = fc[fcidx].getFilters()[i].getRegisters();}writeMCPFilterRegisters(filterid, registers);filterid++;}// 如果可用,转到下一个过滤器链if (fc.length - 1 > fcidx) {fcidx++;}}}
}
1.1 CANSender 类
CANSender 类是 USBtin 的派生类,新增2个抽象方法和1个普通方法。
//CANSender.java
package host_communication; // 声明包名为host_communicationimport USBtin.CANMessage; // 导入USBtin包中的CANMessage类
import USBtin.USBtin; // 导入USBtin包中的USBtin类
import USBtin.USBtinException; // 导入USBtin包中的USBtinException类public abstract class CANSender extends USBtin { // 声明一个抽象类CANSender,继承自USBtin类public abstract CANMessage getMessageToSend(); // 声明一个抽象方法getMessageToSend,用于获取要发送的CAN消息public abstract void sendMessage(CANMessage message); // 声明一个抽象方法sendMessage,用于发送CAN消息public void closedCC() { // 声明一个方法closedCC,用于关闭CAN通道try {this.closeCANChannel(); // 尝试关闭CAN通道this.disconnect(); // 尝试断开连接} catch (USBtinException ex) { // 捕获USBtinException异常ex.printStackTrace(); // 打印异常堆栈信息}}
}
1.1.1 SimpleSender类
CANSender 类是 CANSender(抽象类) 的派生类,实现了2个抽象方法。定义了1个成员变量和一个构造方法。
//SimpleSender.java
package host_communication; // 声明包名为host_communicationimport USBtin.CANMessage; // 导入USBtin包中的CANMessage类
import USBtin.USBtin; // 导入USBtin包中的USBtin类
import USBtin.USBtinException; // 导入USBtin包中的USBtinException类public class SimpleSender extends CANSender { // 声明一个类SimpleSender,继承自CANSender类private CANMessage message; // 声明一个私有的CANMessage类型的变量messagepublic SimpleSender(CANMessage mess, String port, int channel) { // 声明一个构造方法,接收CANMessage类型的mess、String类型的port和int类型的channel参数this.message = mess; // 将mess赋值给message变量try {this.connect(port); // 尝试连接指定的端口this.openCANChannel(channel, USBtin.OpenMode.ACTIVE); // 尝试打开指定通道,并设置为活动模式} catch (USBtinException e) { // 捕获USBtinException异常e.printStackTrace(); // 打印异常堆栈信息}}@Overridepublic CANMessage getMessageToSend() { // 实现抽象方法getMessageToSend,用于获取要发送的CAN消息return this.message; // 返回message变量}@Overridepublic void sendMessage(CANMessage message) { // 实现抽象方法sendMessage,用于发送CAN消息try {this.send(message); // 尝试发送消息} catch (USBtinException e) { // 捕获USBtinException异常e.printStackTrace(); // 打印异常堆栈信息}}}
1.2 CANReceiver类
CANReceiver 类是 USBtin 的派生类,新增1个普通方法。
package host_communication;import USBtin.USBtin;
import USBtin.USBtinException;public abstract class CANReceiver extends USBtin {public void closedCC() {try {this.closeCANChannel();this.disconnect();} catch (USBtinException ex) {ex.printStackTrace();}}}
1.2.1 SimpleReceiver类
SimpleReceiver类是CANReceiver的派生类。定义了1个构造函数。
//SimpleReceiver.java
package host_communication; //声明包名为host_communicationimport USBtin.USBtinException; // 导入USBtin包中的USBtinException类
import USBtin.USBtin; // 导入USBtin包中的USBtin类public class SimpleReceiver extends CANReceiver { // 声明一个类SimpleReceiver,继承自CANReceiver类public SimpleReceiver(String port, int channel) { // 声明一个构造方法,接收String类型的port和int类型的channel参数super(); // 调用父类的无参构造方法try {this.connect(port); // 尝试连接指定的端口this.openCANChannel(channel, USBtin.OpenMode.ACTIVE); // 尝试打开指定通道,并设置为活动模式} catch (USBtinException e) { // 捕获USBtinException异常e.printStackTrace(); // 打印异常堆栈信息}}}
1.3 Noise_node类
Noise_node类是USBtin的派生类。定义了2个成员变量和3个成员方法。
//Noise_node.java
package noise; //声明包名为noiseimport USBtin.CANMessage; //导入USBtin包中的CANMessage类
import USBtin.USBtin; //导入USBtin包中的USBtin类
import USBtin.USBtinException; //导入USBtin包中的USBtinException类public class Noise_node extends USBtin { //声明一个类Noise_node,继承自USBtin类private long PERIOD; //声明一个私有的long类型变量PERIODprivate boolean running = true; //声明一个私有的boolean类型变量running,并初始化为truepublic Noise_node(long period) { //声明一个构造方法,接收一个long类型的period参数PERIOD = period; //将period赋值给PERIOD变量if (PERIOD == 0) { //如果PERIOD等于0running = false; //将running设置为false}}public void start(CANMessage mess) { //声明一个方法start,接收一个CANMessage类型的mess参数while (running) { //当running为true时执行循环try {Thread.sleep((long) (PERIOD)); //线程休眠指定的时间this.send(mess); //发送mess消息} catch (InterruptedException | USBtinException e) { //捕获InterruptedException或USBtinException异常e.printStackTrace(); //打印异常堆栈信息}}}public void stop() { //声明一个方法stopthis.running = false; //将running设置为false}
}
二、CANMessageListener 接口
CANMessageListener家族
CANMessageListener 接口具有3个实现类。
- IAT_Monitor类
- BasicListener类
- DLC_Monitor类
CANMessageListener 接口
CANMessageListener 接口代码
//CANMessageListener.java
package USBtin;/*** CAN消息监听器.*/
public interface CANMessageListener {/*** 方法在CAN消息传入时被调用** @param canmsg 接收的CAN消息*/public void receiveCANMessage(CANMessage canmsg);
}
2.1 IAT_Monitor
IAT_Monitor类是CANMessageListener接口的实现类。具有22个成员变量和6个成员函数。
代码:
// IAT_Monitor.java
package transmission_channel.IAT_channel;import attestation.AttestationProtocol;
import USBtin.CANMessage;
import USBtin.CANMessageListener;
import error_detection.ErrorCorrectionCode;
import util.CANAuthMessage;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;public class IAT_Monitor implements CANMessageListener {private final int WINDOW_LENGTH;private final long PERIOD;private final long DELTA;private final long WATCH_ID;private final int CHANNEL;private final long NOISE_PERIOD;private long lastArrival;private List<Long> window = new LinkedList<>();private boolean detecting = false;private List<Byte> authMessage = new LinkedList<>();private FileWriter filewriterIAT;private FileWriter filewriterREL;private ErrorCorrectionCode corrector;private AttestationProtocol protocol;private long counter;private int silence_start;private int silence_end;private int silence_counter;private IATBitConverter converter;private boolean stopping;private boolean starting;private int total_received;public IAT_Monitor(long period, long delta, int windowLength, int watchid, int channel, long nperiod,int silence_start, int silence_end, IATBitConverter converter) {this.PERIOD = period;this.DELTA = delta;this.WINDOW_LENGTH = windowLength;this.WATCH_ID = watchid;this.CHANNEL = channel;this.NOISE_PERIOD = nperiod;this.silence_start = silence_start;this.silence_end = silence_end;this.converter = converter;// 统计数据try {// 创建文件夹new File("timings").mkdir();// 创建文件夹new File("reliability").mkdir();// 创建csv文件,filewriterIAT对象用于写入文件this.filewriterIAT = new FileWriter("timings/IAT_" + "P" + PERIOD + "_D" + DELTA + "_C" +CHANNEL + "_N" + NOISE_PERIOD + ".csv");// this.filewriterREL = new FileWriter("reliability/IATrel_" + "_D" + DELTA + "_C" +// CHANNEL + "_N" + NOISE_PERIOD + ".csv");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void receiveCANMessage(CANMessage message) {if (message.getId()==this.WATCH_ID) {this.counter += 1;long currentTime = System.currentTimeMillis();// 收到的第一条消息if (lastArrival == 0) {lastArrival = currentTime;window.add(PERIOD);return;}long IAT = currentTime - lastArrival;// 保存IATtry {this.filewriterIAT.append(IAT + ";" + System.currentTimeMillis() + "\n");} catch (IOException e) {e.printStackTrace();}lastArrival = currentTime;// sample running average 样本运行平均值window.add(IAT);if (window.size() == WINDOW_LENGTH) {detectBit(window);window = new LinkedList<>();}}}private String detectBit(List<Long> fullWindow) {long sum = 0L;for (long v : fullWindow) {sum += v;}long avg = sum / fullWindow.size();int intervals = this.converter.getIntervals(avg);if (intervals != 0) {if (starting) {//正确的(采取的)行为是开始的沉默位之后if (silence_counter >= silence_start) {detecting = true;starting = false;silence_counter = 0;this.authMessage.addAll(this.converter.convertFromIntervals(intervals));return authMessage.toString();}else {starting = false;silence_counter = 0;authMessage = new LinkedList<>();return "Garbage bit";}}else if (stopping) {stopping = false;silence_counter = 0;this.authMessage = new LinkedList<>();return "Garbage bit";}// 正确行为:在检测过程中if (detecting) {this.authMessage.addAll(this.converter.convertFromIntervals(intervals));return this.authMessage.toString();}}else {silence_counter++;// Correct behaviour : start of start silence// 正确行为:开始沉默位时开始if (!starting && !detecting && !stopping) {starting = true;silence_counter = 1;authMessage = new LinkedList<>();return "Silence bit";}// Correct behaviour : start of end silence// 正确行为:结束沉默位时开始if (detecting) {detecting = false;stopping = true;silence_counter = 1;}if (stopping) {// Correct behaviour : end of end silence -> end of message// 正确行为:结束沉默位结束时 -> 消息结束if (silence_counter >= silence_end) {stopping = false;silence_counter = 0;int attSize = authMessage.size();// Check error detection// 错误检测if (this.corrector == null) {System.out.println("DETECTED MESSAGE: " + authMessage);}else if (this.corrector.checkCodeForAuthMessage(authMessage)) {List<Byte> mess = authMessage.subList(0, authMessage.size() - this.corrector.getNrCorrectingBits());attSize = mess.size();System.out.println("DETECTED MESSAGE: " + mess + " COUNTER: " + this.counter);}else {
// try {
// this.filewriterREL.append("O\n");
// } catch (IOException e) {
// e.printStackTrace();
// }System.out.println("Error in transmission detected! Received: " + authMessage + " COUNTER: " + counter);this.authMessage = new LinkedList<>();return "Silence bit";}// 检查认证if (this.protocol != null) {CANAuthMessage auth = new CANAuthMessage(authMessage.subList(0, attSize));if (this.protocol.checkAttestationMessage(auth)) {System.out.println("Attestation OK");this.total_received++;// try {
// this.filewriterREL.append("1\n");
// } catch (IOException e) {
// e.printStackTrace();
// }}else {System.out.println("Attestation NOK");// try {
// this.filewriterREL.append("O\n");
// } catch (IOException e) {
// e.printStackTrace();
// }}}else {this.total_received++;// try {
// this.filewriterREL.append("1\n");
// } catch (IOException e) {
// e.printStackTrace();
// }}this.authMessage = new LinkedList<>();return "Silence bit";}}return "Silence bit";}return "No bit detected";}public void setCorrector(ErrorCorrectionCode corrector) {this.corrector = corrector;}public void setProtocol(AttestationProtocol prot) {this.protocol = prot;}public void leave() {// 统计数据System.out.println("Total received: " + this.total_received);try {this.filewriterIAT.close();// this.filewriterREL.close();} catch (IOException e) {e.printStackTrace();}}}
2.2 BasicListener
BasicListener类是CANMessageListener接口的实现类。实现了接口中的方法。
代码:
package util;import USBtin.CANMessage;
import USBtin.CANMessageListener;// 实现CANMessageListener接口的基本监听器类
public class BasicListener implements CANMessageListener {@Overridepublic void receiveCANMessage(CANMessage canmsg) {// 打印接收到的消息System.out.println("Watched message: " + canmsg.toString());}
}
2.3 DLC_Monitor
DLC_Monitor类是CANMessageListener接口的实现类。具有5个成员变量和5个成员函数。
代码:
// DLC_Monitor.java
package transmission_channel.DLC_channel;import USBtin.CANMessage;
import USBtin.CANMessageListener;
import attestation.AttestationProtocol;
import error_detection.ErrorCorrectionCode;
import util.CANAuthMessage;import java.util.LinkedList;
import java.util.List;public class DLC_Monitor implements CANMessageListener {private boolean detecting = false; // 表示是否正在检测消息private List<Byte> authMessage = new LinkedList<>(); // 用于存储认证消息的列表private ErrorCorrectionCode corrector; // 错误校正码private AttestationProtocol protocol; // 认证协议private int WATCHID; // 监控的IDpublic DLC_Monitor(int watchid) {this.WATCHID = watchid; // 初始化监控的ID}@Overridepublic void receiveCANMessage(CANMessage message) {detectBit(message); // 接收到CAN消息时调用detectBit方法进行处理}private void detectBit(CANMessage message) {if (message.getId() == this.WATCHID) { // 检查消息ID是否与监控的ID匹配int DLC = message.getDLC(); // 获取消息的数据长度码if (detecting) { // 如果正在检测消息if (DLC > 8) { // 如果数据长度码大于8// 根据数据长度码的不同情况添加认证消息switch (DLC) {case (DLC_Node.DLC_0):authMessage.add((byte) 0);return;case (DLC_Node.DLC_1):authMessage.add((byte) 1);return;case (DLC_Node.DLC_00):authMessage.add((byte) 0);authMessage.add((byte) 0);return;case (DLC_Node.DLC_01):authMessage.add((byte) 0);authMessage.add((byte) 1);return;case (DLC_Node.DLC_10):authMessage.add((byte) 1);authMessage.add((byte) 0);return;case (DLC_Node.DLC_11):authMessage.add((byte) 1);authMessage.add((byte) 1);return;}}}// 如果数据长度码等于静默位的数据长度码if (DLC == DLC_Node.SILENCE_BIT_DLC) { // 如果正在检测消息if (detecting) { // 检查错误校正码if (this.corrector == null) { // 如果没有设置错误校正码System.out.println("DETECTED MESSAGE: " + authMessage); // 输出检测到的消息} else if (this.corrector.checkCodeForAuthMessage(authMessage)) { // 如果校验通过if (authMessage.size() - this.corrector.getNrCorrectingBits() < 0) {System.out.println("Error in transmission detected! (too little bits)"); // 检测到传输错误(位数过少)} else {List<Byte> mess = authMessage.subList(0, authMessage.size() - this.corrector.getNrCorrectingBits());System.out.println("DETECTED MESSAGE: " + mess); // 输出检测到的消息}} else {System.out.println("Error in transmission detected! (wrong bits): " + authMessage); // 检测到传输错误(错误的位)}// 检查认证int size = authMessage.size() - this.corrector.getNrCorrectingBits() > 0 ?authMessage.size() - this.corrector.getNrCorrectingBits() :0;CANAuthMessage canAuthMessage = this.corrector == null ?new CANAuthMessage(authMessage) :new CANAuthMessage(authMessage.subList(0, size));if (this.protocol.checkAttestationMessage(canAuthMessage)) {System.out.println("Attestation OK"); // 认证通过} else {System.out.println("Attestation NOK"); // 认证不通过}}authMessage = new LinkedList<>(); // 重置认证消息列表detecting = !detecting; // 切换检测状态}}}public void setCorrector(ErrorCorrectionCode corrector) {this.corrector = corrector; // 设置错误校正码}public void setAttestation(AttestationProtocol protocol) {this.protocol = protocol; // 设置认证协议}}
三、IATBitConverter 抽象类
IATBitConverter类是一个抽象类。具有3个成员变量和7个成员方法(5个普通方法和2个抽象方法)。
package transmission_channel.IAT_channel;import java.util.List;// IAT位转换器的抽象类
public abstract class IATBitConverter {private long period; // 周期private long delta; // 增量private int bits; // 编码位数// 构造函数IATBitConverter(long period, long delta, int bits) {this.period = period; // 设置周期this.delta = delta; // 设置增量this.bits = bits; // 设置编码位数}// 根据IAT计算间隔数public int getIntervals(long IAT) {return Math.round(((float)(IAT-this.period))/(float)this.delta); // 计算间隔数}// 获取编码位数public int getBitsEncoded() {return this.bits; // 返回编码位数}// 从IAT转换为字节列表public List<Byte> convertFromIAT(long IAT) {return convertFromIntervals(getIntervals(IAT)); // 转换为间隔数后再转换为字节列表}// 从字节列表转换为IATpublic long convertToIAT(List<Byte> bytes) {return this.period + this.delta*convertToIntervals(bytes); // 根据间隔数转换为IAT}// 抽象方法:根据间隔数转换为字节列表abstract List<Byte> convertFromIntervals(int intervals);// 抽象方法:根据字节列表转换为间隔数abstract int convertToIntervals(List<Byte> bytes);
}
3.1 OneBitConverter类
/** OneBitConverter 扩展了IATBitConverter类,并提供了将间隔与字节相互转换的方法.*/
package transmission_channel.IAT_channel;import java.util.LinkedList;
import java.util.List;public class OneBitConverter extends IATBitConverter {/** 构造方法.* @param period The period.* @param delta The delta.* @param bits The number of bits.*/public OneBitConverter(long period, long delta, int bits) {super(period, delta, bits);}/** 间隔数转为字节列表* @param intervals The intervals to be converted.* @return A list of bytes.*/@OverrideList<Byte> convertFromIntervals(int intervals) {List<Byte> result = new LinkedList<>();if (intervals == -1) { result.add( (byte) 0 ); }if (intervals == 1) { result.add( (byte) 1 ); }return result;}/** 字节列表转换为间隔数.* @param bytes 要转换的字节列表.* @return The intervals .*/@Overrideint convertToIntervals(List<Byte> bytes) {if (bytes.get(0) == ( (byte) 0) ) { return -1; }return 1;}
}
3.2 TwoBitConverter类
/** TwoBitConverter 扩展了IATBitConverter类,并提供了将间隔与字节相互转换的方法。*/
package transmission_channel.IAT_channel;import java.util.LinkedList;
import java.util.List;public class TwoBitConverter extends IATBitConverter {// 表示不同间隔的常量private final int INT_0 = 3;private final int INT_00 = 2;private final int INT_01 = 1;private final int INT_10 = -1;private final int INT_11 = -2;private final int INT_1 = -3;/** 构造函数* @param period 周期* @param delta 增量.* @param bits 编码位数.*/public TwoBitConverter(long period, long delta, int bits) {super(period, delta, bits);}/** 间隔数转为字节列表.* @param intervals 间隔数.* @return A list of bytes.*/@OverrideList<Byte> convertFromIntervals(int intervals) {List<Byte> result = new LinkedList<>();switch (intervals) {case (INT_0):result.add( (byte) 0 );break;case (INT_00):result.add( (byte) 0 );result.add( (byte) 0 );break;case (INT_01):result.add( (byte) 0 );result.add( (byte) 1 );break;case (INT_10):result.add( (byte) 1 );result.add( (byte) 0 );break;case (INT_11):result.add( (byte) 1 );result.add( (byte) 1 );break;case (INT_1):result.add( (byte) 1 );break;}return result;}/** 间隔数转换为字节列表.* @param bytes 要转换的字节数.* @return The intervals.*/@Overrideint convertToIntervals(List<Byte> bytes) {if (bytes.get(0).equals( (byte) 0 )) {if (bytes.size() == 1) { return INT_0; }if (bytes.get(1).equals( (byte) 0 )) { return INT_00; }return INT_01;}if (bytes.size() == 1) { return INT_1; }if (bytes.get(1).equals( (byte) 0 )) { return INT_10; }if (bytes.get(1).equals( (byte) 1 )) { return INT_11; }return 0;}}
四、ErrorCorrectionCode 错误纠正码接口
/** ErrorCorrectionCode 提供用于错误校正码的方法。*/
package error_detection;import util.CANAuthMessage; // 导入CANAuthMessage类
import java.util.List; // 导入List接口public interface ErrorCorrectionCode {// 获取纠正位的数量int getNrCorrectingBits();// 获取CANAuthMessage的错误校正码List<Byte> getCodeForAuthMessage(CANAuthMessage message);// 检查CANAuthMessage的错误校正码boolean checkCodeForAuthMessage(List<Byte> message);
}
4.1 SimpleCRC类
/** 这个类实现了ErrorCorrectionCode接口,用于简单的CRC(循环冗余校验)。*/
public class SimpleCRC implements ErrorCorrectionCode {private int N; // 用于存储纠正位的数量private String polynomial = ""; // 用于存储多项式// 构造函数public SimpleCRC(int n, String polynomial) {// 如果n大于0且多项式的长度等于n+1,则进行初始化if (n > 0 && polynomial.length() == n+1) {this.N = n;this.polynomial = polynomial;}}// 获取纠正位的数量@Overridepublic int getNrCorrectingBits() {return this.N;}// 获取CANAuthMessage的错误校正码@Overridepublic List<Byte> getCodeForAuthMessage(CANAuthMessage message) {// 填充被除数String dividend = bytesToString(message.getMessage());for (int i=0; i<this.N; i++) { dividend += "0"; }String remainder = CRCdivision(dividend);return stringToBytes(remainder);}// 检查CANAuthMessage的错误校正码@Overridepublic boolean checkCodeForAuthMessage(List<Byte> message) {if (message.size() < this.N*2) {return false;}String dividend = bytesToString(message);String remainder = CRCdivision(dividend);String wantedRemainder = "";for (int i=0; i<this.N; i++) { wantedRemainder += "0"; }return remainder.equals(wantedRemainder);}// CRC(循环冗余校验)的除法运算private String CRCdivision(String dividend) {String divisor = this.polynomial;while (divisor.length() < dividend.length()) { divisor += "0"; }String padded_divisor = divisor;while (dividend.contains("1") && dividend.indexOf("1")<dividend.length()-this.N) {// 对齐除数和被除数int offset = dividend.indexOf("1");divisor = padded_divisor;if (offset>0) { for (int i=0; i<offset; i++) { divisor = "0" + divisor; } }divisor = divisor.substring(0, dividend.length());// 执行除法String new_dividend = "";for (int i=0; i<dividend.length(); i++) {char d1 = dividend.charAt(i);char d2 = divisor.charAt(i);new_dividend += (d1 == d2) ? "0" : "1";}dividend = new_dividend;}// 提取最后N位(余数)return dividend.substring(dividend.length()-this.N);}// 将字节列表转换为字符串private String bytesToString(List<Byte> bytes) {String result = "";for (int i=0; i<bytes.size(); i++) {if (bytes.get(i).equals( (byte) 1 )) {result += "1";}else {result += "0";}}return result;}// 将字符串转换为字节列表private List<Byte> stringToBytes(String str) {List<Byte> result = new LinkedList<>();for (int i=0; i<str.length(); i++) {if (str.charAt(i) == '1') {result.add( (byte) 1 );}else {result.add( (byte) 0 );}}return result;}
}
4.2 SimpleParity
/** 这个类实现了ErrorCorrectionCode接口,用于简单的奇偶校验。*/
public class SimpleParity implements ErrorCorrectionCode {// 获取纠正位的数量@Overridepublic int getNrCorrectingBits() {return 1;}// 获取CANAuthMessage的错误校正码@Overridepublic List<Byte> getCodeForAuthMessage(CANAuthMessage message) {// 计算消息中1的个数int paritycounter = 0;for (int i=0 ; i<message.getMessage().size() ; i++) {if (message.getMessage().get(i) == ((byte) 1)) {paritycounter += 1;}}// 根据奇偶性添加校验位List<Byte> result = new LinkedList<Byte>();if (paritycounter%2 == 0) { result.add( (byte) 0 ); }else { result.add( (byte) 1 ); }return result;}// 检查CANAuthMessage的错误校正码@Overridepublic boolean checkCodeForAuthMessage(List<Byte> message) {// 计算消息中1的个数int paritycounter = 0;for (int i=0 ; i<message.size() ; i++) {if (message.get(i).equals( (byte) 1 )) {paritycounter += 1;}}// 检查奇偶性return (paritycounter%2 == 0);}
}
这篇关于【论文代码】基于隐蔽带宽的汽车控制网路鲁棒认证-到达时间间隔通道的Java实现(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!