java 上位机编程常用的 BCD 码、ASCII,BIN 码常用格式解析生成。

2023-12-20 07:59:24

? ? ? 1 生成报文序列seq

? ? ? ? 序列号域即为数据包的发送顺序号,从 0 开始顺序增加,如是应答数据包,则与询问数据包序号保持一致,当桩与平台网络断开重新建立连接或者溢出后归 0。
import java.util.HashMap;

/**
 * @author hua
 * @date 2023-10-10 19:09
 */
public class SeqNumGenerator {

    private static HashMap<String,SeqNumGenerator> local=new HashMap<String,SeqNumGenerator>();

    /**
     * 开始序列
     */
    private short sequenceNumber = 0;

    /**
     * 依据报文格式要求设置最允许序列
     */
    private short maxSeqLimit = 99;

    public byte[] getNextSequenceNumber() {
        // 递增序号
        sequenceNumber++;
        if(sequenceNumber>maxSeqLimit){
            sequenceNumber=0;
        }
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (sequenceNumber & 0xFF);
        bytes[1] = (byte) ((sequenceNumber >> 8) & 0xFF);
        return bytes;

    }

    /**
     * 报文序列生成
     * @param seqKeyName
     * @return
     */
    public static byte[] getSeq(String seqKeyName){
        if(!(seqKeyName!=null&&seqKeyName.trim().length()>0)){
            seqKeyName="common";
        }
        if(local.get(seqKeyName)==null){
            SeqNumGenerator generator = new SeqNumGenerator();
            byte[] r=generator.getNextSequenceNumber();
            return r;
        }else{
            return local.get(seqKeyName).getNextSequenceNumber();
        }
    }


}

2 bcd格式解析?

static final char[] HEX_CHAR = "0123456789ABCDEF".toCharArray();

    /**
     * 转金额
     *
     * @param dataByte bcd码
     * @param left     左移位数, 123456 -> 12345.6
     * @return
     */
    public static BigDecimal getBcdValueBy(byte[] dataByte, int left) {
        byte[] data = MessageUtils.convertToLittleEndian(dataByte);
        
        char[] chars = new char[data.length * 2];

        for (int i = 0; i < data.length; ++i) {
            chars[i * 2] = HEX_CHAR[data[i] >> 4 & 15];
            chars[i * 2 + 1] = HEX_CHAR[data[i] & 15];
        }

        String str = new String(chars).toLowerCase();
        return new BigDecimal(str).movePointLeft(left);
    }

3 bin格式解析

/**
     * bin码解析
     *
     * @param bytes
     * @return
     */
    public static int getPriceByBin(byte[] bytes) {
        int result = 0;
        for (int i = bytes.length - 1; i >= 0; i--) {
            result = (result << 8) | (bytes[i] & 0xFF);
        }
        return result;
    }

4 生成下发金额生成bin

? 文档要求:

? 按文档生成长度为4的byte字节,精度五位小数

    /**
     * 计费规则用  4byte  5位小数
     *
     * @param price
     * @return
     */
    public static byte[] get4bPrice(BigDecimal price) {

        int price_int = price.movePointRight(5).intValue();//右移5位,与文档要求一致

        ByteBuffer byteBuffer = ByteBuffer.allocate(4); //这里的4是与设备下发要求的长度一致
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN); //这里是小端模式
        byteBuffer.putInt(price_int);
        byte[] bytes =byteBuffer.array();
        return bytes;
    }

5 生成bcd数据

// 将十进制数字转换为BCD码
    public static byte[] getBCDBy(int dec) {
        int temp = dec;
        // 计算BCD码数组的长度
        int bcdLength = (int) Math.ceil((double) Integer.toString(dec).length() / 2);
        // 创建存储BCD码的字节数组
        byte[] bcdCode = new byte[bcdLength];

        // 从右向左遍历BCD码数组
        for (int i = bcdLength - 1; i >= 0; i--) {
            // 取出最低位的十进制数字
            byte lowerNibble = (byte) (temp % 10);
            // 取出次低位的十进制数字
            byte upperNibble = (byte) ((temp / 10) % 10);
            // 使用位运算将两个十进制数字合并成一个字节,高位使用upperNibble,低位使用lowerNibble
            bcdCode[i] = (byte) ((upperNibble << 4) | lowerNibble);
            // 将temp右移两位,准备处理下两位十进制数字
            temp /= 100;
        }

        return bcdCode;
    }

6 ascii码解析

public static String bytesToAscii(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append((char) b);
        }
        return sb.toString();
    }

7 互转大小端

? 设备上传的不全是小端时需要转换。window平台一般都是小端模式。

 /**
     * 互转小端
     *
     * @param data
     * @return
     */
    public static byte[] convertToLittleEndian(byte[] data) {
        byte[] converted = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            converted[i] = data[data.length - i - 1];
        }
        return converted;
    }

文章来源:https://blog.csdn.net/qyhua/article/details/135063769
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。