Эх сурвалжийг харах

tms中间件版本--00.00.02(江西江投站版本)

xgm 3 жил өмнө
parent
commit
3cdf2658ad

+ 1 - 0
middleware-client-jiangxi/pom.xml

@@ -11,6 +11,7 @@
 
     <artifactId>middleware-client-jiangxi</artifactId>
 
+
     <dependencies>
         <!--spring-boot-starter-web-->
         <dependency>

+ 153 - 15
middleware-client-jiangxi/src/main/java/com/tokheim/client/itouch/ClientFactory.java

@@ -3,6 +3,7 @@ package com.tokheim.client.itouch;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.tokheim.client.manager.factory.AsyncFactory;
+import com.tokheim.client.manager.factory.SocketFactory;
 import com.tokheim.client.utils.ByteUtils;
 import com.tokheim.client.utils.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
@@ -28,6 +29,9 @@ import java.util.concurrent.Executors;
 public class ClientFactory {
     // 创建固定数量的线程池
     private static ExecutorService executorService = null;
+    private static ExecutorService reExecutorService = null;
+    private static ExecutorService nozzleExecutorService = null;
+    private static ExecutorService headerExecutorService = null;
 
     private String iTouchHost;
     private String iTouchPort;
@@ -52,6 +56,9 @@ public class ClientFactory {
 
     static {
         executorService = Executors.newFixedThreadPool(10);
+        reExecutorService = Executors.newFixedThreadPool(10);
+        nozzleExecutorService = Executors.newFixedThreadPool(10);
+        headerExecutorService = Executors.newFixedThreadPool(10);
         //模拟油枪信息
         //nozzles.add("02 01 01 00 02 60 00 09 02 21 11 05 01 01 D3 01 00");
         //nozzles.add("02 01 01 00 02 60 00 09 02 23 11 05 01 03 D3 01 00");
@@ -61,11 +68,20 @@ public class ClientFactory {
         //nozzles2.add("00000000000000103139322E3136382E312E353A39393132020101000260000B0100FF0720200928174255103139322E3136382E312E353A39393132020101000060001601242205060000223223050600000279240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000223223050600000279240404000800000000000000103139322E3136382E312E353A39393132020101000060001601242205060000281623050600000352240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000281623050600000352240404000800000000000000103139322E3136382E312E353A39393132020101000060001601242205060000334423050600000418240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000334423050600000418240404000800000000000000103139322E3136382E312E353A39393132020101000260000B0100FF0720200928174258103139322E3136382E312E353A39393132020101000060001601242205060000388023050600000485240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000388023050600000485240404000800000000000000103139322E3136382E");
     }
 
+    /**
+     * 将字符串去掉0开发
+     *
+     * @param stationIp 油机Ip地址
+     * @param iTouchPort 多媒体屏app的ip端口号
+     * @param msg 油机发送过来的16进制字符串
+     */
     public void setData(String stationIp, String iTouchPort, String msg) {
         try {
-            if (iTouchIps.isEmpty()) {
+           /* if (iTouchIps.isEmpty()) {
                 getConfigure(stationIp);
-            }
+            }*/
+           iTouchIps.clear();
+            getConfigure(stationIp);
             this.iTouchPort = iTouchPort;
             this.msg = msg;
             //获取ITouch多媒体屏ip
@@ -79,7 +95,11 @@ public class ClientFactory {
     }
 
 
-    //获取枪配置信息
+    /**
+     * 油枪信息截取
+     *
+     * @param msg 多条油枪组成16进制字符串
+     */
     public void recursionMsg(String msg) {
         if (msg.contains(header)) {
             String msg_front = msg.substring(msg.indexOf(header));
@@ -96,6 +116,11 @@ public class ClientFactory {
     }
 
 
+    /**
+     * 判断后发送数据到多媒体屏app
+     *
+     * @param msg 16进制字符串
+     */
     public void sendData(String msg) {
         for (String iTouchIp : iTouchIps) {
             Socket socket = socketMap.get(iTouchIp);
@@ -185,6 +210,11 @@ public class ClientFactory {
     }*/
 
 
+    /**
+     * 发送数据到多媒体屏app
+     *
+     * @param iTouchIp 多媒体app的Ip地址
+     */
     public void send(String iTouchIp) {
         try {
             Socket socket = socketMap.get(iTouchIp);
@@ -244,9 +274,10 @@ public class ClientFactory {
         }
     }
 
-
     /**
-     * 重连
+     * 重连多媒体app
+     *
+     * @param iTouchIp 多媒体app的Ip地址
      */
     public void restartSocket(String iTouchIp) {
         try {
@@ -278,7 +309,9 @@ public class ClientFactory {
 
 
     /**
-     * 刚启动时,app没有启动
+     * 监听多媒体app初始化是是否已启动
+     *
+     * @param iTouchIp 多媒体app的Ip地址
      */
     public void startSocket(String iTouchIp) {
         try {
@@ -302,7 +335,9 @@ public class ClientFactory {
     }
 
     /**
-     * 停止
+     * 停止与多媒体app连接
+     *
+     * @param iTouchIp 多媒体app的Ip地址
      */
     public void stopSocket(String iTouchIp) {
         try {
@@ -315,11 +350,14 @@ public class ClientFactory {
     }
 
 
+
     /**
-     * 发送油机心跳信息
+     * 发送心跳到多媒体app
+     *
+     * @param iTouchIp 多媒体app的Ip地址
      */
     public void sendHeartedData(String iTouchIp) {
-        new Thread(new Runnable() {
+        /*new Thread(new Runnable() {
             @Override
             public void run() {
                 try {
@@ -341,11 +379,75 @@ public class ClientFactory {
                     }
                 }
             }
-        }).start();
+        }).start();*/
+        headerExecutorService.submit(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(10000);
+                    Socket socket = socketMap.get(iTouchIp);
+                    if (socket != null && !socket.isClosed()) {
+                        OutputStream out = socket.getOutputStream();
+                        out.write(0);
+                        out.flush();
+                    }
+                } catch (Exception e) {
+                    socketMap.remove(iTouchIp);
+                    flag = false;
+                    restartSocket(iTouchIp);
+                    e.printStackTrace();
+                } finally {
+                    if (flag) {
+                        sendHeartedData(iTouchIp);
+                    }
+                }
+            }
+        });
     }
 
+    /**
+     *接收多媒体app发送信息
+     *
+     * @param iTouchIp 多媒体app的Ip地址
+     */
     public void reData(String iTouchIp) {
-        new Thread(new Runnable() {
+       /* new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Socket socket = socketMap.get(iTouchIp);
+                    if (socket != null && !socket.isClosed()) {
+                        byte[] buf = new byte[1024];
+                        while (true) {
+                            InputStream in = socket.getInputStream();
+                            if (in.available() > 0) {
+                                int len = in.read(buf);
+                                byte[] real = new byte[len];
+                                //解析数据
+                                for (int i = 0; i < real.length; i++) {
+                                    real[i] = buf[i];
+                                }
+                                String[] strings = ByteUtils.bytesToHexStrings(real);
+                                //log.info("接收油机数据--" + Arrays.toString(strings));
+                                String msg = Arrays.toString(strings).replaceAll(",", "");
+                                msg = msg.substring(1, msg.length() - 1);
+                                if (!msg.contains("02 01 01 00 02 60 00 0B 01 00 FF")) {
+                                    //System.err.println(iTouchIp + "--ITouch信息---" + msg);
+                                    //log.info(iTouchIp + "--ITouch信息---" + msg);
+                                    AsyncFactory.out.write(ByteUtils.hexToByteArray(msg));
+                                } else {
+                                    //System.err.println("ITouch心跳信息---" + msg);
+                                }
+
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }).start();*/
+        reExecutorService.submit(new Runnable() {
             @Override
             public void run() {
                 try {
@@ -380,12 +482,17 @@ public class ClientFactory {
                     e.printStackTrace();
                 }
             }
-        }).start();
+        });
     }
 
 
+    /**
+     *发送油枪信息到多媒体app
+     *
+     * @param iTouchIp 多媒体app的Ip地址
+     */
     public void sendNozzleInfo(String iTouchIp) {
-        new Thread(new Runnable() {
+       /* new Thread(new Runnable() {
             @Override
             public void run() {
                 try {
@@ -408,7 +515,32 @@ public class ClientFactory {
                     e.printStackTrace();
                 }
             }
-        }).start();
+        }).start();*/
+
+        nozzleExecutorService.submit(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    if (flagMap.get(iTouchIp)) {
+                        Socket socket = socketMap.get(iTouchIp);
+                        OutputStream out = socket.getOutputStream();
+                        //先发送油枪信息
+                        String nozzleInfo = "";
+                        for (String nozzle : nozzles) {
+                            nozzleInfo += nozzle + " ";
+                        }
+                        System.err.println(iTouchIp + "--发送油枪信息--" + nozzleInfo);
+                        log.info(iTouchIp + "--发送油枪信息--" + nozzleInfo);
+                        byte[] byteInfo = ByteUtils.hexToByteArray(nozzleInfo);
+                        out.write(byteInfo);
+                        out.flush();
+                        flagMap.put(iTouchIp, false);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
     }
 
    /* public void sendNozzleInfo2(String iTouchIp) {
@@ -471,9 +603,15 @@ public class ClientFactory {
     }*/
 
 
+    /**
+     * 获取配置文件汇总多媒体信息
+     *
+     * @param stationIp 油机Ip地址
+     * @return
+     */
     public boolean getConfigure(String stationIp) {
         try {
-            String s = JSONUtils.readJSONFile(AsyncFactory.FILEPATH);
+            String s = JSONUtils.readJSONFile(SocketFactory.FILEPATH);
             s = s.trim();
             JSONObject configure = JSONObject.parseObject(s);
             JSONArray params = configure.getJSONArray("param");

+ 25 - 13
middleware-client-jiangxi/src/main/java/com/tokheim/client/manager/factory/AsyncFactory.java

@@ -94,27 +94,38 @@ public class AsyncFactory {
                                 //长度 0x11   ip:port
                                 String[] strings = ByteUtils.bytesToHexStrings(real);
                                 //log.info("接收油机数据--" + Arrays.toString(strings));
-                                //System.out.println("接收油机数据--" + Arrays.toString(strings));
                                 String msg = Arrays.toString(strings).replaceAll(",", "");
                                 //msg 需要去掉 []
                                 msg = msg.substring(1, msg.length() - 1);
+                                System.out.println("接收油机数据(16进制)--" + msg);
 
-
-                                int length = Integer.valueOf(ByteUtils.hexToDecimal(strings[0]));
-                                byte[] ipAndPort = PackageUtils.getIpAndPort(real, length);
-
-                                String ipPort = new String(ipAndPort);
-                                String stationIp = ipPort.substring(0, ipPort.indexOf(":"));
-                                //去掉ip地址与端口-->获取业务头--心跳头  02 01 01 00 02 60 00 0B 01
-                                byte[] newReal = Arrays.copyOfRange(real, length + 1, real.length);
-                                //心跳业务包头固定长度为 9
-                                byte[] serverHeader = PackageUtils.getServerHeader(newReal, 9);
-                                String[] serverHeaderString = ByteUtils.bytesToHexStrings(serverHeader);
                                 //协议心跳业务固定包头
                                 String heartHeaderPackage = "02 01 01 00 02 60 00 0B 01";
                                 String realTimePackage = "02 01 01 00 00 60 00 16 01";
                                 String oilHeaderPackage = "02 01 01 00 00 60 00 31 04";
                                 //String speechHeaderPackage = "02 01 01 00 00 60 00 08 01";
+                                String stationIp = "";
+                                //TODO 处理粘包
+                                if (msg.contains(heartHeaderPackage)){
+                                    String msg_sub = msg.substring(msg.lastIndexOf(heartHeaderPackage) - 51); //将粘包数据根据心跳头截取数据
+                                    String[] msg_arr = msg_sub.split(" "); //主要是想获取数据长度
+                                    int length = Integer.valueOf(ByteUtils.hexToDecimal(msg_arr[0]));
+                                    byte[] bytes = ByteUtils.hexToByteArray(msg_sub); //将16进制的字符创转成字节数组
+                                    byte[] ipAndPort = PackageUtils.getIpAndPort(bytes, length);
+                                    String ipPort = new String(ipAndPort);//将字节转成字符串
+                                    stationIp = ipPort.substring(0, ipPort.indexOf(":")); //获取油机ip地址
+                                }
+
+
+
+
+
+                                //去掉ip地址与端口-->获取业务头--心跳头  02 01 01 00 02 60 00 0B 01
+                                //byte[] newReal = Arrays.copyOfRange(real, length + 1, real.length);
+                                //心跳业务包头固定长度为 9
+                                //byte[] serverHeader = PackageUtils.getServerHeader(newReal, 9);
+                                //String[] serverHeaderString = ByteUtils.bytesToHexStrings(serverHeader);
+
 
                                 try {
                                     //TODO:将油机原始数据原封不动发送到多媒体中间件
@@ -129,11 +140,12 @@ public class AsyncFactory {
                                     ClientFactory clientFactory = new ClientFactory();
                                     clientFactory.setData(stationIp, ITOUCHPORT, msg);
                                 } catch (Exception e) {
+                                    log.error(e.getMessage());
                                     e.printStackTrace();
                                 }
 
                                 //心跳头
-                                if (Arrays.equals(serverHeaderString, heartHeaderPackage.split(" "))) {
+                                if (msg.contains(heartHeaderPackage)) {
                                     //组装心跳包发送回到服务端
                                     //去掉 ip:port 心跳业务包头
                                     HEARTED = msg;

+ 731 - 0
middleware-client-jiangxi/src/main/java/com/tokheim/client/manager/factory/SocketFactory.java

@@ -0,0 +1,731 @@
+package com.tokheim.client.manager.factory;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.tokheim.client.itouch.ClientFactory;
+import com.tokheim.client.utils.*;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author xgm
+ * @version 1.0
+ * @date: Created in 8:51 2021/10/12
+ */
+@Slf4j
+public class SocketFactory {
+
+    private static ExecutorService executorHearService = null;
+
+    private static String HOST;//服务器地址 10
+    private static int PORT;//服务器端口号
+    private static String URL;
+    public static String FILEPATH;
+
+    //多媒体socket ip与port
+    private static String ITOUCHHOST;
+    private static String ITOUCHPORT;
+    private static Map<String, String> nozzleInfoMap = new HashMap<>();
+    private static Map<String, String> configureMap = new HashMap<>();
+
+
+    private static Socket socket = null;
+    public static OutputStream out = null;
+    public static InputStream in = null;
+    private static boolean flag = true;
+    private static String prevPump = "";
+
+    private static String HEARTED = "";
+
+
+    private static String ENV;
+    private static String stationIp = "";
+
+
+    //private static List<String> stationIps = new ArrayList<>();
+    private static Map<String, ClientFactory> clientFactoryMap = new HashMap<>();
+
+    private static String msg_sub2 = "";
+
+
+
+
+
+
+    static {
+        executorHearService = Executors.newFixedThreadPool(5);
+        //getStationIps();
+    }
+
+    /**
+     * 主函数入口
+     *
+     * @param host 中间件设备socket的Ip地址
+     * @param port 中间件设备socket的端口号
+     * @param url 第三方后台地址
+     * @param filePath 配置文件存储路径
+     * @param env 开发环境变量
+     * @param iTouchHost 多媒体 app socket ip地址
+     * @param iTouchPort 多媒体app 的socket端口号
+     */
+    public synchronized  static void sendHeartMsg(String host, Integer port, String url, String filePath, String env, String iTouchHost, String iTouchPort) {
+        /*new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+            }
+        }).start();*/
+        byte buf[] = new byte[1024];
+        try {
+            HOST = host;
+            PORT = port;
+            URL = url;
+            FILEPATH = filePath;
+            ENV = env;
+            ITOUCHHOST = iTouchHost;
+            ITOUCHPORT = iTouchPort;
+            if (socket == null) socket = new Socket(HOST, PORT);
+            if (socket.isClosed()) {
+                socket = null;
+                socket = new Socket();
+                socket.connect(new InetSocketAddress(host, Integer.valueOf(port)), 2000);//超时时间为2秒
+            }
+
+            boolean connected = socket.isConnected();
+            if (connected) {
+                flag = true;
+                out = socket.getOutputStream();
+                in = socket.getInputStream();
+
+                //TODO 该发送数据主要是解决在客户端与服务端正常数据交互的情况下,服务端突然断开的情况
+                if (flag) sendMsg();
+                //启动一个方法检测心跳
+
+
+                while (true) {
+                    if (in.available() > 0) {
+                        int len = in.read(buf);
+                        byte[] real = new byte[len];
+                        //解析数据
+                        for (int i = 0; i < real.length; i++) {
+                            real[i] = buf[i];
+                        }
+                        //心跳包处理格式
+                        //长度 0x11   ip:port
+                        String[] strings = ByteUtils.bytesToHexStrings(real);
+                        //log.info("接收油机数据--" + Arrays.toString(strings));
+                        String msg = Arrays.toString(strings).replaceAll(",", "");
+                        //msg 需要去掉 []
+                        msg = msg.substring(1, msg.length() - 1);
+
+
+                        //协议心跳业务固定包头
+                        String heartHeaderPackage = "02 01 01 00 02 60 00 0B 01";
+                        String realTimePackage = "02 01 01 00 00 60 00 16 01";
+                        String oilHeaderPackage = "02 01 01 00 00 60 00 31 04";
+                        //String speechHeaderPackage = "02 01 01 00 00 60 00 08 01";
+
+                        //TODO 改进获取 stationIp方法,该情况是黑盒子不往ITouch发送数据,所以注释掉,如果黑盒子往ITouch发送数据则不可注释掉
+                        //String[] data = msg.split(" ");
+                        //String length_hex = data[0];
+                        //int length_ = ByteUtils.hexToDecimal(length_hex);
+                        //String[] ipAndPort_ = Arrays.copyOfRange(data, 1, length_ +1);
+                        //String s = Arrays.toString(ipAndPort_);
+                        //String ipAndPortStr_ = s.substring(1,s.length() - 1).replaceAll(",","");
+                        //byte[] bytes_ = ByteUtils.hexToByteArray(ipAndPortStr_);
+                        //String value = new String(bytes_);
+                        //stationIp = value.substring(0,value.indexOf(":"));
+
+
+                      /*  //TODO 处理粘包
+                        if (msg.contains(heartHeaderPackage)) {
+                            String msg_sub = msg.substring(0, msg.indexOf(heartHeaderPackage)); //将粘包数据根据心跳头截取数据
+                            String[] msg_arr = msg_sub.split(" "); //主要是想获取数据长度
+                            int length = Integer.valueOf(ByteUtils.hexToDecimal(msg_arr[0]));
+                            byte[] bytes = ByteUtils.hexToByteArray(msg_sub); //将16进制的字符创转成字节数组
+                            byte[] ipAndPort = PackageUtils.getIpAndPort(bytes, length);
+                            String ipPort = new String(ipAndPort);//将字节转成字符串
+                            stationIp = ipPort.substring(0, ipPort.indexOf(":")); //获取油机ip地址
+                            //log.info("油机心跳信息--" + msg);
+                            //log.info("油机Ip--" + stationIp);
+                        }*/
+
+                         System.out.println(stationIp + "--接收油机数据(16进制)--" + msg);
+                         //log.info(stationIp + "--接收油机数据(16进制)--" + msg);
+
+                        //去掉ip地址与端口-->获取业务头--心跳头  02 01 01 00 02 60 00 0B 01
+                        //byte[] newReal = Arrays.copyOfRange(real, length + 1, real.length);
+                        //心跳业务包头固定长度为 9
+                        //byte[] serverHeader = PackageUtils.getServerHeader(newReal, 9);
+                        //String[] serverHeaderString = ByteUtils.bytesToHexStrings(serverHeader);
+
+
+                        try {
+                            //TODO:将油机原始数据原封不动发送到多媒体中间件
+                                    /*Map<String,Object> map = new HashMap<>();
+                                    map.put("msg",msg);
+                                    JSONObject object = new JSONObject(map);
+                                    HttpUtils httpUtils = new HttpUtils(false);
+                                    httpUtils.sendPost3("http://localhost:6682/receive/getData",object);*/
+                            //CacheData cacheData = new CacheData();
+                            //cacheData.setData(stationIp, ITOUCHPORT, msg);
+
+                            //ClientFactory clientFactory = new ClientFactory();
+                            //clientFactory.setData(stationIp, ITOUCHPORT, msg);
+
+                        } catch (Exception e) {
+                            log.error(e.getMessage());
+                            e.printStackTrace();
+                        }
+
+                        //心跳头
+                        if (msg.contains(heartHeaderPackage)) {
+                            //组装心跳包发送回到服务端
+                            //去掉 ip:port 心跳业务包头
+                            HEARTED = msg;
+                            out.write(real);
+                            out.flush();
+                        }
+                        if (msg.contains(realTimePackage)) {
+                            ////System.out.println("加油实时数据: " + Arrays.toString(ByteUtils.bytesToHexStrings(serverHeader)));
+                            ////System.out.println("加油实时数据:" + msg);
+                        }
+                        //加油记录包头,因为加油交易记录会粘包,所以需要转成string使用包含的方法获取交易记录信息
+                        if (msg.contains(oilHeaderPackage)) {
+                            //System.err.println("原始加油数据--" + msg);
+                            //log.info("原始加油数据--" + msg);
+                            Map<String, String> fuelMsg = getFuelMsg(msg, oilHeaderPackage);
+                            String id = ID.get().next().toString();
+                            //String filePath = System.getProperty("user.dir") + "\\configure.json"; //获取文件路径
+
+                            //获取配置文件信息
+                            //Map<String, String> configureMap = null;
+                            /*if (nozzleInfoMap.size() <= 0){
+                                configureMap = getConfigure(stationIp, fuelMsg);
+                            }else {
+                                configureMap.putAll(nozzleInfoMap);
+                            }*/
+
+                            msg_sub2 = msg.substring(0,msg.lastIndexOf(oilHeaderPackage)); //将粘包数据根据心跳头截取数据
+                            String[] msg_arr2 = msg_sub2.split(" "); //主要是想获取数据长度
+                            int length2 = Integer.valueOf(ByteUtils.hexToDecimal(msg_arr2[0]));
+                            byte[] bytes2 = ByteUtils.hexToByteArray(msg_sub2); //将16进制的字符创转成字节数组
+                            byte[] ipAndPort2 = PackageUtils.getIpAndPort(bytes2, length2);
+                            String ipPort2 = new String(ipAndPort2);//将字节转成字符串
+                            stationIp = ipPort2.substring(0, ipPort2.indexOf(":")); //获取油机ip地址
+
+
+
+                            configureMap = getConfigure(stationIp, fuelMsg);
+
+
+                            String businessTime = fuelMsg.get("date").trim() + " " + fuelMsg.get("time");//交易时间
+                            String refuelTime = fuelMsg.get("date").trim() + " " + fuelMsg.get("time"); //加油时间
+                            double quantity = Double.valueOf(fuelMsg.get("rise"));
+                            double amount = Double.valueOf(fuelMsg.get("amount"));
+                            double oilsPrice = Double.valueOf(fuelMsg.get("price"));
+
+
+
+                            //发送加油数据到第三方云平台
+                            String oilMsg = "{\"id\": \"" + id + "\"," + //id不能超过40个字节
+                                    "\"stationId\": \"" + configureMap.get("stationId") + "\"," + //油站Id
+                                    "\"stationName\": \"" + configureMap.get("stationName") + "\"," + // 油站名称
+                                    "\"sysDept\": \"" + configureMap.get("sysDept") + "\"," + //部门Id
+                                    "\"businessTime\": \"" + businessTime + "\"," + //交易时间
+                                    "\"memberId\": \"\"," + //会员Id
+                                    "\"memberNo\": \"\"," + //会员编号
+                                    "\"memberName\": \"\"," + // 持卡人
+                                    "\"cardNo\": \"\"," + //卡号
+                                    "\"gunNo\": \"" + configureMap.get("gunNo") + "\"," + // 枪号
+                                    "\"oils\": \"" + configureMap.get("oils") + "\"," + //油品名称--汽油、柴油
+                                    "\"oilGrade\": \"" + configureMap.get("oilGrade") + "\"," + //油品等级 92# 93# 98#
+                                    "\"quantity\": " + quantity + "," + //加油量
+                                    "\"amount\": " + amount + "," +  // 金额
+                                    "\"payAmount\": 0.0," + //支付金额 1--公众号、2--微信、3--支付宝、4--银联、5--现金、6--加油卡
+                                    "\"payShop\": \"" + configureMap.get("payShop") + "\"," +  // 支付方式 1--公众号、2--微信、3--支付宝、4--银联,5--现金,6--加油卡
+                                    "\"payState\": \"" + "0" + "\"," +  // 支付状态 0--待支付 1--已支付
+                                    "\"payType\": \"" + configureMap.get("payType") + "\"," +  // 支付方式 0--验泵卡、1--员工卡、2--维修卡、4--用户卡
+                                    "\"refuelTime\": \"" + refuelTime + "\"," +  //加油时间
+                                    "\"dealType\": \"\"," + // 处理类型
+                                    "\"refuelNum\": 0.0," + //
+                                    "\"oilsPrice\": " + oilsPrice + "," + // 单价
+                                    "\"ttc\": \"\"," + //
+                                    "\"ctc\": \"\"}"; //
+                            if (!prevPump.equals(fuelMsg.get("pump"))) {
+                                String oilMsgBase64 = Base64.getEncoder().encodeToString(oilMsg.getBytes());
+                                //System.err.println("加密后数据:" + oilMsgBase64);
+                                byte[] decode = Base64.getDecoder().decode(oilMsgBase64);
+                                //System.err.println("解密后数据:" + new String(decode));
+                                String sendOilMsg = "{ \"param\": \"" + oilMsgBase64 + "\"}";
+                                JSONObject jsonObject = JSON.parseObject(sendOilMsg);
+                                System.err.println("云平台数据:" + jsonObject.toString());
+                                log.info("ip地址:" + stationIp + "--" + "加油数据:" + JSONObject.toJSONString(fuelMsg));
+                                //log.error("加油数据:" + JSONObject.toJSONString(fuelMsg));
+                                //log.info("云平台数据:" + jsonObject.toString());
+                                //log.error("云平台数据:" + jsonObject.toString());
+                                System.out.println("云平台数据(解密):" + new String(decode));
+                                log.info("云平台数据(解密):" + new String(decode));
+                                String success = "";
+                                if (ENV.equals("prod")) { //dev  prod
+                                    String response = HttpUtils.sendPost3(url, jsonObject);
+                                    System.out.println("响应数据:" + response);
+                                    log.info("响应数据:" + response);
+                                    JSONObject js = JSONObject.parseObject(response);
+                                    success = String.valueOf(js.get("success"));
+                                } else {
+                                    success = "true";
+                                }
+                                if (Boolean.valueOf(success)) { //云平台响应成功
+                                    //记录上传泵码
+                                    prevPump = fuelMsg.get("pump");
+                                    //应答
+                                    String reHeader = "02 01 01 00 00 61 00 06 04 " + fuelMsg.get("gunNo") + " 21 " + fuelMsg.get("serialNum") + " 00"; //02 01 01 00 00 61 00 06 04 21 21 00 05 00  //16进制 固定包头 0201010000610006042121000500
+                                    byte[] bytes = ByteUtils.hexToByteArray(reHeader);
+                                    out.write(bytes);
+                                    out.flush();
+                                } else { //上传云平台响应失败
+                                    //记录上传泵码
+                                    prevPump = fuelMsg.get("pump");
+                                    //应答
+                                    String reHeader = "02 01 01 00 00 61 00 06 04 " + fuelMsg.get("gunNo") + " 21 " + fuelMsg.get("serialNum") + " 01"; //02 01 01 00 00 61 00 06 04 21 21 00 05 00  //16进制 固定包头 0201010000610006042121000500
+                                    byte[] bytes = ByteUtils.hexToByteArray(reHeader);
+                                    out.write(bytes);
+                                    out.flush();
+                                }
+                            } else {
+                                //log.error("配置文件出错,没有匹配上的ip或者油机泵码不变");
+                            }
+                        }
+                    }
+                }
+            } else {
+                //System.out.println("服务端已主动断开....");
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage() + "--" + msg_sub2);
+            log.error(e.getLocalizedMessage());
+            log.error(e.getStackTrace().toString());
+            e.printStackTrace();
+        } finally {
+            restartSocket();
+        }
+    }
+
+    /**
+     * 向油机发送心跳
+     *
+     * 该方法用于处理情景: 在连接正常地数据传输过程中,服务端突然断掉,
+     * 由于客户端没有报异常,所以无法知道 服务端已断掉,故通过不断向服务端发送 0 字节以此确认服务端是否连接
+     * TODO--后面可以通过主动向客户端发送心跳来解决
+     */
+    public static void sendMsg() {
+       /* new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(10000);
+                    //System.err.println("发送0数据......");
+                    if (socket != null && !socket.isClosed()){
+                        out.write(ByteUtils.hexToByteArray(HEARTED));
+                        out.flush();
+                    }
+                } catch (Exception e) {
+                    socket = null; //若发生异常则将socket置为null,后面重新建立新的对象,以确保新的连接
+                    out = null;
+                    in = null;
+                    flag = false;
+                    restartSocket();
+                    e.printStackTrace();
+                } finally {
+                    if (flag) {
+                        sendMsg();
+                    }
+                }
+            }
+        }).start();*/
+
+        executorHearService.submit(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(10000);
+                    //System.err.println("发送0数据......");
+                    if (socket != null && !socket.isClosed()) {
+                        out.write(ByteUtils.hexToByteArray(HEARTED));
+                        out.flush();
+                    }
+                } catch (Exception e) {
+                    socket = null; //若发生异常则将socket置为null,后面重新建立新的对象,以确保新的连接
+                    out = null;
+                    in = null;
+                    flag = false;
+                    restartSocket();
+                    e.printStackTrace();
+                } finally {
+                    if (flag) {
+                        sendMsg();
+                    }
+                }
+            }
+        });
+    }
+
+
+    /**
+     * 加油交易记录解析
+     *
+     * @param msg 加油交易记录,16进制字符串
+     * @param oilHeaderPackage 加油交易记录包头,16进制字符串
+     */
+    public static Map<String, String> getFuelMsg(String msg, String oilHeaderPackage) {
+        try {
+            //msg = msg.substring(msg.indexOf(oilHeaderPackage));
+            //System.out.println("油机加油数据(截取后)--" + msg);
+            //log.info("加油数据(16进制)--" + msg);
+            //拼接 上传交易记录
+            Map<String, String> resMap = new HashMap<>();
+
+            if (msg.contains(oilHeaderPackage)) {
+                msg = msg.substring(msg.indexOf(oilHeaderPackage));
+                //System.out.println(msg);
+                String[] arr = msg.split(" ");
+                String[] heart = Arrays.copyOfRange(arr, 0, 9);//交易记录-固定包头(9)
+                //System.out.println("包头: " + Arrays.toString(heart));
+
+                /**
+                 * 恒山加油机:一个加油点只能有一把或两把枪,两把枪的时候不能两把枪同时加油
+                 * 外部枪号就是逻辑枪号,外部枪号用于区分加油点有几把枪(1把或2把枪),外部枪号用于油站人员展示使用,关系不大!
+                 * 加油点+内部枪号+外部枪号
+                 * 如:1+1+1/1+2+2
+                 * 加油点1的第一把枪(内部枪号)   加油点1的第二把枪(内部枪号)
+                 *
+                 */
+                String[] gunNo = Arrays.copyOfRange(arr, 9, 10);//枪号(1)
+
+                for (int i = 0; i < gunNo.length; i++) {
+                    //int gunNo_ = ByteUtils.hexToDecimal(gunNo[i]) - ByteUtils.hexToDecimal("20");
+                    resMap.put("gunNo", gunNo[i]);
+                    //System.out.println("枪号: " + gunNo[i]);
+                }
+                String[] fixedVal = Arrays.copyOfRange(arr, 10, 11);//固定值(1)
+                for (int i = 0; i < fixedVal.length; i++) {
+                    //System.out.println("固定值: " + fixedVal[i]);
+                }
+                String[] serialNum = Arrays.copyOfRange(arr, 11, 13);//交易序列号(2)
+                StringBuffer serialNum_Str = new StringBuffer();
+                for (int i = 0; i < serialNum.length; i++) {
+                    serialNum_Str.append(serialNum[i]);
+                }
+                resMap.put("serialNum", serialNum_Str.toString());
+                //System.out.println("交易序列号: " + serialNum_Str);
+
+                String[] serialNum2 = Arrays.copyOfRange(arr, 13, 17);//交易序列号(4)
+                StringBuffer serialNum2_Str = new StringBuffer();
+                for (int i = 0; i < serialNum2.length; i++) {
+                    serialNum2_Str.append(serialNum2[i]);
+                }
+                //System.out.println("交易序列号2: " + Arrays.toString(serialNum2));
+                String[] amount = Arrays.copyOfRange(arr, 17, 24);//金额数目(7)
+                StringBuffer amount_int = new StringBuffer();
+                StringBuffer amount_frac = new StringBuffer();
+                if (amount[0].equals("05")) { //05--金额标识
+                    int flag = ByteUtils.hexToDecimal(amount[1]); //代表金额位数,第二个字节为几表示后续的几个字节均为表示金额的数据
+                    int int_part = ByteUtils.hexToDecimal(amount[2]) / 2; //整数部分占据几位
+                    int frac_part = (flag - 1) - int_part; //小数部分占据几位(去掉标识位数本身一位和整数位数就是小数位数)
+                    for (int i = 1; i <= int_part; i++) {
+                        //String flag_00 = amount[i + 2];
+                        //if (!flag_00.equals("00")) {
+                            amount_int.append(amount[i + 2]);
+                       // }
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        amount_frac.append(amount[i + 2 + int_part]);
+                    }
+                }
+
+                String amount_ = amount_int + "." + amount_frac;
+                //判断整数是否是0开头,如果是0开头需要去掉0
+                //if (amount_.startsWith("0")) amount_ = amount_.substring(1);
+                //if (amount_.startsWith(".")) amount_ = "0" + amount_;
+               splitVal(amount_);
+
+                resMap.put("amount", DATA);
+                //System.out.println("金额数目: " + amount_);
+
+
+                String[] rise = Arrays.copyOfRange(arr, 24, 31);//加油量(7)
+                StringBuffer rise_int = new StringBuffer();
+                StringBuffer rise_frac = new StringBuffer();
+                if (rise[0].equals("06")) { //06是加油量标识
+                    int flag = ByteUtils.hexToDecimal(rise[1]);
+                    int int_part = ByteUtils.hexToDecimal(rise[2]) / 2;
+                    int frac_part = (flag - 1) - int_part;
+                    for (int i = 1; i <= int_part; i++) {
+                        //if (!rise[i + 2].equals("00")) {
+                            rise_int.append(rise[i + 2]);
+                        //}
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        rise_frac.append(rise[i + 2 + int_part]);
+                    }
+                }
+                String rise_ = rise_int + "." + rise_frac;
+                //if (rise_.startsWith("0")) rise_ = rise_.substring(1); //若是以0开头需要去掉
+                //if (rise_.startsWith(".")) rise_ = "0" + rise_; //若点开头需要在前面添加0
+                splitVal(rise_);
+                if (DATA.startsWith(".")) DATA = "0" + DATA;
+                resMap.put("rise", DATA);
+                //System.out.println("加油量: " + rise_);
+
+
+                String[] price = Arrays.copyOfRange(arr, 31, 37);//单价(6)
+                StringBuffer price_int = new StringBuffer();
+                StringBuffer price_frac = new StringBuffer();
+                if (price[0].equals("07")) { //07标识单价
+                    int flag = ByteUtils.hexToDecimal(price[1]);
+                    int int_part = ByteUtils.hexToDecimal(price[2]) / 2;
+                    int frac_part = (flag - 1) - int_part;
+                    for (int i = 1; i <= int_part; i++) {
+                        //if (!price[i + 2].equals("00")) {
+                            price_int.append(price[i + 2]);
+                        //}
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        price_frac.append(price[i + 2 + int_part]);
+                    }
+                }
+                String price_ = price_int + "." + price_frac;
+                //if (price_.startsWith("0")) price_ = price_.substring(1);
+                //if (price_.startsWith(".")) price_ = "0" + price_;
+                splitVal(price_);
+                if (DATA.startsWith(".")) DATA = "0" + DATA;
+                resMap.put("price", DATA);
+                //System.out.println("单价: " + price_);
+
+                String[] date = Arrays.copyOfRange(arr, 37, 43);//日期(6)
+                StringBuffer dateBuffer = new StringBuffer();
+                if (date[0].equals("CA")) { //日期标识
+                    int flag = ByteUtils.hexToDecimal(date[1]);
+                    for (int i = 0; i < flag; i++) {
+                        dateBuffer.append(date[i + 2]);
+                    }
+                }
+
+                char[] chars = dateBuffer.toString().toCharArray();
+                char[] yyyy = Arrays.copyOfRange(chars, 0, 4);
+                char[] mm = Arrays.copyOfRange(chars, 4, 6);
+                char[] rr = Arrays.copyOfRange(chars, 6, 9);
+                String date_ = String.valueOf(yyyy) + "-" + String.valueOf(mm) + "-" + String.valueOf(rr);
+                date_ = date_.trim();
+                resMap.put("date", date_);
+                //System.out.println("日期: " + date_);
+
+
+                String[] time = Arrays.copyOfRange(arr, 43, 48);//时间(5)
+                StringBuffer time_str = new StringBuffer();
+                if (time[0].equals("D5")) {
+                    int flag = ByteUtils.hexToDecimal(time[1]);
+                    for (int i = 0; i < flag; i++) {
+                        time_str.append(time[i + 2] + ":");
+                    }
+
+                }
+                String time_ = time_str.toString();
+                if (time_.endsWith(":")) time_ = time_.substring(0, time_.lastIndexOf(":"));
+                resMap.put("time", time_);
+                //System.out.println("时间: " + time_);
+
+                String[] pump = Arrays.copyOfRange(arr, 48, 57);//泵码(9)
+                StringBuffer pump_int = new StringBuffer();
+                StringBuffer pump_frac = new StringBuffer();
+                if (pump[0].equals("CD")) { //CD 泵码标识
+                    int flag = ByteUtils.hexToDecimal(pump[1]);
+                    int int_part = ByteUtils.hexToDecimal(pump[2]) / 2;
+                    int frac_part = (flag - 1) - int_part;
+                    for (int i = 1; i <= int_part; i++) {
+                        //if (!pump[i + 2].equals("00")) {
+                            pump_int.append(pump[i + 2]);
+                        //}
+
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        pump_frac.append(pump[i + 2 + int_part]);
+                    }
+                }
+                String pump_ = pump_int + "." + pump_frac;
+                //if (pump_.startsWith("0")) pump_ = pump_.substring(1);
+                //if (pump_.startsWith(".")) pump_ = "0" + pump_;
+                splitVal(pump_);
+                if (DATA.startsWith(".")) DATA = "0" + DATA;
+                resMap.put("pump", DATA);
+                return resMap;
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage() + "--原始数据--" + msg);
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 重新连接油机
+     */
+    public static void restartSocket() {
+        try {
+           /* if (!socket.isClosed()) {
+                socket.close();
+            }*/
+            //每隔间10s向服务器请求一次以此检查服务器是否已经起来
+            Thread.sleep(10000);
+            System.out.println("重连油机socket.......");
+            if (socket == null) socket = new Socket(HOST, PORT);
+            SocketFactory.sendHeartMsg(HOST, Integer.valueOf(PORT), URL, FILEPATH, ENV, ITOUCHHOST, ITOUCHPORT);
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (socket == null) {
+                restartSocket();
+            }
+
+        }
+
+    }
+
+
+    /**
+     * 从配置文件获取油枪信息
+     *
+     * @param stationIp 油机Ip地址
+     * @param fuelMsg Map集合键值对
+     * @return
+     */
+    public static Map<String, String> getConfigure(String stationIp, Map<String, String> fuelMsg) {
+        try {
+            Map<String, String> resMap = new HashMap<>();
+            String s = JSONUtils.readJSONFile(FILEPATH);
+            s = s.trim();
+            JSONObject configure = JSONObject.parseObject(s);
+            JSONArray params = configure.getJSONArray("param");
+            String[] nozzles = null;
+            String gunNo = "";
+            String oils = "";
+            String oilGrade = "";
+            String payShop = "";
+            String payType = "";
+            String stationId = "";
+            String stationName = "";
+            String sysDept = "";
+            String ip = "";
+            String iTouchIp = "";
+            for (Object param : params) {
+                String paramStr = String.valueOf(param);
+                JSONObject configureObject = JSONObject.parseObject(paramStr);
+                ip = String.valueOf(configureObject.get("ip"));
+                if (ip.equals(stationIp)) {
+                    String nozzle = String.valueOf(configureObject.getJSONObject("configure").get("nozzle"));
+                    stationId = String.valueOf(configureObject.getJSONObject("configure").getJSONObject("station").get("stationId"));
+                    stationName = String.valueOf(configureObject.getJSONObject("configure").getJSONObject("station").get("stationName"));
+                    sysDept = String.valueOf(configureObject.getJSONObject("configure").getJSONObject("station").get("sysDept"));
+                    nozzles = nozzle.split(",");
+                }
+            }
+
+            String gunNum = fuelMsg.get("gunNo");
+            String gunNo_ = String.valueOf(ByteUtils.hexToDecimal(gunNum) - ByteUtils.hexToDecimal("20"));
+            if (nozzles != null) {
+                for (String nozzleInfo : nozzles) {
+                    String[] split = nozzleInfo.split("\\+");
+                    if (gunNo_.equals(split[0])) {
+                        gunNo = split[0]; //枪号
+                        if (gunNo.equals(gunNo_)) {
+                            oils = split[1]; //油品名称
+                            oilGrade = split[2];//油品等级
+                            payShop = split[3];//支付方式
+                            payType = split[4];//加油卡类型
+
+                            if (split.length >= 6) {
+                                iTouchIp = split[5];//ITouch ip 地址,显示将该条数据往哪个ITouch屏发送
+                            }
+                        }
+                    }
+                }
+            }
+
+            resMap.put("gunNo", gunNo);
+            resMap.put("oils", oils);
+            resMap.put("oilGrade", oilGrade);
+            resMap.put("payShop", payShop);
+            resMap.put("payType", payType);
+            resMap.put("stationId", stationId);
+            resMap.put("stationName", stationName);
+            resMap.put("sysDept", sysDept);
+
+
+            resMap.put("iTouchIp", iTouchIp);
+
+            nozzleInfoMap.putAll(resMap);
+            return resMap;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+
+    }
+
+
+    public static void getStationIps() {
+        try {
+            String s = JSONUtils.readJSONFile(SocketFactory.FILEPATH);
+            s = s.trim();
+            JSONObject configure = JSONObject.parseObject(s);
+            JSONArray params = configure.getJSONArray("param");
+            for (Object param : params) {
+                String paramStr = String.valueOf(param);
+                JSONObject configureObject = JSONObject.parseObject(paramStr);
+                ClientFactory clientFactory = new ClientFactory();
+                clientFactoryMap.put(String.valueOf(configureObject.get("ip")), clientFactory);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    private static String DATA = "";
+
+    /**
+     * 将字符串去掉0开头
+     *
+     * @param val 0开头的字符串
+     */
+    public static void splitVal(String val){
+
+        if (val.startsWith("0")){
+            DATA = val.substring(1);
+        }
+        if (DATA.startsWith("0")){
+            splitVal(DATA);
+        }
+
+        //return msg;
+
+    }
+
+
+
+
+
+
+}

+ 3 - 1
middleware-client-jiangxi/src/main/java/com/tokheim/client/socket/SocketListener.java

@@ -2,6 +2,7 @@ package com.tokheim.client.socket;
 
 import com.tokheim.client.manager.AsyncManager;
 import com.tokheim.client.manager.factory.AsyncFactory;
+import com.tokheim.client.manager.factory.SocketFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.ApplicationArguments;
@@ -49,7 +50,8 @@ public class SocketListener implements ApplicationRunner {
         //heartThread.setData(client);
         //heartThread.start();
         String active = env.getProperty("spring.profiles.active");
-        AsyncManager.me().execute(AsyncFactory.sendHeartMsg(host,Integer.valueOf(port),url,filePath,active,iTouchHost,iTouchPort));
+        //AsyncManager.me().execute(AsyncFactory.sendHeartMsg(host,Integer.valueOf(port),url,filePath,active,iTouchHost,iTouchPort));
+        SocketFactory.sendHeartMsg(host,Integer.valueOf(port),url,filePath,active,iTouchHost,iTouchPort);
     }
 
 }

+ 72 - 49
middleware-client-jiangxi/src/main/java/com/tokheim/client/utils/ByteUtils.java

@@ -1,5 +1,7 @@
 package com.tokheim.client.utils;
 
+import lombok.extern.slf4j.Slf4j;
+
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -12,6 +14,7 @@ import java.util.List;
  * @author zjp
  * @date 2019/8/15
  */
+@Slf4j
 public class ByteUtils {
 
     /**
@@ -270,24 +273,30 @@ public class ByteUtils {
      * 如果Hex超过0xFF,显然转换后结果不是一个byte,而是一个byte数组
      */
     public static byte[] hexToByteArray(String inHex) {
-        inHex = inHex.replaceAll("\\s*", ""); //去除空格等字符
-        int hexlen = inHex.length();
-        byte[] result;
-        if (hexlen % 2 == 1) {
-            //奇数
-            hexlen++;
-            result = new byte[(hexlen / 2)];
-            inHex = "0" + inHex;
-        } else {
-            //偶数
-            result = new byte[(hexlen / 2)];
-        }
-        int j = 0;
-        for (int i = 0; i < hexlen; i += 2) {
-            result[j] = hexToByte(inHex.substring(i, i + 2));
-            j++;
+        try {
+            inHex = inHex.replaceAll("\\s*", ""); //去除空格等字符
+            int hexlen = inHex.length();
+            byte[] result;
+            if (hexlen % 2 == 1) {
+                //奇数
+                hexlen++;
+                result = new byte[(hexlen / 2)];
+                inHex = "0" + inHex;
+            } else {
+                //偶数
+                result = new byte[(hexlen / 2)];
+            }
+            int j = 0;
+            for (int i = 0; i < hexlen; i += 2) {
+                result[j] = hexToByte(inHex.substring(i, i + 2));
+                j++;
+            }
+            return result;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
         }
-        return result;
+        return null;
     }
 
 
@@ -320,24 +329,28 @@ public class ByteUtils {
      * @return
      */
     public static String[] bytesToHexStrings(byte[] src) {
-        if (src == null || src.length <= 0) {
-            return null;
-        }
-        String[] str = new String[src.length];
-
-        for (int i = 0; i < src.length; i++) {
-            int v = src[i] & 0xFF;
-            String hv = Integer.toHexString(v);
-			hv = hv.toUpperCase();
-			if (hv.length() < 2) {
-                str[i] = "0" + hv;
-            }else {
-				str[i] = hv;
-			}
-
+        try {
+            if (src == null || src.length <= 0) {
+                return null;
+            }
+            String[] str = new String[src.length];
+
+            for (int i = 0; i < src.length; i++) {
+                int v = src[i] & 0xFF;
+                String hv = Integer.toHexString(v);
+                hv = hv.toUpperCase();
+                if (hv.length() < 2) {
+                    str[i] = "0" + hv;
+                } else {
+                    str[i] = hv;
+                }
+            }
+            return str;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
         }
-
-        return str;
+        return null;
     }
 
 
@@ -348,15 +361,21 @@ public class ByteUtils {
      * @return
      */
     public static String print(String[] infos) {
-        StringBuffer strBuffer = new StringBuffer();
-        for (int i = 0; i < infos.length; i++) {
+        try {
+            StringBuffer strBuffer = new StringBuffer();
+            for (int i = 0; i < infos.length; i++) {
             /*if (i > 0) {
                 //strBuffer.append(" ");
                 strBuffer.append(" ");
             }*/
-            strBuffer.append(infos[i]);
+                strBuffer.append(infos[i]);
+            }
+            return strBuffer.toString();
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
         }
-        return strBuffer.toString();
+        return null;
     }
 
 
@@ -365,28 +384,32 @@ public class ByteUtils {
      * @return: int
      * @description: 按位计算,位值乘权重
      */
-    public static int  hexToDecimal(String hex){
-        int outcome = 0;
-        for(int i = 0; i < hex.length(); i++){
-            char hexChar = hex.charAt(i);
-            outcome = outcome * 16 + charToDecimal(hexChar);
+    public static int hexToDecimal(String hex) {
+        try {
+            int outcome = 0;
+            for (int i = 0; i < hex.length(); i++) {
+                char hexChar = hex.charAt(i);
+                outcome = outcome * 16 + charToDecimal(hexChar);
+            }
+            return outcome;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            e.printStackTrace();
         }
-        return outcome;
+        return 0;
     }
+
     /**
      * @param: [c]
      * @return: int
      * @description:将字符转化为数字
      */
-    public static int charToDecimal(char c){
-        if(c >= 'A' && c <= 'F')
+    public static int charToDecimal(char c) {
+        if (c >= 'A' && c <= 'F')
             return 10 + c - 'A';
         else
             return c - '0';
     }
 
 
-
-
-
 }

+ 3 - 3
middleware-client-jiangxi/src/main/resources/application-dev.yml

@@ -33,9 +33,9 @@ spring:
 # payShop 支付方式  1--公众号 2--微信 3--支付宝 4--银联 5--现金 6--加油卡
 # payType 加油卡类型 0--验泵卡  1--员工卡  2--维修卡  3--用户卡
 socketInfo:
-  host: 192.168.1.10    # 192.168.1.10
-  port: 10002
-  url: http://121.41.120.154/zh-boot/cus/gasRecord/synGasRecord
+  host: 192.168.1.7    # 192.168.1.10
+  port: 10002 # 10002
+  url: http://121.41.120.154/zh-boot/cus/gasRecord/synGasRecord  # 生产ip:121.196.10.232   测试ip:121.41.120.154
   filePath: /app/configure_dev.json # C:/token/info__manager_system/configure_dev.json
 iTouch:
   host: 192.168.1.102

+ 5 - 4
middleware-client-jiangxi/src/main/resources/application-prod.yml

@@ -32,12 +32,13 @@ spring:
 
 
 socketInfo:
-  host: 192.168.1.110
+  host: 192.168.3.25
   port: 10002
-  url: http://121.41.120.154/zh-boot/cus/gasRecord/synGasRecord
+  url: http://121.196.10.232/zh-boot/cus/gasRecord/synGasRecord   # 生产ip:121.196.10.232   测试ip:121.41.120.154
   filePath: /app/configure.json
-
-
+iTouch:
+  host: 192.168.1.102
+  port: 20003
 
 
 

+ 84 - 41
middleware-client-jiangxi/src/main/resources/logback-spring.xml

@@ -1,63 +1,106 @@
-<?xml version="1.0" encoding="UTF-8" ?>
+<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
 
-    <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender">
-        <layout class="ch.qos.logback.classic.PatternLayout">
-            <pattern>
-                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
-            </pattern>
-        </layout>
-    </appender>
+    <!--<springProperty scope="context" name="log.path"
+                    source="logback.log.home" />-->
+    <!-- 日志存放路径 -->
+    <property name="log.path" value="/app_log" />
+    <!-- 日志输出格式 -->
+    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
 
-    <appender name="fileInfoApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <filter class="ch.qos.logback.classic.filter.LevelFilter">
-            <level>ERROR</level>
-            <onMatch>DENY</onMatch>
-            <onMismatch>ACCEPT</onMismatch>
-        </filter>
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
         <encoder>
-            <pattern>
-                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
-            </pattern>
+            <pattern>${log.pattern}</pattern>
         </encoder>
-        <!-- 滚动策略 -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 -->
-            <fileNamePattern>/app_log/middleware-client/app.info.%d.log</fileNamePattern>
-        </rollingPolicy>
     </appender>
 
-    <appender name="fileErrorApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder>
-            <pattern>
-                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
-            </pattern>
-        </encoder>
 
-        <!-- 设置滚动策略 -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 -->
-            <fileNamePattern>/app_log/middleware-client/app.err.%d.log</fileNamePattern>
 
-            <!-- 控制保留的归档文件的最大数量,超出数量就删除旧文件,假设设置每个月滚动,
-            且<maxHistory> 是1,则只保存最近1个月的文件,删除之前的旧文件 -->
-            <MaxHistory>1</MaxHistory>
+    <!--日志分析-->
+    <appender name="fileInfoApp" class="ch.qos.logback.classic.sift.SiftingAppender">
+        <!--discriminator鉴别器,设置运行时动态属性,siftingAppender根据这个属性来输出日志到不同文件 -->
+        <discriminator>
+            <key>msgName</key>
+            <defaultValue>web</defaultValue>
+        </discriminator>
+        <sift>
+            <!--具体的写日志appender,每一个userId创建一个文件-->
+            <appender name="FILE-${msgName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <append>true</append>
+                <encoder>
+                    <pattern>
+                        %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
+                    </pattern>
+                </encoder>
 
-        </rollingPolicy>
-    </appender>
+                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+                    <!--定义文件滚动时的文件名的格式-->
+                    <fileNamePattern>${log.path}/${msgName}/app.info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+                    <maxFileSize>10MB</maxFileSize>
+                    <!--7天的时间周期,日志量最大20GB-->
+                    <maxHistory>7</maxHistory>
+                    <totalSizeCap>10MB</totalSizeCap>
+                    <!--启动清理过期日志-->
+                    <clearHistoryOnStart>true</clearHistoryOnStart>
+                </rollingPolicy>
+
+                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+                    <level>INFO</level>
+                </filter>
 
 
+            </appender>
+        </sift>
+    </appender>
 
+    <!--错误日志-->
+    <appender name="fileErrorApp" class="ch.qos.logback.classic.sift.SiftingAppender">
+        <!--discriminator鉴别器,设置运行时动态属性,siftingAppender根据这个属性来输出日志到不同文件 -->
+        <discriminator>
+            <key>msgName</key>
+            <defaultValue>web</defaultValue>
+        </discriminator>
+        <sift>
+            <!--具体的写日志appender,每一个userId创建一个文件-->
+            <appender name="FILE-${msgName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <append>true</append>
+                <encoder>
+                    <pattern>
+                        %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
+                    </pattern>
+                </encoder>
 
+                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+                    <!--定义文件滚动时的文件名的格式-->
+                    <fileNamePattern>${log.path}/${msgName}/app.error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+                    <maxFileSize>10MB</maxFileSize>
+                    <maxHistory>7</maxHistory>
+                    <totalSizeCap>10MB</totalSizeCap>
+                    <!--启动清理过期日志-->
+                    <clearHistoryOnStart>true</clearHistoryOnStart>
+                </rollingPolicy>
 
+                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+                    <level>ERROR</level>
+                </filter>
 
 
+            </appender>
+        </sift>
+    </appender>
+
+  <!--  <root level="INFO">
+        <appender-ref ref="file_error"/>
+        <appender-ref ref="file_info"/>
+        <appender-ref ref="msg_info"/>
+    </root>
+    -->
     <root level="INFO">
-        <appender-ref ref="consoleApp"/>
         <appender-ref ref="fileInfoApp"/>
+    </root>
+
+    <root level="ERROR">
         <appender-ref ref="fileErrorApp"/>
     </root>
 </configuration>

+ 0 - 1
middleware-client-jiangxi/src/test/java/com/tokheim/client/ClientTest.java

@@ -142,7 +142,6 @@ public class ClientTest {
                 for (int i = 0; i < flag; i++) {
                     time_str.append(time[i + 2] + ":");
                 }
-
             }
             String time_ = time_str.toString();
             if (time_.endsWith(":"))time_ =  time_.substring(0,time_.lastIndexOf(":"));

+ 259 - 0
middleware-client-jiangxi/src/test/java/com/tokheim/client/OilFuelTest.java

@@ -0,0 +1,259 @@
+package com.tokheim.client;
+
+import com.tokheim.client.utils.ByteUtils;
+import com.tokheim.client.utils.PackageUtils;
+import org.apache.commons.lang.ArrayUtils;
+
+import java.util.Arrays;
+
+/**
+ * @author xgm
+ * @version 1.0
+ * @date: Created in 13:56 2021/10/19
+ */
+public class OilFuelTest {
+
+    public static void main(String[] args) {
+      /* String oilHeaderPackage = "02 01 01 00 00 60 00 31 04";
+       String msg = "12 31 39 32 2E 31 36 38 2E 33 2E 31 31 31 3A 39 38 37 39 02 01 01 00 00 60 00 31 04 21 21 37 78 01 02 37 78 05 05 06 00 00 00 00 06 05 06 00 00 00 00 07 04 04 00 07 28 CA 04 20 21 10 19 D5 03 15 47 13 CD 07 0A 00 00 07 12 24 22";
+
+       String msg_sub2 = msg.substring(0,msg.lastIndexOf(oilHeaderPackage)); //将粘包数据根据心跳头截取数据
+       String[] msg_arr2 = msg_sub2.split(" "); //主要是想获取数据长度
+       int length2 = Integer.valueOf(ByteUtils.hexToDecimal(msg_arr2[0]));
+       byte[] bytes2 = ByteUtils.hexToByteArray(msg_sub2); //将16进制的字符创转成字节数组
+       byte[] ipAndPort2 = PackageUtils.getIpAndPort(bytes2, length2);
+       String ipPort2 = new String(ipAndPort2);//将字节转成字符串
+       String  stationIp = ipPort2.substring(0, ipPort2.indexOf(":")); //获取油机ip地址
+       System.out.println(stationIp);*/
+
+
+        //10 31 39 32 2E 31 36 38 2E 31 2E 35 3A 37 36 38 36 02 01 01 00 00 60 00 31 04 21 21 00 13 01 02 00 13 05 05 06 00 00 70 57 06 05 06 00 00 06 41 07 04 04 00 11 01 CA 04 00 00 00 00 D5 03 14 21 27 CD 07 00 13 00 00 00 00 05
+        String oilHeaderPackage = "02 01 01 00 00 60 00 31 04";
+        //byte[] real = {16, 49, 57, 50, 46, 49, 54, 56, 46, 49, 46, 53, 58, 56, 50, 53, 50, 2, 1, 1, 0, 0, 96, 0, 49, 4, 33, 33, 0, 20, 1, 2, 0, 20, 5, 5, 6, 0, 0, 8, -111, 6, 5, 6, 0, 0, 0, -127, 7, 4, 4, 0, 17, 1, -54, 4, 0, 0, 0, 0, -43, 3, 21, 24, 20, -51, 7, 0, 20, 0, 0, 0, 0, 5};
+        String msg_byte = "[16, 49, 57, 50, 46, 49, 54, 56, 46, 49, 46, 53, 58, 56, 50, 53, 50, 2, 1, 1, 0, 0, 96, 0, 49, 4, 33, 33, 0, 20, 1, 2, 0, 20, 5, 5, 6, 0, 0, 8, -111, 6, 5, 6, 0, 0, 0, -127, 7, 4, 4, 0, 17, 1, -54, 4, 0, 0, 0, 0, -43, 3, 21, 24, 20, -51, 7, 0, 20, 0, 0, 0, 0, 5]";
+        String msg = "[10 31 39 32 2E 31 36 38 2E 31 2E 35 3A 37 36 38 36 02 01 01 00 00 60 00 31 04 21 21 00 13 01 02 00 13 05 05 06 00 00 07 57 06 05 06 00 00 00 41 07 04 04 00 11 01 CA 04 00 00 00 00 CD 07 00 13 00 00 00 00 05 D5 03 14 21 27";
+        //String msg = "[10 31 39 32 2E 31 36 38 2E 31 2E 35 3A 37 36 38 36 02 01 01 00 00 60 00 31 04 21 21 00 13 01 02 00 13 06 05 06 00 00 00 41 05 05 06 00 00 07 57 07 04 04 00 11 01 CA 04 00 00 00 00 D5 03 14 21 27 CD 07 00 13 00 00 00 00 05";
+
+        if (msg.contains(oilHeaderPackage)) {
+            msg = msg.substring(msg.indexOf(oilHeaderPackage));
+            System.out.println(msg);
+            String[] arr = msg.split(" ");
+            String[] heart = Arrays.copyOfRange(arr, 0, 9);//交易记录-固定包头(9)
+            System.out.println("包头: " + Arrays.toString(heart));
+
+            /**
+             * 恒山加油机:一个加油点只能有一把或两把枪,两把枪的时候不能两把枪同时加油
+             * 外部枪号就是逻辑枪号,外部枪号用于区分加油点有几把枪(1把或2把枪),外部枪号用于油站人员展示使用,关系不大!
+             * 加油点+内部枪号+外部枪号
+             * 如:1+1+1/1+2+2
+             * 加油点1的第一把枪(内部枪号)   加油点1的第二把枪(内部枪号)
+             *
+             *
+             */
+            String[] gunNo = Arrays.copyOfRange(arr, 9, 10);//枪号(1)
+            for (int i = 0; i < gunNo.length; i++) {
+                System.out.println("枪号: " + gunNo[i]);
+            }
+            String[] fixedVal = Arrays.copyOfRange(arr, 10, 11);//固定值(1)
+            for (int i = 0; i < fixedVal.length; i++) {
+                System.out.println("固定值: " + fixedVal[i]);
+            }
+            String[] serialNum = Arrays.copyOfRange(arr, 11, 13);//交易序列号(2)
+            StringBuffer serialNum_Str = new StringBuffer();
+            for (int i = 0; i < serialNum.length; i++) {
+                serialNum_Str.append(serialNum[i]);
+            }
+            System.out.println("交易序列号: " + serialNum_Str);
+
+            String[] serialNum2 = Arrays.copyOfRange(arr, 13, 17);//交易序列号(4)
+            StringBuffer serialNum2_Str = new StringBuffer();
+            for (int i = 0; i < serialNum2.length; i++) {
+                serialNum2_Str.append(serialNum2[i]);
+            }
+            System.out.println("交易序列号2: " + Arrays.toString(serialNum2));
+
+           // String flag = arr[17];
+            explainData(arr);
+
+
+
+        }
+    }
+
+
+    public static void explainData(String[] arr){
+        String dataFlag = arr[17];
+        switch (dataFlag) {
+            case "05": //金额标识
+                String[] amount = Arrays.copyOfRange(arr, 17, 24);//金额数目(7)
+                StringBuffer amount_int = new StringBuffer();
+                StringBuffer amount_frac = new StringBuffer();
+                if (amount[0].equals("05")) { //05--金额标识
+                    int flag = ByteUtils.hexToDecimal(amount[1]); //代表金额位数,第二个字节为几表示后续的几个字节均为表示金额的数据
+                    int int_part = ByteUtils.hexToDecimal(amount[2])/2; //整数部分占据几位
+                    int frac_part = (flag - 1) - int_part; //小数部分占据几位(去掉标识位数本身一位和整数位数就是小数位数)
+                    for (int i = 1; i <= int_part; i++) {
+                        String flag_00 = amount[i + 2];
+                        if (!flag_00.equals("00")){
+                            amount_int.append(amount[i + 2]);
+                        }
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        amount_frac.append(amount[i + 2 + int_part]);
+                    }
+                }
+
+                String amount_ = amount_int + "." + amount_frac;
+                //判断整数是否是0开头,如果是0开头需要去掉0
+                if (amount_.startsWith("0")) amount_ = amount_.substring(1);
+                if (amount_.startsWith(".")) amount_ = "0" + amount_;
+                System.out.println("金额数目: " +  amount_);
+
+                String[] first = Arrays.copyOfRange(arr, 0, 17);
+                String[] second = Arrays.copyOfRange(arr, 24 , arr.length );
+                arr = (String[]) ArrayUtils.addAll(first, second);
+
+
+                break;
+            case "06": //加油量标识
+
+                String[] rise = Arrays.copyOfRange(arr, 17, 24);//加油量(7)
+                StringBuffer rise_int = new StringBuffer();
+                StringBuffer rise_frac = new StringBuffer();
+                if (rise[0].equals("06")){ //06是加油量标识
+                    int flag = ByteUtils.hexToDecimal(rise[1]);
+                    int int_part = ByteUtils.hexToDecimal(rise[2]) / 2;
+                    int frac_part = (flag - 1) -int_part;
+                    for (int i = 1; i <= int_part ; i++) {
+                        if (!rise[i + 2].equals("00")){
+                            rise_int.append(rise[i + 2]);
+                        }
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        rise_frac.append(rise[i + 2 + int_part]);
+                    }
+                }
+                String rise_ = rise_int+"."+rise_frac;
+                if (rise_.startsWith("0")) rise_ = rise_.substring(1); //若是以0开头需要去掉
+                if (rise_.startsWith(".")) rise_ = "0" + rise_; //若点开头需要在前面添加0
+                System.out.println("加油量: " + rise_);
+
+
+                String[] first_2 = Arrays.copyOfRange(arr, 0, 17);
+                String[] second_2 = Arrays.copyOfRange(arr, 24 , arr.length );
+                arr = (String[]) ArrayUtils.addAll(first_2, second_2);
+
+
+                break;
+            case "07": //单价标识
+
+                String[] price = Arrays.copyOfRange(arr, 17, 23);//单价(6)
+                StringBuffer price_int = new StringBuffer();
+                StringBuffer price_frac = new StringBuffer();
+                if (price[0].equals("07")){ //07标识单价
+                    int flag = ByteUtils.hexToDecimal(price[1]);
+                    int int_part = ByteUtils.hexToDecimal(price[2]) / 2;
+                    int frac_part = (flag - 1) - int_part;
+                    for (int i = 1; i <= int_part; i++) {
+                        if (!price[i + 2].equals("00")){
+                            price_int.append(price[i + 2]);
+                        }
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        price_frac.append(price[i + 2 + int_part]);
+                    }
+                }
+                String price_ = price_int + "." + price_frac;
+                if (price_.startsWith("0")) price_ = price_.substring(1);
+                if (price_.startsWith(".")) price_ = "0" + price_;
+                System.out.println("单价: " + price_);
+
+
+                String[] first_3 = Arrays.copyOfRange(arr, 0, 17);
+                String[] second_3 = Arrays.copyOfRange(arr, 23, arr.length);
+                arr = (String[]) ArrayUtils.addAll(first_3, second_3);
+
+
+                break;
+            case "CA": //日期标识
+                String[] date = Arrays.copyOfRange(arr, 17, 23);//日期(6)
+                StringBuffer date_ = new StringBuffer();
+                if (date[0].equals("CA")){ //日期标识
+                    int flag = ByteUtils.hexToDecimal(date[1]);
+                    for (int i = 0; i < flag; i++) {
+                        date_.append(date[i + 2]);
+                    }
+                }
+                System.out.println("日期: " +date_);
+
+                String[] first_4= Arrays.copyOfRange(arr, 0, 17);
+                String[] second_4 = Arrays.copyOfRange(arr, 23 , arr.length );
+                arr = (String[]) ArrayUtils.addAll(first_4, second_4);
+
+                break;
+            case "D5": //时间标识
+                String[] time = Arrays.copyOfRange(arr, 17, 22);//时间(5)
+                StringBuffer time_str = new StringBuffer();
+                if (time[0].equals("D5")){
+                    int flag = ByteUtils.hexToDecimal(time[1]);
+                    for (int i = 0; i < flag; i++) {
+                        time_str.append(time[i + 2] + ":");
+                    }
+                }
+                String time_ = time_str.toString();
+                if (time_.endsWith(":"))time_ =  time_.substring(0,time_.lastIndexOf(":"));
+                System.out.println("时间: " + time_);
+
+
+                String[] first_5 =Arrays.copyOfRange(arr, 0, 17);
+                String[] second_5 = Arrays.copyOfRange(arr, 22 , arr.length );
+                arr = (String[]) ArrayUtils.addAll(first_5, second_5);
+                break;
+            case "CD": //泵码标识
+
+                String[] pump = Arrays.copyOfRange(arr, 17, 26);//泵码(9)
+                StringBuffer pump_int = new StringBuffer();
+                StringBuffer pump_frac = new StringBuffer();
+                if (pump[0].equals("CD")){ //CD 泵码标识
+                    int flag = ByteUtils.hexToDecimal(pump[1]);
+                    int int_part = ByteUtils.hexToDecimal(pump[2]) / 2;
+                    int frac_part = (flag - 1) - int_part;
+                    for (int i = 1; i <= int_part; i++) {
+                        if (!pump[i + 2].equals("00")){
+                            pump_int.append(pump[i + 2]);
+                        }
+
+                    }
+                    for (int i = 1; i <= frac_part; i++) {
+                        pump_frac.append(pump[i + 2 + int_part]);
+                    }
+                }
+                String pump_ = pump_int + "."+pump_frac;
+                if (pump_.startsWith("0")) pump_ = pump_.substring(1);
+                if (pump_.startsWith(".")) pump_ = "0" + pump_;
+                System.out.println("泵码: " + pump_);
+
+                String[] first_6 =Arrays.copyOfRange(arr, 0, 17);
+                String[] second_6 = Arrays.copyOfRange(arr, 26 , arr.length );
+                arr = (String[]) ArrayUtils.addAll(first_6, second_6);
+
+                break;
+            default:
+                break;
+        }
+
+        String valFlag = "";
+         try {
+              valFlag = arr[17];
+              }catch (Exception e){
+                // e.printStackTrace();
+                 return;
+             }
+
+        if (valFlag.equals("05") || valFlag.equals("06") || valFlag.equals("07") || valFlag.equals("CA") || valFlag.equals("D5") || valFlag.equals("CD")){
+            explainData(arr);
+        }
+
+    }
+
+}