package com.jsowell.common.util; import com.google.common.primitives.Bytes; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; import lombok.extern.slf4j.Slf4j; import java.math.BigDecimal; import java.util.Arrays; @Slf4j public class YKCUtils { private static final BigDecimal multiple = new BigDecimal("100000"); /** * 校验云快充请求数据格式 * * @param msg 请求报文 * @return */ public static boolean checkMsg(byte[] msg) { // 起始标志 byte[] head = BytesUtil.copyBytes(msg, 0, 1); // 数据长度 byte[] length = BytesUtil.copyBytes(msg, 1, 1); // 序列号域 byte[] serialNumber = BytesUtil.copyBytes(msg, 2, 2); // 加密标志 byte[] encryptFlag = BytesUtil.copyBytes(msg, 4, 1); // 帧类型标志 byte[] frameType = BytesUtil.copyBytes(msg, 5, 1); // 消息体 byte[] msgBody = BytesUtil.copyBytes(msg, 6, msg.length - 8); // 帧校验域 byte[] crcByte = new byte[]{msg[msg.length - 2], msg[msg.length - 1]}; //起始位必须是0x68 if (0x68 != head[0]) { log.error("起始位必须是0x68"); return false; } // 序列号域+加密标志+帧类型标志+消息体 byte[] data = Bytes.concat(serialNumber, encryptFlag, frameType, msgBody); // 校验长度 if (data.length != BytesUtil.bytesToIntLittle(length)) { log.error("数据长度不正确, 数据长度:{}, 实际长度:{}", BytesUtil.bytesToIntLittle(length), data.length); return false; } // CRC校验 source target String sourceCRC = String.format("%04x", BytesUtil.bytesToInt(crcByte, 0)); String targetCRC = String.format("%04x", CRC16Util.calcCrc16(data)); String oldTargetCRC = String.format("%04x", CRC16Util.calcCrc16Old(data)); // 将高低位位置反转,得出新的crc String lowString = StringUtils.substring(targetCRC, 0, 2); String highString = StringUtils.substring(targetCRC, 2, 4); String crc = highString + lowString; // 若目标crc和高低位反转前/后的crc都不一致,则校验不通过 if (sourceCRC.equalsIgnoreCase(targetCRC) || sourceCRC.equalsIgnoreCase(crc)) { return true; } log.error("CRC校验不通过, 源crc:{}, 计算得出crc:{}, 老crc计算:{}, 高低位反转后crc:{}, 帧类型:{}, 帧名称:{},报文:{}, msg:{}" , sourceCRC, targetCRC, oldTargetCRC, crc, YKCUtils.frameType2Str(frameType), YKCFrameTypeCode.getFrameTypeStr(YKCUtils.frameType2Str(frameType)), BytesUtil.binary(msg, 16), Arrays.toString(msg)); return false; } /** * 转换电压电流以及起始soc * 精确到小数点后一位;待机置零 * * @param bytes * @return */ public static String convertVoltageCurrent(byte[] bytes) { // 转换为int 最后一位是小数位 int i = BytesUtil.bytesToIntLittle(bytes); // 使用BigDecimal BigDecimal bigDecimal = new BigDecimal(i); BigDecimal divide = bigDecimal.divide(new BigDecimal(10), 1, BigDecimal.ROUND_UP); return divide.toString(); } /** * 转换小数点 * * @param bytes * @param scale 小数位 * @return */ public static String convertDecimalPoint(byte[] bytes, int scale) { // 转换为int int i = BytesUtil.bytesToIntLittle(bytes); // 使用BigDecimal BigDecimal bigDecimal = new BigDecimal(i); BigDecimal divide = bigDecimal.divide(BigDecimal.valueOf(Math.pow(10d, scale)), scale, BigDecimal.ROUND_UP); return divide.toString(); } /** * 获取价格byte数组 * 价格转换为byte数组 * @param price 实际价格,单位元 * @param scale 保留小数位 * @return */ public static byte[] getPriceByte(String price, int scale) { // 保留小数位 例:保留5位小数,需要乘以10的5次方 BigDecimal value = BigDecimal.valueOf(Math.pow(10d, scale)); int i = new BigDecimal(price).multiply(value).intValue(); return BytesUtil.intToBytesLittle(i, 4); } /** * byte转帧类型字符串 如:"01"--> "0x01" * @param bytes * @return */ public static String frameType2Str(byte[] bytes) { String s = BytesUtil.bin2HexStr(bytes); return Constants.HEX_PREFIX + s; } public static byte[] frameTypeStr2Bytes(String frameTypeStr) { byte[] bytes = BytesUtil.hexString2Bytes(frameTypeStr); return bytes; } public static void main(String[] args) { String frameTypeStr = "0x01"; byte[] bytes = frameTypeStr2Bytes(frameTypeStr); System.out.println("转为byte数组:" + Arrays.toString(bytes)); String frameType2Str = frameType2Str(bytes); System.out.println("转为Str:" + frameType2Str); // String hexString = "681E0000003388000000000027012302081602434533880000000000270101008361"; // byte[] byteArray = new byte[hexString.length() / 2]; // for (int i = 0; i < byteArray.length; i++) { // int index = i * 2; // int j = Integer.parseInt(hexString.substring(index, index + 2), 16); // byteArray[i] = (byte) j; // } // System.out.println(byteArray); // String binary = BytesUtil.binary(byteArray, 16); // String aaa = DatatypeConverter.printHexBinary(byteArray); // System.out.println(binary); // System.out.println(aaa); // String targetCRC = "0abb"; // String substring = StringUtils.substring(targetCRC, 0, 2); // String substring1 = StringUtils.substring(targetCRC, 2, 4); // String crc = substring1 + substring; // // String hexString = "4f"; // byte[] bytes = new byte[]{0x4f}; // // String s = transitionTemperature(bytes); // System.out.println(s); // // byte[] bytess = new byte[]{(byte) 0x80, (byte) 0x1A, 0x06, 0x00}; // String s1 = convertDecimalPoint(bytess, 5); // System.out.println(s1); // // String amount = "1000"; // byte[] priceByte = getPriceByte(amount, 2); // System.out.println(BytesUtil.bin2HexStr(priceByte)); } /** * 转换温度 * BIN 码 1 整形,偏移量-50;待机置零 */ public static String transitionTemperature(byte[] bytes) { String s = BytesUtil.binary(bytes, 10); int i = Integer.parseInt(s); if (i > 0) { return String.valueOf(i - 50); } return "一"; } }