【论文代码】基于隐蔽带宽的汽车控制网路鲁棒认证-到达时间间隔通道的Java实现(二)

文章目录

  • 五、TransmissionThread 抽象类
    • 5.1 IAT_thread类
    • 5.2 DLC_Thread
  • 六、AttestationProtocol 接口
    • 6.1 HardCodedAttestation
  • 七、FilterMash 类
    • 7.1 FilterValue
  • 八、其他类
    • 8.1 CANAuthMessage
    • 8.2 USBtinException
    • 8.3 USBtinLibDemo
    • 8.4 CANMessage
    • 8.5 NoiseThread
    • 8.6 FilterChain
    • 8.7 DLC_Node
    • 8.8 IAT_Node

跳转上一篇: 【论文代码】基于隐蔽带宽的汽车控制网路鲁棒认证-到达时间间隔通道的Java实现(一)

此篇文章是对原有代码的注释进行翻译,尝试对其架构和实现方式进行理解。

项目结构

在这里插入图片描述

Java实现代码

如图UML类图:
在这里插入图片描述
从图中明显可见,其代码组织方式,各个代码文件的继承和实现的关系。

以下内容围绕UML类图,分别进行阐述。

五、TransmissionThread 抽象类

/*
 * 这个抽象类定义了传输线程的基本结构,用于处理通信和校验相关的功能。
 */
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; }

}

5.1 IAT_thread类

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();
    }
}

5.2 DLC_Thread

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();
    }
}

六、AttestationProtocol 接口

/*
 * 这个接口定义了认证协议的基本功能,用于生成认证消息和检查认证消息的有效性。
 */
package attestation;

import util.CANAuthMessage;
import USBtin.USBtin;

public interface AttestationProtocol {
    // 获取认证消息
    CANAuthMessage getAttestationMessage();

    // 检查认证消息
    boolean checkAttestationMessage(CANAuthMessage message);
}

6.1 HardCodedAttestation

/*
 * 这个类实现了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());
    }
}

七、FilterMash 类

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;
    }

}

7.1 FilterValue

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);
    }

}

八、其他类

8.1 CANAuthMessage

/*
 * 这个类表示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;
    }

}

8.2 USBtinException

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);
    }
}

8.3 USBtinLibDemo

这个是主函数位置。

/*
 * 演示如何使用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();
        }
    }

}

8.4 CANMessage

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的末尾。

8.5 NoiseThread

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();
        }
    }
}

8.6 FilterChain

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;
    }

}

8.7 DLC_Node

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;
    }
}

8.8 IAT_Node

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; // 设置认证协议
    }

}

你可能感兴趣的:(CAN总线,汽车,java,开发语言)