精选文章 java读取modbus(串口,DTU(WIFI )也可 DTU(gprs)也可)协议数据 解释详细 踩坑完整 拿来就可以用的demo(下)

java读取modbus(串口,DTU(WIFI )也可 DTU(gprs)也可)协议数据 解释详细 踩坑完整 拿来就可以用的demo(下)

作者:请叫我书生 时间: 2020-08-05 09:54:18
请叫我书生 2020-08-05 09:54:18

福兮祸所伏, 祸兮福所倚。(现在发生在你身上的都是好事,福祸相伴)  

这些源码应该都可以看的懂  我就不解释了。

public void Connect(String comPort) throws Exception {
        // 类似于串口连接(个人理解)
        this.portIdentifier = CommPortIdentifier.getPortIdentifier(comPort);
        if (this.portIdentifier.isCurrentlyOwned()) {
            System.out.println("Error: Port is currently in use");
        } else {
            int timeout = 2000;
            // 串口对象
            CommPort commPort = this.portIdentifier.open(this.getClass().getName(), timeout);
            if (commPort instanceof SerialPort) {
                this.serialPort = (SerialPort)commPort;
                this.serialPort.setSerialPortParams(9600, 8, 1, 2);
           
                this.serialPort.enableReceiveTimeout(1000);
                this.serialPort.disableReceiveThreshold();
                this.in = this.serialPort.getInputStream();
                this.out = this.serialPort.getOutputStream();
                this.serialflag = true;
            } else {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }

    }

那咱们就运行  ,结果。。。。。。。。。。。

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)1

少了个处理串口的依赖包 (我用的是RXTX  2.2,当时找的时候  网上那些都是粘贴,估计怎么搞得  他们都不知道   搞得我晕头转向的   真的是误人子弟。上解决方法)

下载RXTX2.2(包括各个系统版本)

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)2

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)3

 将RXTXcomm.jar以上面相同的方式 引入到你的项目 

 我的是64的  我直接说64的  32位的会有所不同  留给你们自己去探索吧

  1. 找到RXTXcomm.jar   复制你的java_home下jre\lib和jre\lib\ext
  2. 点击进入win64  复制rxtxSerial.dll 到\jre\bin

 那接下来是不是可以见证奇迹了呢     还要再等下  

  1. 如果单单是串口读取的话   我们现在的代码就可以完全操作了
  2. 如果说是wifi (就一ip地址+端口,局域网, 不要想的那么复杂)  如果说  我搞个虚拟串口的话  是不是 我直接操作虚拟串口就可以了呢(我直接给串口发数据,然后直接使用咱们的上面代码就可以搞定了吧。)
  3. 如果说是GPRS呢?  wifi我可以处理   你外网我当然可以处理  同理 在云服务器上嫁接个虚拟串口  完全ok。
  4. 补充一点:wifi和GPRS都可以理解为TCP协议。

先给你们个虚拟串口工具的直通车

V-COM虚拟串口工具

 这个工具的话  在使用中  如果说  你删除串口的话  还提示串口被占用的话     其他的不要多想     直接去服务里面找到v-com-Service     枪杀了它  就OK了   或者重启当前服务也可以  

补充:  其他人都不知道   这可是我自己研究出来的。啧啧

不多比比了  看效果 

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)4

 解释下 咱们发送命令是怎么产生

02  03  00 01  00  04  15  FA

02对应的是咱们java的

modbusClient.setUnitIdentifier((byte)1);也就是DTU的id

03 是功能码 对应咱们的

modbusClient.ReadHoldingRegisters  (只要是这个方法的就是03)

00 01  对应的是咱们的

 modbusClient.ReadHoldingRegisters(1, 4)的第一个参数   也就是寄存器的起始地址

 00 04 对应的是咱们的

 modbusClient.ReadHoldingRegisters(1, 4)的第二个参数   也就是读取寄存器的长度   物联网的寄存器也就是软件的内存地址  可以这样理解。 

15 FA  对CRC校验码   是根据  02 03 00 01 00 04 这些数据 生成的    就类似于微信官方接口的凭证

DTU返回的数据(02 03 08 00 00 07 79 00 01 80 d3  77 73)解释:

02 03 不解释了   

08代表的是数据是后面的8个字节    00 00 07 79 00 01 80 d3      4个对应一个值   这些都是16进制  需要转化(放心,会把我写工具类给你   你拿去用就好。)

77 73 CRC校验码

 

最后 把写的工具类给你们吧    针对于modbus协议  基本上都使用的

public static String getAlValue(int al1High, int al1Low) {
        int highAl1 = 0;
        int lowAl1 = 0;
        if (al1High >= 0) {
            highAl1 = al1High * 65536;
            System.out.println("highAl1的值为:" + highAl1);
        } else {
            highAl1 = Integer.valueOf(getAlHex(al1High));
            System.out.println("highAl1的值为:" + highAl1);
        }

        if (al1Low >= 0) {
            lowAl1 = al1Low;
            System.out.println("lowAl1的值为:" + lowAl1);
        } else {
            lowAl1 = Integer.valueOf(getAlHex(al1Low));
            System.out.println("lowAl1的值为:" + lowAl1);
        }
        return String.valueOf(highAl1 + lowAl1);
    }
private static String getAlHex(int lowOrder) {

        // 去掉符号位
        lowOrder =  Math.abs(lowOrder);

        // 转为2进制
        String al1Str = Integer.toBinaryString(lowOrder);

        String zorn = "";
        if (al1Str.length() < 16) {
            for (int i = 0; i< 16 - al1Str.length(); i++) {
                zorn += "0";
            }
        }
        al1Str = zorn + al1Str;

        /**
         * * 转为数组  遍历循环  取补码
        */
        // 转为数组
        String[] alArrStr = al1Str.split("");
        // 先转反码  再转为补码
        String str = getComplement(alArrStr);
        // 转为10进制
        int bitStr = Integer.parseInt(str, 2);
        // 返回16进制
        return String.valueOf(bitStr);
    }
private static String getComplement (String[] alArrStr) {
        StringBuilder str = new StringBuilder();

        // 遍历  获取反码
        for (int i = 0; i < alArrStr.length; i++) {
            if (MeterConstant.BIT_ZERO_FLAG.equals(alArrStr[i])) {
                str.append(MeterConstant.BIT_ONE_FLAG);
            } else {
                str.append(MeterConstant.BIT_ZERO_FLAG);
            }
        }
        String[] code = str.toString().split("");
        Boolean isCarry = false;
        // 再去补码
        for (int i = code.length - 1; i < code.length; i--) {
            if (MeterConstant.BIT_ZERO_FLAG.equals(code[i])) {
                if (isCarry) {
                    code[i] = MeterConstant.BIT_ONE_FLAG;
                    isCarry = false;
                }
                break;
            } else {
                code[i] = MeterConstant.BIT_ZERO_FLAG;
                isCarry = true;
            }
        }
        return org.apache.commons.lang3.StringUtils.join(code);
    }

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)5

这是我项目中的数据读取效果。好好看下  应该可以看懂

工具类  写的有点乱,也有点low     也懒得改了  但是绝对好用。就到这里吧   如果感觉有用的话 就打赏下小弟吧。

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)6

java读取modbus(串口,DTU(WIFI  )也可  DTU(gprs)也可)协议数据 解释详细  踩坑完整  拿来就可以用的demo(下)7

 

相关文章

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:阿里2020/8/3笔试题(二)

下一篇:存储直通、PCI直通和SR-IOV

您可能感兴趣

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。