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; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.*; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author xgm * @version 1.0 * @date: Created in 9:42 2021/9/26 *

* 多台ITouch操作 */ @Slf4j 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; private String msg; private static List nozzles = new ArrayList<>(); private static List nozzles2 = new ArrayList<>(); private static String header = "02 01 01 00 02 60 00 09 02"; //枪配置信息头 //private static String heartHeaderPackage = "02 01 01 00 02 60 00 0B 01"; //心跳头 //private static String realTimePackage = "02 01 01 00 00 60 00 16 01"; //实时加油数据头 //private static String oilHeaderPackage = "02 01 01 00 00 60 00 31 04";//加油交易记录头 //private static String speechHeaderPackage = "02 01 01 00 00 60 00 08 01";//语音数据头 private static boolean flag = true; public static Set iTouchIps = new HashSet<>(); private static Map socketMap = new HashMap<>(); private static Map flagMap = new HashMap<>(); //private static TwoKeyMap socketTwoKeyMap = new TwoKeyMap<>(); // private static MultiValueMap nozzleMap = new LinkedMultiValueMap<>(); 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"); //模拟错误信息 //nozzles2.add("103139322E3136382E312E353A3939313202010100006000080121140104150101103139322E3136382E312E353A3939313202010100006000080124140106150101103139322E3136382E312E353A3939313202010100006000080121140106150101103139322E3136382E312E353A3939313202010100006000080124140108150101103139322E3136382E312E353A3939313202010100006000080121140108150101103139322E3136382E312E353A39393132020101000260000B0100FF0720200928174252103139322E3136382E312E353A39393132020101000060001601242205060000064023050600000080240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000064023050600000080240404000800000000000000103139322E3136382E312E353A39393132020101000060001601242205060000116823050600000146240404000800000000000000103139322E3136382E312E353A39393132020101000060001601212205060000116823050600000146240404000800000000000000103139322E3136382E312E353A39393132020101000060001601242205060000170423050600000213240404000800000000000000103139322E3136382E312E353A393931320201010000600016012122050600001704230506000002132404040008"); //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()) { getConfigure(stationIp); }*/ iTouchIps.clear(); getConfigure(stationIp); this.iTouchPort = iTouchPort; this.msg = msg; //获取ITouch多媒体屏ip recursionMsg(msg); //枪信息 sendData(msg); } catch (Exception e) { log.error("配置文件获取失败--" + e.getMessage()); e.printStackTrace(); } } /** * 油枪信息截取 * * @param msg 多条油枪组成16进制字符串 */ public void recursionMsg(String msg) { if (msg.contains(header)) { String msg_front = msg.substring(msg.indexOf(header)); //截取第一条枪配置信息 String msg_end = msg_front.substring(50); String nozzleInfo = msg_front.substring(0, 50); if (!nozzles.contains(nozzleInfo)) { nozzles.add(nozzleInfo); } if (msg_end.contains(header)) { recursionMsg(msg_end); } } } /** * 判断后发送数据到多媒体屏app * * @param msg 16进制字符串 */ public void sendData(String msg) { for (String iTouchIp : iTouchIps) { Socket socket = socketMap.get(iTouchIp); if (socket == null) { executorService.submit(new Runnable() { @Override public void run() { send(iTouchIp); } }); /*new Thread(new Runnable() { @Override public void run() { send(iTouchIp); } }).start();*/ } else { //正常传输数据 send(iTouchIp); } } } /* public void sendDataToITouch(String iTouchIp) { try { //TODO 将发送数据根据油枪号进行过滤发送 if (msg.contains(realTimePackage)){ //实时加油 //System.err.println("加油实时数据:" + msg); String substring = msg.substring(msg.indexOf(realTimePackage)); String[] arrData = substring.split(" "); String[] gunNoArr = Arrays.copyOfRange(arrData, 9, 10);//枪号(1) String gunNo = ""; for (int i = 0; i < gunNoArr.length; i++) { gunNo = String.valueOf(ByteUtils.hexToDecimal(gunNoArr[i]) - ByteUtils.hexToDecimal("20"));; } if (nozzleMap.containsKey(iTouchIp)){ List stringList = nozzleMap.get(iTouchIp); for (String nozzleNo : stringList) { if (nozzleNo.equals(gunNo)){ System.err.println(iTouchIp + "--加油实时数据:" + msg); send(iTouchIp); } } } } if (msg.contains(oilHeaderPackage)){ String substring = msg.substring(msg.indexOf(oilHeaderPackage)); String[] arrData = substring.split(" "); String[] gunNoArr = Arrays.copyOfRange(arrData, 9, 10);//枪号(1) String gunNo = ""; for (int i = 0; i < gunNoArr.length; i++) { gunNo = String.valueOf(ByteUtils.hexToDecimal(gunNoArr[i]) - ByteUtils.hexToDecimal("20"));; } if (nozzleMap.containsKey(iTouchIp)){ List stringList = nozzleMap.get(iTouchIp); for (String nozzleNo : stringList) { if (nozzleNo.equals(gunNo)){ System.err.println(iTouchIp + "--加油记录数据:" + msg); send(iTouchIp); } } } } if (msg.contains(speechHeaderPackage)){ String substring = msg.substring(msg.indexOf(speechHeaderPackage)); String[] arrData = substring.split(" "); String[] gunNoArr = Arrays.copyOfRange(arrData, 9, 10);//枪号(1) String gunNo = ""; for (int i = 0; i < gunNoArr.length; i++) { gunNo = String.valueOf(ByteUtils.hexToDecimal(gunNoArr[i]) - ByteUtils.hexToDecimal("20"));; } if (nozzleMap.containsKey(iTouchIp)){ List stringList = nozzleMap.get(iTouchIp); for (String nozzleNo : stringList) { if (nozzleNo.equals(gunNo)){ System.err.println(iTouchIp + "--语音数据:" + msg); send(iTouchIp); } } } } send(iTouchIp); } catch (Exception e) { e.printStackTrace(); } }*/ /** * 发送数据到多媒体屏app * * @param iTouchIp 多媒体app的Ip地址 */ public void send(String iTouchIp) { try { Socket socket = socketMap.get(iTouchIp); if (socket == null) { socketMap.remove(iTouchIp); socket = new Socket(); socket.connect(new InetSocketAddress(iTouchIp, Integer.valueOf(iTouchPort)), 2000);//超时时间为2秒 socketMap.put(iTouchIp, socket); flagMap.put(iTouchIp, true); } if (socket.isClosed()) { socketMap.remove(iTouchIp); socket = new Socket(); socket.connect(new InetSocketAddress(iTouchIp, Integer.valueOf(iTouchPort)), 2000);//超时时间为2秒 socketMap.put(iTouchIp, socket); flagMap.put(iTouchIp, true); System.out.println(iTouchIp + "--socket 关闭..."); log.info(iTouchIp + "--socket 关闭..."); } Socket socketNew = socketMap.get(iTouchIp); if (socket.isConnected()) { OutputStream out = socketNew.getOutputStream(); if (flag) sendHeartedData(iTouchIp); reData(iTouchIp); sendNozzleInfo(iTouchIp); //sendNozzleInfo2(iTouchIp); //if (msg.contains("01 01 02 01 00 40 00 13 01")) //System.err.println(iTouchIp + "--发送数据:" + msg); byte[] bytes = ByteUtils.hexToByteArray(msg); out.write(bytes); out.flush(); } else { System.out.println(iTouchIp + "--socket服务端未启动......"); log.info(iTouchIp + "--socket服务端未启动......"); restartSocket(iTouchIp); } } catch (IOException e) { e.printStackTrace(); if (e instanceof SocketTimeoutException) { System.err.println(iTouchIp + "--连接超时,正在重连...."); log.error(iTouchIp + "--连接超时,正在重连...."); startSocket(iTouchIp); } else if (e instanceof NoRouteToHostException) { System.err.println(iTouchIp + "--该地址不存在,请检查......"); log.error(iTouchIp + "--该地址不存在,请检查......"); stopSocket(iTouchIp); } else if (e instanceof ConnectException) { System.err.println(iTouchIp + "--连接异常或被拒绝,请检查....."); log.error(iTouchIp + "--连接异常或被拒绝,请检查....."); stopSocket(iTouchIp); } else if (e instanceof SocketException) { System.out.println(iTouchIp + "--服务端关闭,客户端关闭后重启......"); log.error(iTouchIp + "--服务端关闭,客户端关闭后重启......"); //stopSocket(); restartSocket(iTouchIp); } } } /** * 重连多媒体app * * @param iTouchIp 多媒体app的Ip地址 */ public void restartSocket(String iTouchIp) { try { Socket socket = socketMap.get(iTouchIp); flagMap.put(iTouchIp, false); //每隔间2s向服务器请求一次以此检查服务器是否已经起来 Thread.sleep(2000); log.info(iTouchIp + "--重连(ITouch)socket......."); System.out.println(iTouchIp + "--重连(ITouch)socket......."); if (socket == null) { socket = new Socket(); socket.connect(new InetSocketAddress(iTouchIp, Integer.valueOf(iTouchPort)), 2000);//超时时间为2秒 socketMap.put(iTouchIp, socket); flagMap.put(iTouchIp, true); } else { socket.close(); } } catch (Exception e) { e.printStackTrace(); } finally { Socket socket = socketMap.get(iTouchIp); if (socket == null) { restartSocket(iTouchIp); } } } /** * 监听多媒体app初始化是是否已启动 * * @param iTouchIp 多媒体app的Ip地址 */ public void startSocket(String iTouchIp) { try { Socket socket = socketMap.get(iTouchIp); Thread.sleep(2000); //每隔两秒重新连接一次 log.info(iTouchIp + "--两秒后重新链接...."); System.out.println(iTouchIp + "--两秒后重新链接...."); //创建socket客户端 socket = new Socket(); socket.connect(new InetSocketAddress(iTouchIp, Integer.valueOf(iTouchPort)), 2000);//超时时间为2秒 flagMap.put(iTouchIp, true); sendData(msg); } catch (Exception e) { e.printStackTrace(); if (e instanceof SocketTimeoutException) { socketMap.remove(iTouchIp); startSocket(iTouchIp); } } } /** * 停止与多媒体app连接 * * @param iTouchIp 多媒体app的Ip地址 */ public void stopSocket(String iTouchIp) { try { Socket socket = socketMap.get(iTouchIp); flagMap.put(iTouchIp, false); socket.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 发送心跳到多媒体app * * @param iTouchIp 多媒体app的Ip地址 */ public void sendHeartedData(String iTouchIp) { /*new Thread(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); } } } }).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() { @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 { 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(); } } }); } /** *发送油枪信息到多媒体app * * @param iTouchIp 多媒体app的Ip地址 */ public void sendNozzleInfo(String iTouchIp) { /* new Thread(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(); } } }).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) { executorService.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 : nozzles2) { System.err.println(iTouchIp + "--发送模拟信息--" + nozzle); //log.info(iTouchIp + "--发送模拟信息--" + nozzle); byte[] byteInfo = ByteUtils.hexToByteArray(nozzle); out.write(byteInfo); out.flush(); } *//*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(); } } }); *//*new Thread(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 : nozzles2) { System.err.println(iTouchIp + "--发送模拟信息--" + nozzle); //log.info(iTouchIp + "--发送模拟信息--" + nozzle); byte[] byteInfo = ByteUtils.hexToByteArray(nozzle); out.write(byteInfo); out.flush(); } *//**//*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(); } } }).start();*//* }*/ /** * 获取配置文件汇总多媒体信息 * * @param stationIp 油机Ip地址 * @return */ public boolean getConfigure(String stationIp) { try { String s = JSONUtils.readJSONFile(SocketFactory.FILEPATH); s = s.trim(); JSONObject configure = JSONObject.parseObject(s); JSONArray params = configure.getJSONArray("param"); String[] nozzles = null; String ip = ""; 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")); nozzles = nozzle.split(","); } } if (nozzles != null) { for (String nozzleInfo : nozzles) { String[] split = nozzleInfo.split("\\+"); //Nozzle nozzle = new Nozzle(); //nozzle.setGunNo(split[0]); //枪号 //nozzle.setOils(split[1]); //油品名称 //nozzle.setOilGrade(split[2]); //油品等级 //nozzle.setPayShop(split[3]); //支付方式 //nozzle.setPayType(split[4]); //加油卡类型 if (split.length >= 6) { //nozzle.setiTouchIp(split[5]); //ITouch ip 地址,显示将该条数据往哪个ITouch屏发送 iTouchHost = split[5]; iTouchIps.add(iTouchHost); //nozzleMap.add(split[5],split[0]); } } } return true; } catch (Exception e) { e.printStackTrace(); } return false; } }