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;
}
}