设备上位机串口通讯调试程序 通过串口发送控制台命令 将串口消息发送到消息队列

具体功能:

  •  1、监听串口,获取设备返回报文打印到控制台,并上传到平台mq。
    
  •  2、监听控制台,获取请求报文通过串口发送设备。
    

执行方式

  • 打包jar后执行
  • 命令: java -jar ***.jar 串口名 波特率
  • 示例: java -jar App.jar COM3 115200

maven依赖

<dependency>
  <groupId>com.neuronrobotics</groupId>
    <artifactId>nrjavaserial</artifactId>
    <version>5.1.1</version>
</dependency>

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>3.4.1</version>
</dependency>

程序入口RxtxNRSerialPortApp

public class RxtxNRSerialPortApp {
    /**
     * @param args args[0] 串口名称 args[1] 波特率
     */
    public static void main(String[] args) {

        for (String s : NRSerialPort.getAvailableSerialPorts()) {
            System.out.println("Availible port: " + s);
        }

        if (args.length < 1 || args[0] == null || "".equals(args[0])) {
            System.out.println("请输入串口名称!");
            System.exit(-101);
        }
        String port = args[0];

        int baudRate = 115200;


        if (args.length >= 2 && args[1] != null && !"".equals(args[1])) {
            String baudRateStr = args[1];
            Pattern pattern = Pattern.compile("[0-9]*");
            Matcher isNum = pattern.matcher(baudRateStr);
            if (!isNum.matches()) {
                System.out.println("波特率应为整数!");
                System.exit(-102);
            }
            baudRate = Integer.parseInt(baudRateStr);
            if (baudRate % 1200 != 0) {
                System.out.println("波特率应为1200整倍数!");
                System.exit(-102);
            }
        }

        KafkaProducer producer = null;
        try {
            producer = getProducer();
        } catch (Exception e) {
            System.out.println("MQ连接失败!");
            e.printStackTrace();
            System.exit(-202);
        }

        if (producer == null) {
            System.out.println("MQ连接失败!");
            System.exit(-202);
        }
        System.out.println("MQ连接成功....");
        RxtxClient rxtxClient = new RxtxClient(port, baudRate, producer);
        //1、监听串口,获取设备返回报文打印到控制台,并上传到平台mq。
        //连接串口
        try {
            rxtxClient.start();
        } catch (Exception e) {
            System.out.println("串口连接失败!");
            e.printStackTrace();

            rxtxClient.stop();
            System.exit(-201);
        }

        System.out.println("串口"+port+"连接成功....");

        rxtxClient.sendMsg("0000");//握手指令
        try {
            Thread.sleep(1024);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //打印设备返回ID
        System.out.println(rxtxClient.getId() + "设备连接成功");


        // 2、监听控制台,获取请求报文通过串口发送设备。
        System.out.print("请输入发送设备" + rxtxClient.getId() + "命令报文:");//提示输入
        Scanner scanner = new Scanner(System.in);//控制台输入控件
        while (scanner.hasNextLine()) {
            String command = scanner.nextLine();  //nextLine()接收字符串类型的输入
            if (command == null || command.isEmpty()) continue;
            if ("0".equals(command)) {
                rxtxClient.stop();
                System.exit(0);
            }
            rxtxClient.sendMsg(command);
//System.out.print("请输入发送设备" + rxtxClient.getSnId() + "命令报文:");//提示输入
        }
    }


    private static KafkaProducer getProducer() throws Exception {
        Properties properties = new Properties();
        //	1.配置生产者启动的关键属性参数
        //	1.1	BOOTSTRAP_SERVERS_CONFIG:连接kafka集群的服务列表,如果有多个,使用"逗号"进行分隔
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092");
        //	1.2	CLIENT_ID_CONFIG:这个属性的目的是标记kafkaclient的ID
        properties.put(ProducerConfig.CLIENT_ID_CONFIG, "reflectivity-producer");
        //	1.3 KEY_SERIALIZER_CLASS_CONFIG VALUE_SERIALIZER_CLASS_CONFIG
        //	Q: 对 kafka的 key 和 value 做序列化,为什么需要序列化?
        //	A: 因为KAFKA Broker 在接收消息的时候,必须要以二进制的方式接收,所以必须要对KEY和VALUE进行序列化
        //	字符串序列化类:org.apache.kafka.common.serialization.StringSerializer
        //	KEY: 是kafka用于做消息投递计算具体投递到对应的主题的哪一个partition而需要的
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        //	VALUE: 实际发送消息的内容
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        //	2.创建kafka生产者对象 传递properties属性参数集合
        KafkaProducer<String, String> producer = new KafkaProducer<>(properties);

        return producer;
    }
}

串口连接程序


public class RxtxClient {
    private NRSerialPort serialPort;

