package com.yuanchu.mom.utils; import cn.hutool.core.io.IORuntimeException; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.yuanchu.mom.exception.ErrorException; import com.yuanchu.mom.pojo.DataConfig; import com.yuanchu.mom.pojo.Device; import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; public class DataAcquisition { private static final String HTTP = "http://"; private static final String GETFILE = ":9527/lims/getFile"; // 获取文件接口 private static final String MOVEFILE = ":9527/lims/moveFile"; // 文件移动地址 private static final String splitIdentifier = "@-@"; // 自定义唯一标识分割符 public static final String frequency = "frequency"; /** * 数采入口 * * @param dataConfig * @param device * @return */ public static Map dataAcquisitionEntrance(List dataConfig, Device device, String entrustCode, String sampleCode, String ip) { String http = HTTP + ip + GETFILE + "?filePath=" + device.getCollectUrl() + "&fileExtension=" + device.getFileType() + "&entrustCode=" + entrustCode + "&sampleCode=" + sampleCode; String result = null; try { result = HttpUtil.get(http); } catch (IORuntimeException e) { throw new ErrorException("所在电脑未安装或未启动:LIMS文件采集器!"); } JSONObject jsonObject = JSON.parseObject(result); if (Objects.equals(jsonObject.get("code"), 1)) { if (ObjectUtils.isEmpty(jsonObject.get("msg"))) { throw new ErrorException("未查询到数据,可能文件路径配置错误!"); } else { System.out.println(jsonObject); throw new ErrorException("未知错误,请联系管理员!"); } } else { String data = jsonObject.get("data").toString(); // 考虑到一个检测项可能会存在多个数采配置,所以需要进行分组 Map> userMap = dataConfig.stream() .peek(i -> i.setInsProductItem( i.getInspectionItem().equals(i.getInspectionItemSubclass()) ? i.getInspectionItem() + "," : i.getInspectionItem() + "," + i.getInspectionItemSubclass() )) .collect(Collectors.groupingBy(DataConfig::getInsProductItem)); Map map; switch (device.getFileType()) { case ".docx": map = analysisString(data, userMap); break; case ".xlsx": map = analysisList(data, userMap); break; case ".txt": map = analysisTxt(data, userMap); break; case ".csv": map = analysisList(data, userMap); break; case ".mdb": map = analysisMdb(data, userMap, entrustCode, sampleCode); break; case ".db": map = analysisDb(data, userMap, entrustCode, sampleCode); break; case ".png": map = readPngString(data, userMap); break; default: map = null; break; } // 如果存在存储地址,则移动地址 if (ObjectUtils.isNotEmpty(device.getStorageUrl())) { String s = HTTP + ip + MOVEFILE + "?startFilePath=" + device.getCollectUrl() + "&endFilePath=" + device.getStorageUrl() + "&fileType=" + device.getFileType(); String storageUrlResult = HttpUtil.get(s); JSONObject storageUrlResultJson = JSON.parseObject(storageUrlResult); } return map; } } public static String createFrequency(String entrustCode, String sampleCode) { String key = frequency + ":" + entrustCode + ":" + sampleCode; boolean b = RedisUtil.hasKey(key); String frequencyValue; if (b) { long incr = RedisUtil.incr(key, 1); frequencyValue = String.valueOf(incr); } else { RedisUtil.set(key, 1); frequencyValue = "1"; } return frequencyValue; } /** * 需要通过X,Y轴定位 * * @param data * @param dataConfig * @return */ private static Map analysisDb(String data, Map> dataConfig, String entrustCode, String sampleCode) { JSONObject jsonObject = JSON.parseObject(data); JSONArray dataList = JSONArray.parseArray(jsonObject.get("data").toString()); Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { List list = new ArrayList<>(); for (int config = 0; config < v.size(); config++) { String referx = getRefer(v.get(config).getReferx()); for (int i = 0; i < dataList.size(); i++) { JSONObject jsonObject1 = JSON.parseObject(dataList.get(i).toString()); if (entrustCode.equals(jsonObject1.get("ExtInfo_Value1"))) { Object o = jsonObject1.get(referx); if (ObjectUtils.isNotEmpty(o)) { list.add(o); } } } } // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } /** * 需要通过X,Y轴定位 * * @param data * @param dataConfig * @return */ private static Map analysisMdb(String data, Map> dataConfig, String entrustCode, String sampleCode) { JSONObject jsonObject = JSON.parseObject(data); JSONArray dataList = JSONArray.parseArray(jsonObject.get("data").toString()); Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { List list = new ArrayList<>(); for (int config = 0; config < v.size(); config++) { String referx = getRefer(v.get(config).getReferx()); for (int i = 0; i < dataList.size(); i++) { JSONObject jsonObject1 = JSON.parseObject(dataList.get(i).toString()); if (entrustCode.equals(jsonObject1.get("OrderNumber")) && sampleCode.equals(jsonObject1.get("SampleNumber"))) { Object o = jsonObject1.get(referx); if (ObjectUtils.isNotEmpty(o)) { list.add(o); } } } } // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } private static Pattern SPATTERN = Pattern.compile("([-+])?\\d+(\\.\\d+)?"); /** * 只需X轴 * * @param data 采集到的文件字符串 * @param dataConfig 用户配置好的x,y轴定位数据与参照物 * @return */ private static Map readPngString(String data, Map> dataConfig) { Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { List list = new ArrayList<>(); for (int config = 0; config < v.size(); config++) { String referx = getRefer(v.get(config).getReferx()); String result = null; // 通过\n将字符串分割为行 String[] aColumnY = data.split("\n"); List list1 = new ArrayList<>(); // 该循环得出用户配置的y轴 for (int i = 0; i < aColumnY.length; i++) { String addDataWithSpaces = referx.replaceAll("", " "); int x = getXOrY(v.get(config).getX(), k, "X"); if (aColumnY[i].contains(addDataWithSpaces)) { Matcher matcher = SPATTERN.matcher(aColumnY[i]); while (matcher.find()) { String group = matcher.group(); list1.add(group); } } if (ObjectUtils.isNotEmpty(list1)) { result = list1.get(x); } } if (ObjectUtils.isNotEmpty(result)) { list.add(result); } } // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } /** * 从文件中提取出来的文字,如果有公式,进行公式计算,否则取列表第一个值 * * @param list 提取出的数字 * @param dataConfig 存储公式的对象 * @return */ private static String calculationFormula(List list, DataConfig dataConfig, String insProductItem) { if (list.size() == 0) { return null; } // 如果不为空,进行公式计算 if (ObjectUtils.isNotEmpty(dataConfig.getFormula())) { return null; // 否则:没有公式代表不需要计算,直接提取List里面的数据 } else { // 这里只会取列表第一个数据 if (list.size() > 1) { throw new ErrorException("未给:" + insProductItem + " 配置公式,可是却采集到了" + list.size() + "个值!分别为:" + list); } else { return list.get(0).toString(); } } } /** * 解析String数据 * * @param data 采集到的文件字符串 * @param dataConfig 用户配置好的x,y轴定位数据与参照物 * @return */ private static Map analysisTxt(String data, Map> dataConfig) { Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { List list = analyzeData(data, v, k, ","); // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } /** * @param data 采集到的文件字符串 * @param dataConfig 用户配置好的x,y轴定位数据与参照物 * @return */ private static Map analysisString(String data, Map> dataConfig) { String processingDataAfterSpaces = data .replaceAll(" +", splitIdentifier) .replaceAll("\r", "") .replaceAll(" ", ""); Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { List list = analyzeData(processingDataAfterSpaces, v, k, splitIdentifier); // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } /** * 取X,Y两个定位 * * @param data 采集到的文件字符串 * @param dataConfig 用户配置好的x,y轴定位数据与参照物 * @return */ public static Map analysisList(String data, Map> dataConfig) { Map map = new HashMap<>(); dataConfig.forEach((k, v) -> { // 用户可能给一个子项目配置了多个配置,即一个项目取多个值,所以需要循环 List list = analyzeData(data, v, k, splitIdentifier); // 进行公式计算 String resultValue = calculationFormula(list, v.get(0), k); map.put(k, resultValue); }); return map; } // 由于在方法中会大量的判断,所以做一个方法 private static int getXOrY(String value, String k, String tips) { try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new ErrorException(k + ":未配置" + tips + "坐标轴的值!"); } } // 防止参照物为空报错,进行判断如果为空赋值空字符 private static String getRefer(String refer) { return ObjectUtils.isNotEmpty(refer) ? refer.replaceAll(" ", "") : ""; } public static List analyzeData(String data, List v, String k, String split) { List list = new ArrayList<>(); for (int config = 0; config < v.size(); config++) { // 取两个用户配置的参照物 String referx = getRefer(v.get(config).getReferx()); String refery = getRefer(v.get(config).getRefery()); // 最终结果 String result = null; // 通过\n将字符串分割为行 String[] aColumnY = data.replaceAll(" ", "").split("\n"); Integer end = null; // 采集数据:Y轴 for (int i = 0; i < aColumnY.length; i++) { // 取x的值,防止报错 int x = getXOrY(v.get(config).getX(), k, "X"); // 如果Y与X用户都配置了则执行 if (ObjectUtils.isNotEmpty(refery)) { // 取Y坐标值 int y = getXOrY(v.get(config).getY(), k, "Y"); // 缓存Y的结束值 if (ObjectUtils.isEmpty(end) && aColumnY[i].contains(refery)) { end = i + y; } // 判断是否在参照物为起到,Y坐标值为最终范围 if (ObjectUtils.isNotEmpty(end) && i <= end) { String[] aLineX = aColumnY[i].split(split); for (int j = 0; j < aLineX.length; j++) { if (aLineX[j].contains(referx)) { try { result = aLineX[j + x]; } catch (Exception e) { throw new ErrorException(k + ":X轴定位超出!"); } break; } } } // 如果只配置了X,则执行下面的代码 } else if (aColumnY[i].contains(referx) && ObjectUtils.isEmpty(refery)) { String[] aLineX = aColumnY[i].split(split); for (int j = 0; j < aLineX.length; j++) { if (aLineX[j].contains(referx)) { try { result = aLineX[j + x]; } catch (Exception e) { throw new ErrorException(k + ":X轴定位超出!"); } } } } } // 防止计算公式的时候出现:[null] 这种数据 if (ObjectUtils.isNotEmpty(result)) { String formatProcessing = getFormatProcessing(result); list.add(formatProcessing); } } return list; } public static String getFormatProcessing(String value) { value = value.replaceAll("%", ""); if(value.contains("=")){ String[] split = value.split("="); return split[split.length - 1]; } else if(value.contains(":")) { String[] split = value.split(":"); return split[split.length - 1]; } else { return value; } } public static String getIp(HttpServletRequest request) { String ipAddress = request.getRemoteAddr(); // 防止回环地址变为IPv6 return ipAddress.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ipAddress; } }