Files
jsowell-charger-web/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java

171 lines
5.3 KiB
Java
Raw Normal View History

2023-03-04 16:29:55 +08:00
package com.jsowell.common.util;
import com.google.common.primitives.Bytes;
2023-12-26 14:41:25 +08:00
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
2023-03-04 16:29:55 +08:00
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("数据长度不正确");
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));
2023-06-29 09:16:50 +08:00
// 将高低位位置反转得出新的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;
2023-03-04 16:29:55 +08:00
}
2023-12-26 14:41:25 +08:00
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));
2023-06-29 09:16:50 +08:00
return false;
2023-03-04 16:29:55 +08:00
}
/**
* 转换电压电流以及起始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转帧类型字符串
* @param bytes
* @return
*/
public static String frameType2Str(byte[] bytes) {
String s = BytesUtil.bin2HexStr(bytes);
return "0x" + s;
}
public static void main(String[] args) {
// 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);
2023-06-29 09:16:50 +08:00
String targetCRC = "0abb";
String substring = StringUtils.substring(targetCRC, 0, 2);
String substring1 = StringUtils.substring(targetCRC, 2, 4);
String crc = substring1 + substring;
2023-03-27 11:49:32 +08:00
String hexString = "4f";
byte[] bytes = new byte[]{0x4f};
2023-03-04 16:29:55 +08:00
2023-03-27 11:49:32 +08:00
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));
2023-03-27 11:49:32 +08:00
}
/**
* 转换温度
* BIN 1 整形偏移量-50待机置零
*/
public static String transitionTemperature(byte[] bytes) {
String s = BytesUtil.binary(bytes, 10);
int i = Integer.parseInt(s);
2023-03-27 17:03:28 +08:00
if (i > 0) {
return String.valueOf(i - 50);
}
return "";
2023-03-04 16:29:55 +08:00
}
}