此篇文章是对原有代码的注释进行翻译,尝试对其架构和实现方式进行理解。
项目结构
Java实现代码
如图UML类图:
从图中明显可见,其代码组织方式,各个代码文件的继承和实现的关系。
以下内容围绕UML类图,分别进行阐述。
/*
* 这个抽象类定义了传输线程的基本结构,用于处理通信和校验相关的功能。
*/
package transmission_channel;
import attestation.AttestationProtocol;
import error_detection.ErrorCorrectionCode;
import host_communication.CANReceiver;
import host_communication.CANSender;
public abstract class TransmissionThread extends Thread {
// 错误校正码实例
private ErrorCorrectionCode corrector;
// 认证协议的实例
private AttestationProtocol attestationProtocol;
// 添加错误校正码
public void addAuthCorrectionCode(ErrorCorrectionCode corrector) {
this.corrector = corrector;
}
// 添加认证协议
public void addAttestationProtocol(AttestationProtocol prot) { this.attestationProtocol = prot; }
// 抽象方法:运行
public abstract void run();
// 抽象方法:结束
public abstract void end();
// 获取错误校正码实例
public ErrorCorrectionCode getCorrector() { return this.corrector; }
// 获取认证协议实例
public AttestationProtocol getAttestationProtocol() { return this.attestationProtocol; }
}
package transmission_channel.IAT_channel;
import attestation.AttestationProtocol;
import USBtin.CANMessage;
import USBtin.USBtin;
import USBtin.USBtinException;
import error_detection.ErrorCorrectionCode;
import host_communication.CANReceiver;
import host_communication.CANSender;
import transmission_channel.TransmissionThread;
public class IAT_Thread extends TransmissionThread {
private long PERIOD;
private long DELTA;
private int WATCH_ID;
private int WINDOW_LENGTH;
private long NOISE_PERIOD;
private int CHANNEL;
private CANReceiver receiver;
private CANSender sender;
private IAT_Monitor IAT_receiver;
private IAT_Node IAT_sender;
private ErrorCorrectionCode corrector;
private AttestationProtocol protocol;
private int silence_start;
private int silence_end;
private IATBitConverter converter;
public IAT_Thread(long period, long delta, int window_length, int watchid,
long nperiod, int silence_start, int silence_end, IATBitConverter converter,
CANReceiver receiver, CANSender sender, int channel) {
this.PERIOD = period;
this.DELTA = delta;
this.WINDOW_LENGTH = window_length;
this.WATCH_ID = watchid;
this.NOISE_PERIOD = nperiod;
this.CHANNEL = channel;
this.silence_start = silence_start;
this.silence_end = silence_end;
this.converter = converter;
this.receiver = receiver;
this.sender = sender;
}
public void addAuthCorrectionCode(ErrorCorrectionCode corrector) {
this.corrector = corrector;
}
public void addAttestationProtocol(AttestationProtocol prot) { this.protocol = prot; }
public void run() {
// 创建IAT发送者和接收者
IAT_Node IAT_sender = new IAT_Node(PERIOD, WINDOW_LENGTH, silence_start, silence_end, converter,
DELTA, CHANNEL, NOISE_PERIOD, this.sender);
IAT_Monitor IAT_receiver = new IAT_Monitor(PERIOD, DELTA, WINDOW_LENGTH, WATCH_ID, CHANNEL, NOISE_PERIOD,
silence_start, silence_end, converter);
this.IAT_sender = IAT_sender;
this.IAT_receiver = IAT_receiver;
// 添加身份认证错误纠正
if (this.corrector != null) {
this.IAT_sender.setCorrector(this.corrector);
this.IAT_receiver.setCorrector(this.corrector);
}
// 添加认证协议
if (this.protocol != null) {
this.IAT_sender.setProtocol(this.protocol);
this.IAT_receiver.setProtocol(this.protocol);
}
// 把物理接收器连接到IAT接收器
receiver.addMessageListener(this.IAT_receiver);
// IAT-sender启动
IAT_sender.start();
}
public void end() {
this.IAT_sender.leave();
this.IAT_receiver.leave();
this.sender.closedCC();
this.receiver.closedCC();
}
}
package transmission_channel.DLC_channel;
import USBtin.CANMessage;
import USBtin.USBtin;
import USBtin.USBtinException;
import host_communication.CANReceiver;
import host_communication.CANSender;
import transmission_channel.TransmissionThread;
public class DLC_Thread extends TransmissionThread {
private long PERIOD;
private int WATCHID;
private DLC_Node DLC_sender;
private DLC_Monitor DLC_monitor;
private CANSender host_sender;
private CANReceiver host_receiver;
private boolean running = true;
// 构造函数
public DLC_Thread(long period, int watchid, CANReceiver receiver, CANSender sender) {
this.PERIOD = period;
this.WATCHID = watchid;
this.host_sender = sender;
this.host_receiver = receiver;
}
public void run() {
// 创建DLC发送者和接收者实例
DLC_Node sender = new DLC_Node(this.PERIOD, this.host_sender);
DLC_Monitor monitor = new DLC_Monitor(this.WATCHID);
this.DLC_sender = sender;
this.DLC_monitor = monitor;
// 添加错误检测
if (this.getCorrector() != null) {
this.DLC_sender.setCorrector(this.getCorrector());
this.DLC_monitor.setCorrector(this.getCorrector());
}
// 添加认证协议
if (this.getAttestationProtocol() != null) {
this.DLC_sender.setAttestation(this.getAttestationProtocol());
this.DLC_monitor.setAttestation(this.getAttestationProtocol());
}
// 连接到USBtin.USBtin并且以Active模式打开CAN通道
host_receiver.addMessageListener(monitor);
DLC_sender.start();
}
public void end() {
this.host_receiver.closedCC();
this.host_sender.closedCC();
DLC_sender.leave();
}
}
/*
* 这个接口定义了认证协议的基本功能,用于生成认证消息和检查认证消息的有效性。
*/
package attestation;
import util.CANAuthMessage;
import USBtin.USBtin;
public interface AttestationProtocol {
// 获取认证消息
CANAuthMessage getAttestationMessage();
// 检查认证消息
boolean checkAttestationMessage(CANAuthMessage message);
}
/*
* 这个类实现了AttestationProtocol接口,用于硬编码的认证协议。
*/
package attestation;
import util.CANAuthMessage;
import USBtin.USBtin;
import java.util.LinkedList;
import java.util.List;
public class HardCodedAttestation implements AttestationProtocol {
private List<Byte> message;
// 构造函数
public HardCodedAttestation(byte[] mess) {
this.message = new LinkedList<>();
for (int i=0; i<mess.length; i++) {
this.message.add(mess[i]);
}
}
// 获取认证消息
@Override
public CANAuthMessage getAttestationMessage() {
return new CANAuthMessage(this.message);
}
// 检查认证消息
@Override
public boolean checkAttestationMessage(CANAuthMessage message) {
return this.message.equals(message.getMessage());
}
}
package USBtin;
/**
* Represents the CAN filter mask registers.表示CAN过滤器掩码寄存器。
*/
public class FilterMask {
/** Registers in MCP2515 style MCP2515风格的寄存器 */
protected byte[] registers = new byte[4];
/**
* Create filer mask for extended CAN messages.为CAN扩展帧创建掩码过滤器
*
* Bitmask: 位掩码:
* 0 - accept (accept regardless of filter)不管过滤器是什么都接受
* 1 - check (accept only if filter matches)只有当过滤器匹配时才接受
*
* Examples:
* fm1 = new USBtin.FilterMask(0x1fffffff); // 检查整个扩展ID
* fm2 = new USBtin.FilterMask(0x1fffff00); // 检查除后8位以外的扩展ID
*
* @param extid CAN标识符的过滤掩码
*/
public FilterMask(int extid) {
registers[0] = (byte)((extid >> 21) & 0xff);
registers[1] = (byte)(((extid >> 16) & 0x03) | ((extid >> 13) & 0xe0));
registers[2] = (byte)((extid >> 8) & 0xff);
registers[3] = (byte)(extid & 0xff);
}
/**
* Create filter mask for standard CAN messages.为标准CAN帧创建掩码过滤器
*
* Bitmask:位掩码
* 0 - accept (accept regardless of filter)
* 1 - check (accept only if filter matches)
*
* Examples:
* fm1 = new USBtin.FilterMask(0x7ff, (byte)0x00, (byte)0x00); // 检查整个id,数据域不检查
* fm2 = new USBtin.FilterMask(0x7f0, (byte)0x00, (byte)0x00); // 检查除最后4位以外的整个id,数据字节无关
* fm2 = new USBtin.FilterMask(0x7f0, (byte)0xff, (byte)0x00); // 检查除最后4位以外的整个id,检查第一个数据字节,第二个是无关的
*
* @param sid CAN标识符的过滤掩码
* @param d0 数据域第一个字节的过滤掩码
* @param d1 数据域第二个字节的过滤掩码
*/
public FilterMask(int sid, byte d0, byte d1) {
registers[0] = (byte) ((sid >> 3) & 0xff);
registers[1] = (byte) ((sid & 0x7) << 5);
registers[2] = d0;
registers[3] = d1;
}
/**
* Get register values in MCP2515 style 获取MCP2515风格的寄存器值
*
* @return Register values
*/
public byte[] getRegisters() {
return registers;
}
}
package USBtin;
/**
* 表示CAN过滤器寄存器
*/
public class FilterValue extends FilterMask {
/**
* 为CAN扩展帧创建过滤器
*
* @param extid 扩展标识符过滤器
*/
public FilterValue(int extid) {
super(extid);
registers[1] |= 0x08;
}
/**
* 为标准帧创建过滤器
* @param sid 标准标识符过滤器
* @param d0 筛选第一个数据字节
* @param d1 筛选第二个数据字节
*/
public FilterValue(int sid, byte d0, byte d1) {
super(sid, d0, d1);
}
}
/*
* 这个类表示CAN认证消息,包括消息内容和校正码。
*/
package util;
import error_detection.ErrorCorrectionCode;
import java.util.LinkedList;
import java.util.List;
public class CANAuthMessage {
// 消息内容
private List<Byte> message = new LinkedList<Byte>();
// 校正码
private List<Byte> correctionCode = new LinkedList<Byte>();
// 构造函数
public CANAuthMessage(List<Byte> message) {
this.message = message;
}
// 设置校正码
public void setCorrectionCode(ErrorCorrectionCode corrector) {
this.correctionCode = corrector.getCodeForAuthMessage(this);
}
// 转换为字节数组
public List<Byte> toByteArray() {
List<Byte> result = new LinkedList<>();
result.addAll(this.message);
result.addAll(this.correctionCode);
return result;
}
// 获取消息内容
public List<Byte> getMessage() {
return this.message;
}
}
package USBtin;
/**
* USBtin.USBtin 自定义异常类
*/
public class USBtinException extends Exception {
/**
* 标准构造器
*/
public USBtinException() {
super();
}
/**
* 异常构造器
*
* @param message 异常消息字符串
*/
public USBtinException(String message) {
super(message);
}
/**
* 异常构造器
*
* @param message 异常消息
* @param cause 异常原因
*/
public USBtinException(String message, Throwable cause) {
super(message, cause);
}
/**
* 异常构造器
*
* @param cause 异常的原因
*/
public USBtinException(Throwable cause) {
super(cause);
}
}
这个是主函数位置。
/*
* 演示如何使用USBtin库进行CAN总线通信的示例代码。
*/
import host_communication.CANReceiver;
import host_communication.CANSender;
import host_communication.SimpleReceiver;
import host_communication.SimpleSender;
import transmission_channel.DLC_channel.DLC_Thread;
import transmission_channel.IAT_channel.IATBitConverter;
import transmission_channel.IAT_channel.IAT_Thread;
import attestation.AttestationProtocol;
import attestation.HardCodedAttestation;
import USBtin.*;
import error_detection.ErrorCorrectionCode;
import error_detection.SimpleCRC;
import noise.NoiseThread;
import transmission_channel.IAT_channel.TwoBitConverter;
import transmission_channel.TransmissionThread;
import java.io.IOException;
public class USBtinLibDemo {
private static final long PERIOD = 200;
private static final long DELTA = 7;
private static final int WINDOW_LENGTH = 4;
private static final int CHANNEL = 50000;
private static final long NOISE_PERIOD = 1; // NOISE_PERIOD=0 --> no noise
private static final String SENDER_PORT = "/dev/tty.usbmodemA021CFBA1";
private static final String NOISE_PORT = "/dev/tty.usbmodemA02102821";
private static final String RECEIVER_PORT = "/dev/tty.usbmodemA02183211";
private static final int WATCHID = 0x100;
private static final int START_SILENCE = 2;
private static final int END_SILENCE = 2;
private static final IATBitConverter CONVERTER = new TwoBitConverter(PERIOD, DELTA, 2);
private static ErrorCorrectionCode AUTH_CORRECTOR = new SimpleCRC(2, "101"); // 在这里设置错误校正实例
private static AttestationProtocol AUTH_PROTOCOL = new HardCodedAttestation(new byte[]{1,1,0,0,1}); // 设置认证协议
// private static TransmissionThread TRANSMISSION_CHANNEL = // 在这里设置传输通道
// new IAT_Thread(PERIOD, DELTA, WINDOW_LENGTH, WATCHID, NOISE_PERIOD, START_SILENCE, END_SILENCE,
// CONVERTER, new SimpleReceiver(RECEIVER_PORT, CHANNEL),
// new SimpleSender(new CANMessage(WATCHID, new byte[]{0x11, 0x22, 0x33}), SENDER_PORT, CHANNEL),
// CHANNEL);
// new DLC_Thread(PERIOD, WATCHID,
// new SimpleReceiver(RECEIVER_PORT, CHANNEL),
// new SimpleSender(new CANMessage(WATCHID, new byte[]{0x11, 0x22, 0x33, 0x44}),SENDER_PORT, CHANNEL)
// );
public static void main(String[] args) {
// 运行传输线程
// TRANSMISSION_CHANNEL.addAuthCorrectionCode(AUTH_CORRECTOR);
// TRANSMISSION_CHANNEL.addAttestationProtocol(AUTH_PROTOCOL);
// TRANSMISSION_CHANNEL.start();
// 运行噪声线程
NoiseThread noise = new NoiseThread(NOISE_PERIOD, CHANNEL, NOISE_PORT,
new CANMessage(0x40, new byte[]{0x11, 0x22, 0x33}));
noise.start();
// 结束通道
try {
System.in.read();
//TRANSMISSION_CHANNEL.end();
noise.end();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package USBtin;
/**
* CAN消息类.
*
* @author Thomas Fischl
*/
public class CANMessage {
/** CAN消息 ID */
protected int id;
private int DLC;
/** CAN消息的数据负载 */
protected byte[] data;
/** 扩展帧标记 */
protected boolean extended;
/** 传输帧标记 */
protected boolean rtr;
/**
* 获取CAN消息ID
*
* @return CAN消息ID
*/
public int getId() {
return id;
}
public int getDLC() { return DLC; }
/**
* Set c
*
* @param id CAN消息ID
*/
public void setId(int id) {
if (id > (0x1fffffff))
id = 0x1fffffff;
if (id > 0x7ff)
extended = true;
this.id = id;
}
public void setDLC(int DLC) {
if (DLC >= 0 && DLC < 16) {
this.DLC = DLC;
}
}
/**
* Get CAN message payload data
*
* @return CAN message payload data
*/
public byte[] getData() {
return data;
}
/**
* Set CAN消息数据负载
*
* @param data CAN消息的字节数组
*/
public void setData(byte[] data) {
this.data = data;
}
/**
* 判断是否扩展了CAN消息id
*
* @return true if extended CAN message
*/
public boolean isExtended() {
return extended;
}
/**
* 判断是否为传输帧
*
* @return true if RTR message
*/
public boolean isRtr() {
return rtr;
}
/**
* 用给定ID和数据创建CAN消息
* 根据ID设置扩展标志
*
* @param id 消息ID
* @param data 数据负载
*/
public CANMessage(int id, byte[] data) {
this.data = data;
setDLC(data.length);
this.extended = false;
setId(id);
this.rtr = false;
}
/**
* 用给定消息属性创建CAN消息
*
* @param id CANID
* @param data 数据域
* @param extended 扩展帧标志
* @param rtr 传输帧标志
*/
public CANMessage(int id, byte[] data, boolean extended, boolean rtr) {
setId(id);
this.data = data;
this.extended = extended;
this.rtr = rtr;
}
/**
* 用给定消息字符串创建CAN消息
* 解析消息字符串。如果出现错误,相应的值将被设置为零。
*
* 消息字符串实例:
* t1230 id: 123h dlc: 0 data: --
* t00121122 id: 001h dlc: 2 data: 11 22
* T12345678197 id: 12345678h dlc: 1 data: 97
* r0037 id: 003h dlc: 7 RTR
*
* @param msg 消息字符串
*/
public CANMessage(String msg) {
this.rtr = false;
int index = 1;
char type;
if (msg.length() > 0) type = msg.charAt(0);
else type = 't';
switch (type) {
case 'r':
this.rtr = true;
default:
case 't':
try {
this.id = Integer.parseInt(msg.substring(index, index + 3), 16);
} catch (StringIndexOutOfBoundsException e) {
this.id = 0;
} catch (NumberFormatException e) {
this.id = 0;
}
this.extended = false;
index += 3;
break;
case 'R':
this.rtr = true;
case 'T':
try {
this.id = Integer.parseInt(msg.substring(index, index + 8), 16);
} catch (StringIndexOutOfBoundsException e) {
this.id = 0;
} catch (NumberFormatException e) {
this.id = 0;
}
this.extended = true;
index += 8;
break;
}
int length;
try {
length = Integer.parseInt(msg.substring(index, index + 1), 16);
this.DLC=length;
if (length > 8) {
length = 8;
}
} catch (StringIndexOutOfBoundsException e) {
length = 0;
} catch (NumberFormatException e) {
length = 0;
}
index += 1;
this.data = new byte[length];
if (!this.rtr) {
for (int i = 0; i < length; i++) {
try {
this.data[i] = (byte) Integer.parseInt(msg.substring(index, index + 2), 16);
} catch (StringIndexOutOfBoundsException e) {
this.data[i] = 0;
} catch (NumberFormatException e) {
this.data[i] = 0;
}
index += 2;
}
}
}
/**
* 将CAN消息对象转换为字符串表示形式
*
* @return CAN message as string representation
*/
@Override
public String toString() {
String s;
if (this.extended) { // 如果是扩展帧
if (this.rtr) s = "R"; // 如果是远程传输请求帧
else s = "T"; // 如果是数据帧
s = s + String.format("%08x", this.id); // 添加帧ID
} else { // 如果是标准帧
if (this.rtr) s = "r"; // 如果是远程传输请求帧
else s = "t"; // 如果是数据帧
s = s + String.format("%03x", this.id); // 添加帧ID
}
s = s + String.format("%01x", this.DLC); // 添加数据长度码
if (!this.rtr) { // 如果不是远程传输请求帧
for (int i = 0; i < this.data.length; i++) {
s = s + String.format("%02x", this.data[i]); // 添加数据字节
}
}
return s; // 返回字符串表示形式
}
}
s = s + String.format("%03x", this.id);
什么是意思?
这行代码的作用是将
this.id
的值格式化为一个3位的十六进制字符串,然后将其添加到字符串s
的末尾。具体来说:
%03x
是一个格式化字符串,表示将一个整数格式化为3位的十六进制字符串。%x
表示以十六进制格式输出,03
表示输出的最小宽度为3位,不足3位时在前面补0。this.id
是一个整数变量,它的值会被格式化为3位的十六进制字符串。String.format
方法将this.id
的值按照指定格式转换为字符串,然后将其添加到字符串s
的末尾。因此,这行代码的作用是将
this.id
的值以3位的十六进制格式添加到字符串s
的末尾。
package noise;
import USBtin.CANMessage;
import USBtin.USBtin;
import USBtin.USBtinException;
/**
* 表示一个噪声线程,用于向CAN总线发送噪声消息
*/
public class NoiseThread extends Thread {
private long PERIOD; // 噪声发送周期
private int CHANNEL; // CAN通道号
private String port; // USBtin串口
private CANMessage message; // 要发送的CAN消息
private Noise_node noise; // 噪声节点
/**
* 构造函数,初始化噪声线程
* @param period 噪声发送周期
* @param channel CAN通道号
* @param port USBtin串口
* @param mess 要发送的CAN消息
*/
public NoiseThread(long period, int channel, String port, CANMessage mess) {
this.PERIOD = period;
this.CHANNEL = channel;
this.port = port;
this.message = mess;
}
/**
* 运行噪声线程
*/
public void run() {
Noise_node node = new Noise_node(this.PERIOD); // 创建噪声节点
this.noise = node;
try {
node.connect(this.port); // 连接USBtin串口
node.openCANChannel(this.CHANNEL, USBtin.OpenMode.ACTIVE); // 打开CAN通道
} catch (USBtinException e) {
e.printStackTrace();
}
node.start(this.message); // 开始发送噪声消息
}
/**
* 结束噪声线程
*/
public void end() {
this.noise.stop(); // 停止发送噪声消息
try {
this.noise.closeCANChannel(); // 关闭CAN通道
this.noise.disconnect(); // 断开USBtin连接
} catch (USBtinException e) {
e.printStackTrace();
}
}
}
package USBtin;
/**
* 表示一个CAN过滤器链。
*/
public class FilterChain {
/** Filter mask */
FilterMask mask;
/** Filters */
FilterValue[] filters;
/**
* 用一个 mask 和多个filters创建一个过滤器链.
*
* @param mask Mask
* @param filters Filters
*/
public FilterChain(FilterMask mask, FilterValue[] filters) {
this.mask = mask;
this.filters = filters;
}
/**
* 获取过滤器链的 mask
*
* @return Mask
*/
public FilterMask getMask() {
return mask;
}
/**
* 获取过滤器链的 filters
*
* @return Filters
*/
public FilterValue[] getFilters() {
return filters;
}
}
package transmission_channel.DLC_channel;
import USBtin.CANMessage;
import USBtin.USBtin;
import USBtin.USBtinException;
import attestation.AttestationProtocol;
import error_detection.ErrorCorrectionCode;
import host_communication.CANSender;
import util.CANAuthMessage;
import java.util.List;
import static java.lang.System.err;
/**
* 表示一个数据长度编码(DLC)节点,用于处理CAN消息的数据长度编码
*/
public class DLC_Node {
private long PERIOD; // 周期
static final public int SILENCE_BIT_DLC=8; // 静默位数据长度
static final public int DLC_0 = 9; // 数据长度编码0
static final public int DLC_1 = 10; // 数据长度编码1
static final public int DLC_00 = 11; // 数据长度编码00
static final public int DLC_01 = 12; // 数据长度编码01
static final public int DLC_10 = 13; // 数据长度编码10
static final public int DLC_11 = 14; // 数据长度编码11
private CANAuthMessage AUTH_MESSAGE; // 认证消息
private ErrorCorrectionCode corrector; // 纠错码
private AttestationProtocol protocol; // 认证协议
private boolean running = true; // 是否在运行
private CANSender sender; // CAN发送器
private int indexInAuthMessage = 0; // 认证消息中的索引
/**
* 构造函数,初始化DLC节点
* @param period 周期
* @param sender CAN发送器
*/
public DLC_Node(long period, CANSender sender) {
PERIOD = period;
this.sender = sender;
}
/**
* 启动DLC节点
*/
public void start() {
if (this.protocol != null) {
this.AUTH_MESSAGE = this.protocol.getAttestationMessage(); // 获取认证消息
}
else { return; }
// 错误校正
if (this.corrector != null) {
this.AUTH_MESSAGE.setCorrectionCode(this.corrector); // 设置纠错码
}
while (running) {
try {
Thread.sleep(PERIOD); // 等待周期
CANMessage message = this.sender.getMessageToSend(); // 获取要发送的消息
message.setDLC(getDLCToUse(message)); // 设置消息的数据长度编码
this.sender.send(message); // 发送消息
}
catch (InterruptedException | USBtinException ex) {
err.println(ex);
}
}
}
/**
* 获取要使用的数据长度编码
* @param message CAN消息
* @return 数据长度编码
*/
private int getDLCToUse(CANMessage message) {
if (message.getData().length < 8) {
return message.getData().length;
}
List<Byte> auth_bytes = this.AUTH_MESSAGE.toByteArray();
// 环绕
if (indexInAuthMessage > auth_bytes.size()+1) {
indexInAuthMessage = 0;
}
// 静默位
if (indexInAuthMessage == 0 || indexInAuthMessage == auth_bytes.size()+1) {
indexInAuthMessage += 1;
return SILENCE_BIT_DLC;
}
// 认证位
if (indexInAuthMessage == auth_bytes.size()) {
if (auth_bytes.get(indexInAuthMessage-1) == 0) {
indexInAuthMessage += 1;
return DLC_0;
}
indexInAuthMessage += 1;
return DLC_1;
}
if (auth_bytes.get(indexInAuthMessage-1) == 0) {
if (auth_bytes.get(indexInAuthMessage) == 0) {
indexInAuthMessage += 2;
return DLC_00;
}
indexInAuthMessage += 2;
return DLC_01;
}
if (auth_bytes.get(indexInAuthMessage) == 0) {
indexInAuthMessage += 2;
return DLC_10;
}
indexInAuthMessage += 2;
return DLC_11;
}
/**
* 设置纠错码
* @param corrector 纠错码
*/
public void setCorrector(ErrorCorrectionCode corrector) {
this.corrector = corrector;
}
/**
* 设置认证协议
* @param protocol 认证协议
*/
public void setAttestation(AttestationProtocol protocol) {
this.protocol = protocol;
}
/**
* 停止DLC节点
*/
public void leave() {
this.running = false;
}
}
package transmission_channel.IAT_channel;
import attestation.AttestationProtocol;
import USBtin.CANMessage;
import USBtin.USBtin;
import USBtin.USBtinException;
import error_detection.ErrorCorrectionCode;
import host_communication.CANSender;
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_Node {
private long PERIOD; // 周期
private int WINDOW_LENGTH; // 窗口长度
private CANAuthMessage AUTH_MESSAGE; // 认证消息
private int placeInWindow = 0; // 窗口中的位置
private int indexInAuthMessage = 0; // 认证消息中的索引
private boolean running = true; // 是否在运行
private ErrorCorrectionCode corrector; // 纠错码
private AttestationProtocol protocol; // 认证协议
private int silence_start; // 静默开始
private int silence_end; // 静默结束
private IATBitConverter converter; // IAT位转换器
private long delta; // 增量
private CANSender host; // CAN发送器
// 统计
private long total_sent = 0; // 总发送数
private FileWriter ITTwriter; // ITT写入器
private long nperiod; // N周期
private long channel; // 通道
// 静默开始/结束
private int silence_counter = 0; // 静默计数器
private boolean starting = false; // 是否开始
private boolean stopping = false; // 是否结束
// 构造函数,初始化IAT节点
public IAT_Node(long period, int windowLength, int silence_start, int silence_end, IATBitConverter converter,
long delta, long channel, long nperiod, CANSender host) {
PERIOD = period;
WINDOW_LENGTH = windowLength;
this.silence_start = silence_start * WINDOW_LENGTH;
this.silence_end = silence_end * WINDOW_LENGTH;
this.converter = converter;
this.delta = delta;
this.channel = channel;
this.nperiod = nperiod;
this.host = host;
}
// 启动IAT节点
public void start() {
if (this.protocol != null) {
this.AUTH_MESSAGE = this.protocol.getAttestationMessage(); // 获取认证消息
}
else { return; }
// 错误校正
if (this.corrector != null) {
this.AUTH_MESSAGE.setCorrectionCode(this.corrector); // 设置纠错码
}
// 统计
try {
new File("timings").mkdir(); // 创建目录
this.ITTwriter = new FileWriter("timings/ITT_" + "P" + PERIOD + "_D" + delta + "_C" +
channel + "_N" + nperiod + ".csv"); // 创建ITT写入器
} catch (IOException e) {
e.printStackTrace();
}
while (running) {
try {
long timeToSleep = this.getTimeToSleep()-3; // 获取睡眠时间
// 保存ITT
try {
this.ITTwriter.append(timeToSleep + ";" + System.currentTimeMillis() + "\n"); // 写入ITT
} catch (IOException e) {
e.printStackTrace();
}
Thread.sleep(timeToSleep); // 线程睡眠
this.host.sendMessage(this.host.getMessageToSend()); // 发送消息
}
catch (InterruptedException ex) {
System.err.println(ex);
}
}
}
// 获取下一次休眠时间
public long getTimeToSleep() {
List<Byte> auth_bytes = this.AUTH_MESSAGE.toByteArray(); // 将认证消息转换为字节列表
// 开始静默位
if (indexInAuthMessage == 0) {
if (!starting) {
silence_counter++; // 静默计数增加
starting = true; // 开始标志
placeInWindow = WINDOW_LENGTH; // 窗口位置
return PERIOD; // 返回周期
}
if (silence_counter < silence_start) {
starting = true; // 开始标志
silence_counter++; // 静默计数增加
return PERIOD; // 返回周期
}
}
starting = false;
// 结束静默位
if (indexInAuthMessage >= auth_bytes.size()) {
if (stopping) {
if (silence_counter < silence_end) {
silence_counter++; // 静默计数增加
return PERIOD; // 返回周期
}
else {
placeInWindow = WINDOW_LENGTH; // 窗口位置
silence_counter = 0; // 静默计数重置
}
}
}
// 环绕
if (placeInWindow >= WINDOW_LENGTH) {
if (indexInAuthMessage >= auth_bytes.size()) {
if (!stopping) {
stopping = true; // 结束标志
silence_counter = 1; // 静默计数重置
return PERIOD; // 返回周期
}
else {
stopping = false; // 结束标志
silence_counter = 0; // 静默计数重置
this.total_sent++; // 总发送数增加
}
}
if (!starting) {
if (indexInAuthMessage == 0) { indexInAuthMessage = 1; }
else { indexInAuthMessage += this.converter.getBitsEncoded(); }
}
placeInWindow = 0; // 窗口位置重置
}
if (indexInAuthMessage > auth_bytes.size()) {
indexInAuthMessage = 0; // 索引重置
silence_counter = 1; // 静默计数重置
return PERIOD; // 返回周期
}
placeInWindow += 1; // 窗口位置增加
// 位编码
List<Byte> restingBytes;
try {
restingBytes = auth_bytes.subList(indexInAuthMessage-1,
indexInAuthMessage-1+this.converter.getBitsEncoded());
} catch (IndexOutOfBoundsException ex) {
restingBytes = auth_bytes.subList(indexInAuthMessage-1, auth_bytes.size());
}
return this.converter.convertToIAT(restingBytes); // 转换为IAT
}
// 离开IAT节点
public void leave() {
running = false; // 停止运行
System.out.println("Total sent: " + this.total_sent); // 输出总发送数
try {
this.ITTwriter.close(); // 关闭ITT写入器
}
catch (IOException ex) {
ex.printStackTrace();
}
}
// 设置错误纠正码
public void setCorrector(ErrorCorrectionCode corrector) {
this.corrector = corrector; // 设置纠错码
}
// 设置认证协议
public void setProtocol(AttestationProtocol prot) {
this.protocol = prot; // 设置认证协议
}
}