Java实现 Modbus RTU Int类型数据解析(4个字节), 默认高位在前、低位在后

部分代码片段: 


import com.keydak.collector.core.response.LengthStrategy;
import com.thoughtworks.xstream.annotations.XStreamAlias;

import java.math.BigDecimal;
import java.util.Optional;

/**
 * 从响应数据 开始地址取4个长度转为Int类型, 默认高位在前、低位在后
 */
@XStreamAlias("Byte4ToIntSensorDefine")
public class Byte4ToIntSensorDefine extends SensorDefine {

    /**
     * 是否是小端法 默认采用大端法(false)
     **/
    private boolean smallHead = false;
    /**
     * 控制高低位 默认高位在前低位在后(false)
     **/
    private boolean reverse = false;
    /**
     * 用于获取2个字节数据,默认取高位数据(false)
     **/
    private boolean towBytes = false;
    /**
     * 是否选择 2个字节解析 默认4个字节解析(fasle)
     **/
    private boolean half = false;

    public Byte4ToIntSensorDefine(String commandName, String chName, String enName, int registerIndex, int scale, double divider) {
        super(commandName, chName, enName, registerIndex, scale, divider);
    }

    @Override
    public BigDecimal getData(IResponseContext<LengthStrategy, byte[]> context) throws Exception {
        byte[] data = {74, 22, 0, 0};
//      byte[] data = context.getData(commandName, getStrategy());
        return Optional.ofNullable(data).map(byteArray -> {
            int actualValue = half ? bytes2IntHalf(byteArray) :
                    (smallHead ? bytes2IntLittle(byteArray) : bytes2IntBig(byteArray));
            BigDecimal value = new BigDecimal(actualValue).divide(BigDecimal.valueOf(divider), scale, BigDecimal.ROUND_HALF_UP);
            return value;
        }).orElse(null);
    }


    @Override
    protected LengthStrategy getStrategy() {
        return new LengthStrategy(registerIndex, 4);
    }

    /**
     * byte数组到int的转换(小端)
     *
     * @param bytes
     * @return
     */
    public int bytes2IntLittle(byte[] bytes) {
        byte[] result = null;
        if (reverse) {
            result = new byte[bytes.length];
            result[0] = bytes[2];
            result[1] = bytes[3];
            result[2] = bytes[0];
            result[3] = bytes[1];
        } else {
            result = bytes;
        }

        int int1 = result[0] & 0xff;
        int int2 = (result[1] & 0xff) << 8;
        int int3 = (result[2] & 0xff) << 16;
        int int4 = (result[3] & 0xff) << 24;
        return int1 | int2 | int3 | int4;
    }

    /**
     * byte数组到int的转换(大端)
     *
     * @param bytes
     * @return
     */
    public int bytes2IntBig(byte[] bytes) {
        byte[] result = null;
        if (reverse) {
            result = new byte[bytes.length];
            result[0] = bytes[2];
            result[1] = bytes[3];
            result[2] = bytes[0];
            result[3] = bytes[1];
        } else {
            result = bytes;
        }
        int int1 = result[3] & 0xff;
        int int2 = (result[2] & 0xff) << 8;
        int int3 = (result[1] & 0xff) << 16;
        int int4 = (result[0] & 0xff) << 24;
        return int1 | int2 | int3 | int4;
    }

    /**
     * 选择解析高位数据或者低位数据(2个字节)
     **/
    public int bytes2IntHalf(byte[] bytes) {
        byte[] result = null;
        if (towBytes) {
            //只取低位两个字节数据
            result = new byte[2];
            result[0] = bytes[2];
            result[1] = bytes[3];
        } else {
            //只取高位两个字节数据
            result = new byte[2];
            result[0] = bytes[0];
            result[1] = bytes[1];
        }

        StringBuilder hexString = new StringBuilder();
        for (byte b : result) {
            hexString.append(String.format("%02X", b));
        }
        String hex = hexString.toString();
        int decimal = Integer.parseInt(hex, 16);
        return decimal;

    }


}

采集命令 :

    <ModbusRequest>
        <name>Jy500-SJ_AI_A5</name>
        <timeout>1000</timeout>
        <commandType>3</commandType>
        <description>ABC相电能</description>
        <length>12</length>
        <registerNumber>536</registerNumber>
    </ModbusRequest>

响应命令数据解析:

  <Byte4ToIntSensorDefine>
    <chName>第一路A相电能</chName>
    <enName>Jy500-SJ_First_A_Phase_Power_Energy</enName>
    <registerIndex>536</registerIndex>
    <scale>1</scale>
    <commandName>Jy500-SJ_AI_A5</commandName>
    <divider>10</divider>
    <reverse>false</reverse>
    <half>true</half>
  </Byte4ToIntSensorDefine>

例子:
[15:29:38.156]发→◇01 03 02 1A 00 02 E4 74 □
[15:29:38.161]收←◆01 03 04 4A 16 00 00 0D EF 

数据:

十六进制:4A 16 00 00  转十进制:74 22 00 00       

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值