Files
jsowell-charger-web/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java
2024-08-02 15:45:15 +08:00

156 lines
4.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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) {
// log.info("checkMsg:{}", BytesUtil.binary(msg, 16));
// 起始标志
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;
}
public static void main(String[] args) {
byte[] length = new byte[]{0x22};
System.out.println(BytesUtil.bytesToIntLittle(length));
}
/**
* 转换电压电流以及起始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;
}
/**
* 转换温度
* 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 "";
}
/**
* 解析vin
*/
public static String parseVin(byte[] vinCodeByteArr) {
return BytesUtil.ascii2Str(vinCodeByteArr);
}
}