工具方法

This commit is contained in:
Guoqs
2024-11-01 15:21:28 +08:00
parent 16fc06e666
commit dfbcbfb786

View File

@@ -2,14 +2,19 @@ package com.jsowell.common.util;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Bytes;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.YKCBaseMessage;
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
import com.jsowell.common.core.redis.StaticRedisCache;
import com.jsowell.common.enums.ykc.PileChannelEntity;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;
@Slf4j
@@ -64,13 +69,116 @@ public class YKCUtils {
if (sourceCRC.equalsIgnoreCase(targetCRC) || sourceCRC.equalsIgnoreCase(crc)) {
return true;
}
log.error("CRC校验不通过, 源crc:{}, 计算得出crc:{}, 老crc计算:{}, 高低位反转后crc:{}, 帧类型:{}, 帧名称:{},报文{}, msg:{}"
log.error("CRC校验不通过, 源crc:{}, 计算得出crc:{}, 老crc计算:{}, 高低位反转后crc:{}, 帧类型:{}, 帧名称:{}, 报文:{}"
, sourceCRC, targetCRC, oldTargetCRC, crc, YKCUtils.frameType2Str(frameType),
YKCFrameTypeCode.getFrameTypeStr(YKCUtils.frameType2Str(frameType)),
BytesUtil.binary(msg, 16), Arrays.toString(msg));
YKCFrameTypeCode.getFrameTypeStr(YKCUtils.frameType2Str(frameType)), BytesUtil.binary(msg, 16));
return false;
}
/**
* 获取结果报文
* @param ykcDataProtocol
* @param messageBody
* @return
*/
public static byte[] getResult(YKCDataProtocol ykcDataProtocol, byte[] messageBody) {
// 起始标志
byte[] head = ykcDataProtocol.getHead();
// 序列号域
byte[] serialNumber = ykcDataProtocol.getSerialNumber();
// 加密标志
byte[] encryptFlag = ykcDataProtocol.getEncryptFlag();
// 请求帧类型
byte[] requestFrameType = ykcDataProtocol.getFrameType();
// 应答帧类型
byte[] responseFrameType = YKCFrameTypeCode.PlatformAnswersRelation.getResponseFrameTypeBytes(requestFrameType);
// 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和
byte[] dataFields = Bytes.concat(serialNumber, encryptFlag, responseFrameType, messageBody);
// 计算crc 从序列号域到数据域的 CRC 校验
int crc16 = CRC16Util.calcCrc16(dataFields);
return Bytes.concat(head, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16));
}
public static byte[] getResult(YKCBaseMessage message, byte[] messageBody) {
// 起始标志
String header = message.getHeader();
byte[] headBytes = BytesUtil.stringToHexBytes(header, 1);
// 序列号域
int serialNumber = message.getSerialNumber();
byte[] serialNumberBytes = BytesUtil.intToBytesLittle(serialNumber, 2);
// 加密标志
int encryptFlag = message.getEncryptFlag();
byte[] encryptFlagBytes = BytesUtil.intToBytesLittle(encryptFlag, 1);
// 请求帧类型
String frameType = message.getFrameType();
byte[] requestFrameTypeBytes = BytesUtil.hexString2Bytes(frameType.replace("0x", ""));
// 应答帧类型
byte[] responseFrameTypeBytes = YKCFrameTypeCode.PlatformAnswersRelation.getResponseFrameTypeBytes(requestFrameTypeBytes);
// 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和
byte[] dataFields = Bytes.concat(serialNumberBytes, encryptFlagBytes, responseFrameTypeBytes, messageBody);
// 计算crc 从序列号域到数据域的 CRC 校验
int crc16 = CRC16Util.calcCrc16(dataFields);
return Bytes.concat(headBytes, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16));
}
public static void main(String[] args) {
String type = "0x3B";
System.out.println(type);
byte[] bytes = BytesUtil.hexString2Bytes(type.replace("0x", ""));
System.out.println(YKCUtils.frameType2Str(bytes));
}
/**
* 保存桩最后链接到平台的时间
* @param pileSn 桩编号
*/
public static void saveLastTimeAndCheckChannel(String pileSn, ChannelHandlerContext ctx) {
String redisKey = CacheConstants.PILE_LAST_CONNECTION + pileSn;
StaticRedisCache.staticRedisCache.setCacheObject(redisKey, DateUtils.getDateTime(), CacheConstants.cache_expire_time_30d);
// 保存桩号和channel的关系
PileChannelEntity.checkChannel(pileSn, ctx);
}
/**
* 阻止重复帧, 并返回是否重复
* 判断逻辑相同的channelId和序列号的请求30秒内只允许一次
* @return true 重复
*/
public static boolean verifyTheDuplicateRequest(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) {
// 获取序列号域
int serialNumber = BytesUtil.bytesToIntLittle(ykcDataProtocol.getSerialNumber());
// 获取channelId
String channelId = ctx.channel().id().asShortText();
String redisKey = "Request_" + channelId + "_" + serialNumber;
Boolean result = StaticRedisCache.staticRedisCache.setnx(redisKey, ykcDataProtocol.getHEXString(), 30);
// result返回false说明没有设置成功就是说已经有相同请求了所以返回true重复
return !result;
}
/**
* 从消息中获取pileSn
*/
public static byte[] getPileSnBytes(String pileSn) {
// 通过pileSN转换为byte[]
return BytesUtil.hexStringToByteArray(pileSn);
}
/**
* 转换电压电流以及起始soc
* 精确到小数点后一位;待机置零
@@ -95,7 +203,7 @@ public class YKCUtils {
* @return
*/
public static String convertDecimalPoint(byte[] bytes, int scale) {
// 转换为int
// 转换为int
int i = BytesUtil.bytesToIntLittle(bytes);
// 使用BigDecimal
BigDecimal bigDecimal = new BigDecimal(i);
@@ -229,12 +337,4 @@ public class YKCUtils {
return map.get("connectorCode");
}
public static void main(String[] args) {
String pileConnectorCode = "8800000000000201";
// pileConnectorCode = "1327388103";
String pileSn = YKCUtils.getPileSn(pileConnectorCode);
System.out.println(pileSn);
String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode);
System.out.println(connectorCode);
}
}