    private String portName;
    private Integer baudRate;
    private EquipmentMsgHandler handler;
    private KafkaProducer producer;

    public RxtxClient(String portName, Integer baudRate, KafkaProducer producer) {
        this.portName = portName;
        this.baudRate = baudRate;
        this.producer = producer;
    }

    public void start() {
        System.out.println("开始启动串口通信:\t" + portName + "\t" + baudRate);
        //串口使用阻塞io
        try {
            serialPort = new NRSerialPort(portName, baudRate);
            boolean isConnected = serialPort.connect();
            if (!isConnected) {
                System.out.println("串口连接失败!");
                System.exit(-201);
            }

            this.handler = new EquipmentMsgHandler(serialPort.getInputStream(), producer);
            this.handler.start();
        } catch (Exception e) {
            System.out.println("串口连接失败!");
            e.printStackTrace();
            System.exit(-201);
        }


    }

    public void stop() {
        serialPort.disconnect();
        producer.close();
    }

    // 发送消息
    public void sendMsg(String msg) {
        try (DataOutputStream outs = new DataOutputStream(serialPort.getOutputStream())) {
            byte[] bytes = new byte[]{};
            try {
                bytes = hexString2Bytes(msg.trim());
            } catch (Exception e) {
                System.out.println("请输入16进制命令!");
            }

            outs.write(bytes);
            outs.flush();
        } catch (IOException e) {
            e.printStackTrace();
            serialPort.disconnect();
        }
    }

    public static byte[] hexString2Bytes(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (byte) Integer
                    .valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }

    public String getId() {
        return handler.getId();
    }
}

消息处理模块


public class EquipmentMsgHandler extends Thread {
    public static final String TOPIC_NAME = "REFLECTIVITY";
    public static String HEXE = "0123456789ABCDEF";

    private String id;

    private InputStream inputStream;
    private KafkaProducer producer;

    public EquipmentMsgHandler(InputStream inputStream, KafkaProducer producer) {
        this.inputStream = inputStream;
        this.producer = producer;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public void run() {

        //1、监听串口,获取设备返回报文打印到控制台,并上传到平台mq。

        try (DataInputStream ins = new DataInputStream(this.inputStream)) {

            StringBuffer lsb_tmp = new StringBuffer();
            byte[] tmpByte;

            //while(ins.available()==0 && !Thread.interrupted());// wait for a byte
            while (!Thread.interrupted()) {// read all bytes
                if (ins.available() > 0) {
                    tmpByte = new byte[ins.available()];
                    ins.read(tmpByte);
                    for (int i = 0; i < tmpByte.length; i++) {
                        lsb_tmp.append(HEXE.charAt((tmpByte[i] & 0xF0) >> 4))
                                .append(HEXE.charAt((tmpByte[i] & 0x0F)));
                    }
                    String msg = lsb_tmp.toString();
                    lsb_tmp.setLength(0);
                    System.out.println("确认设备报文:" + msg);
                    if ("00".equals(msg.substring(8, 10))) {
                        //查询sn号设备
                        this.id = msg.substring(10, 18);
                    }
                    producer.send(new ProducerRecord<String, String>(TOPIC_NAME,msg));

                    System.out.print("请输入发送设备" + getId() + "命令报文:");
                    //提示输入
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值