|
@@ -0,0 +1,152 @@
|
|
|
+package com.tokheim.aifueling.communication.toMachine;
|
|
|
+
|
|
|
+import cn.hutool.core.convert.Convert;
|
|
|
+import com.tokheim.aifueling.utils.ByteArrayUtils;
|
|
|
+import com.tokheim.aifueling.utils.SM4Utils;
|
|
|
+import io.netty.channel.ChannelHandlerContext;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 封装对油机发送信息操作
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class MachineWriter {
|
|
|
+ //数据包头
|
|
|
+ private static byte[] dataHead = new byte[]{0x02,0x01,0x01,0x00,0x00,0x62};
|
|
|
+
|
|
|
+ private static Map<String, ChannelHandlerContext> ctxMap = new HashMap<>();
|
|
|
+
|
|
|
+ public static void setCtxMap(String ip, ChannelHandlerContext ctx) {
|
|
|
+ ctxMap.put(ip, ctx);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void removeCtxMap(String ip) {
|
|
|
+ ctxMap.remove(ip);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 定量加油
|
|
|
+ * @param ip 发送目标油机ip
|
|
|
+ * @param fuelPoint 加油点
|
|
|
+ * @param internalNum 内部枪号
|
|
|
+ * @param amount 定量金额
|
|
|
+ */
|
|
|
+ public static boolean sendQuantitative(String ip,int fuelPoint,int internalNum,String amount) {
|
|
|
+ if (!checkBaseParam(ip, fuelPoint, internalNum)) {
|
|
|
+ log.error("sendQuantitative:参数:{},{},{}错误",ip,fuelPoint,internalNum);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ ChannelHandlerContext context = ctxMap.get(ip);
|
|
|
+ if (context == null) {
|
|
|
+ log.error("sendQuantitative:Cannot find handler for ip {}", ip);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //拼接实际内容
|
|
|
+ byte[] nonAmountBytes = {0x05, (byte) (fuelPoint + 32),0x24, (byte) internalNum,0x27,0x05,0x06};
|
|
|
+ byte[] amountBytes = ByteArrayUtils.decimalStrToBCD(amount);
|
|
|
+ byte[] waitEncryptBytes = ByteArrayUtils.add(nonAmountBytes, amountBytes);
|
|
|
+
|
|
|
+ return sendData(waitEncryptBytes,context);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送车牌号
|
|
|
+ * @param ip 发送目标油机ip
|
|
|
+ * @param fuelPoint 加油点
|
|
|
+ * @param internalNum 内部枪号
|
|
|
+ * @param carNum 车牌号
|
|
|
+ */
|
|
|
+ public static boolean sendCarNumber(String ip,int fuelPoint,int internalNum,String carNum) {
|
|
|
+ if (!checkBaseParam(ip, fuelPoint, internalNum)) {
|
|
|
+ log.error("sendCarNumber:参数:{},{},{}错误",ip,fuelPoint,internalNum);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ ChannelHandlerContext context = ctxMap.get(ip);
|
|
|
+ if (context == null) {
|
|
|
+ log.error("sendCarNumber:Cannot find handler for ip {}", ip);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //拼接实际内容
|
|
|
+ byte[] nonCarNum = {0x06, (byte) (fuelPoint + 32),0x24, (byte) internalNum,0x29};
|
|
|
+ byte[] carNumContentBytes = carNum.getBytes(Charset.forName("GB2312"));
|
|
|
+ byte[] carNumBytes = ByteArrayUtils.add(new byte[]{(byte) carNumContentBytes.length}, carNumContentBytes);
|
|
|
+ byte[] waitEncryptBytes = ByteArrayUtils.add(nonCarNum, carNumBytes);
|
|
|
+
|
|
|
+ return sendData(waitEncryptBytes,context);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 停止加油
|
|
|
+ * @param ip 发送目标油机ip
|
|
|
+ * @param fuelPoint 加油点
|
|
|
+ * @param internalNum 内部枪号
|
|
|
+ */
|
|
|
+ public static boolean stopFueling(String ip,Integer fuelPoint,Integer internalNum) {
|
|
|
+ if (!checkBaseParam(ip, fuelPoint, internalNum)) {
|
|
|
+ log.error("stopFueling:参数:{},{},{}错误",ip,fuelPoint,internalNum);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ ChannelHandlerContext context = ctxMap.get(ip);
|
|
|
+ if (context == null) {
|
|
|
+ log.error("stopFueling:Cannot find handler for ip {}", ip);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //拼接实际内容
|
|
|
+ byte[] waitEncryptBytes = {0x04, (byte) (fuelPoint + 32),0x24, Convert.toByte(internalNum)};
|
|
|
+
|
|
|
+ return sendData(waitEncryptBytes,context);
|
|
|
+ }
|
|
|
+
|
|
|
+ //加密及添加长度
|
|
|
+ private static byte[] encryptAndLen(byte[] waitEncryptBytes) {
|
|
|
+ byte[] noneHeaderBytes = new byte[0];
|
|
|
+ try {
|
|
|
+ byte[] encrypt = SM4Utils.encrypt(waitEncryptBytes);
|
|
|
+ byte[] lenBytes = ByteArrayUtils.intToTwoByteArray(encrypt.length);
|
|
|
+ if (lenBytes != null) {
|
|
|
+ noneHeaderBytes = ByteArrayUtils.add(lenBytes, encrypt);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("加密失败:{}", ByteArrayUtils.bytesToHexString(waitEncryptBytes));
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ return noneHeaderBytes;
|
|
|
+ }
|
|
|
+
|
|
|
+ //检查基础信息
|
|
|
+ private static boolean checkBaseParam(String ip,int fuelPoint,int internalNum) {
|
|
|
+ if (ip == null || ip.isEmpty()) return false;
|
|
|
+ return Convert.toInt(fuelPoint) != null && Convert.toInt(internalNum) != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将数据打包好发送到油机
|
|
|
+ * 加密,添加长度,添加包头
|
|
|
+ * @param waitEncryptBytes 待加密数据
|
|
|
+ * @param context 发送油机 channel
|
|
|
+ * @return 成功与否
|
|
|
+ */
|
|
|
+ private static boolean sendData(byte[] waitEncryptBytes,ChannelHandlerContext context) {
|
|
|
+ //加密并加上长度
|
|
|
+ byte[] noneHeaderBytes = encryptAndLen(waitEncryptBytes);
|
|
|
+
|
|
|
+ //拼接包头并发送
|
|
|
+ if (noneHeaderBytes.length != 0) {
|
|
|
+ byte[] content = ByteArrayUtils.add(dataHead,noneHeaderBytes);
|
|
|
+
|
|
|
+ log.info("发送数据到油机:{},数据:{}",context.channel().remoteAddress(),ByteArrayUtils.bytesToHexString(content));
|
|
|
+ //write 在接口处调用时客户端会接收不到数据,要用 writeAndFlush
|
|
|
+ context.channel().writeAndFlush(content);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|