|
@@ -0,0 +1,721 @@
|
|
|
+package com.jiayue.insu.incloud.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.jiayue.insu.incloud.constants.CommonStant;
|
|
|
+import com.jiayue.insu.incloud.constants.enums.StatusEnum;
|
|
|
+import com.jiayue.insu.incloud.constants.vo.FileCreateLog;
|
|
|
+import com.jiayue.insu.incloud.entity.Record;
|
|
|
+import com.jiayue.insu.incloud.entity.Station;
|
|
|
+import com.jiayue.insu.incloud.service.ApiService;
|
|
|
+import com.jiayue.insu.incloud.service.RecordService;
|
|
|
+import com.jiayue.insu.incloud.service.StationService;
|
|
|
+import com.jiayue.insu.incloud.utils.JsonResultUtil;
|
|
|
+import com.jiayue.insu.incloud.utils.SystermUtils;
|
|
|
+import com.jiayue.insu.minio.util.MinioUtilService;
|
|
|
+import io.jsonwebtoken.JwtBuilder;
|
|
|
+import io.jsonwebtoken.Jwts;
|
|
|
+import io.jsonwebtoken.SignatureAlgorithm;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.velocity.Template;
|
|
|
+import org.apache.velocity.VelocityContext;
|
|
|
+import org.apache.velocity.app.VelocityEngine;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.DigestUtils;
|
|
|
+import java.io.*;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 预测数据业务实现
|
|
|
+ *
|
|
|
+ * @author yh
|
|
|
+ * @version 1.0
|
|
|
+ * @since 2022/5/22 11:29
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class ApiServiceImpl implements ApiService {
|
|
|
+
|
|
|
+ @Value("${minio.pull.url}")
|
|
|
+ String url;
|
|
|
+ @Value("${minio.pull.fileurl}")
|
|
|
+ String fileurl;
|
|
|
+ @Value("${minio.fileurl}")
|
|
|
+ String fileDir;
|
|
|
+ @Value("${minio.bucketname}")
|
|
|
+ private String bucketName;
|
|
|
+ @Value("${minio.pull.cloudFileCreateLog}")
|
|
|
+ private String cloudFileCreateLog;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ RedisTemplate redisTemplate;
|
|
|
+ @Autowired
|
|
|
+ private StationService stationService;
|
|
|
+ @Autowired
|
|
|
+ private VelocityEngine velocityEngine;
|
|
|
+ @Autowired
|
|
|
+ private MinioUtilService minioUtilService;
|
|
|
+ @Autowired
|
|
|
+ public RecordService recordService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取token
|
|
|
+ *
|
|
|
+ * @param userInfo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject getToken(JSONObject userInfo) {
|
|
|
+ JSONObject result;
|
|
|
+ //获取用户名密码
|
|
|
+ String requestUserName = userInfo.getStr(CommonStant.REQUEST_USER_NAME);
|
|
|
+ String requestUserPass = userInfo.getStr(CommonStant.REQUEST_USER_PASS);
|
|
|
+ // 获取用户列表
|
|
|
+ Map<String, String> userMap = redisTemplate.opsForHash().entries(CommonStant.REDIS_USERS);
|
|
|
+ // 如果用户列表为空,返回失败
|
|
|
+ if (userMap == null) {
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ // 根据用户名获取密码
|
|
|
+ String password = userMap.get(requestUserName);
|
|
|
+ // 如果密码为空
|
|
|
+ if (password == null) {
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ // 加密后的密码
|
|
|
+ String passwordMD5t = DigestUtils.md5DigestAsHex(password.getBytes()).toUpperCase();
|
|
|
+ // 如果密码匹配成功
|
|
|
+ if (passwordMD5t.equals(requestUserPass)) {
|
|
|
+ // 拼接kdy名 例如:integration:cloud:userToken:user1
|
|
|
+ String key = CommonStant.REDIS_USER_TOKEN + CommonStant.CHARACTER_COLON + requestUserName;
|
|
|
+ String token = String.valueOf(redisTemplate.opsForValue().get(key));
|
|
|
+ // 如果token存在并且时间大于1小时,则不再生成新token
|
|
|
+ if (token != null && !"".equals(token) && !"null".equals(token)) {
|
|
|
+ // 获取剩余时间
|
|
|
+ long timeout = redisTemplate.opsForValue().getOperations().getExpire(key);
|
|
|
+ // 如果剩余时间>1小时,返回redis中存储的token,否则生成新token
|
|
|
+ if (timeout > 360) {
|
|
|
+ result = JsonResultUtil.success();
|
|
|
+ result.set("token", token);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 生成token
|
|
|
+ JwtBuilder builder = Jwts.builder()
|
|
|
+ .setSubject(requestUserName)
|
|
|
+ //用于设置签发时间
|
|
|
+ .setIssuedAt(new Date())
|
|
|
+ //用于设置签名秘钥
|
|
|
+ .signWith(SignatureAlgorithm.HS256, requestUserPass);
|
|
|
+ // 获取token
|
|
|
+ token = builder.compact();
|
|
|
+ result = JsonResultUtil.success();
|
|
|
+ result.set(CommonStant.TOKEN, token);
|
|
|
+ // 成功生成token后,将toke存入redis 有效期24小时
|
|
|
+ redisTemplate.opsForValue().set(key, token, 24, TimeUnit.HOURS);
|
|
|
+ // 返回结果
|
|
|
+ return result;
|
|
|
+ } else {
|
|
|
+ log.info("用户不存在或密码错误");
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从minIo上获取短期文件并解析返回json格式
|
|
|
+ *
|
|
|
+ * @param requestJson
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject getShortWpfData(JSONObject requestJson) {
|
|
|
+ JSONObject result;
|
|
|
+ String stationCode = requestJson.getStr("wfId");
|
|
|
+ // 根据场站编号查询场站信息
|
|
|
+ Station station = stationService.findByStationCode(stationCode);
|
|
|
+ // 从minIo获取文件
|
|
|
+ File file = downLoadFileFromMinIo(station, "dq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"));
|
|
|
+ //解析短期文件
|
|
|
+ result = fileAnalysis(file, station, "dq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"));
|
|
|
+ // 如果解析完的短期文件列表为空
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收修正短期数据
|
|
|
+ *
|
|
|
+ * @param requestJson
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject putShortWpfData(JSONObject requestJson) {
|
|
|
+ // 根据场站编号查询场站信息
|
|
|
+ Station station = stationService.findByStationCode(requestJson.getStr("wfId"));
|
|
|
+ // 文件生成时间
|
|
|
+ String recDate = requestJson.getStr("recDate");
|
|
|
+ // 功率json
|
|
|
+ JSONObject values = JSONUtil.parseObj(requestJson.getJSONArray("values").get(0));
|
|
|
+ // 明日修正后数据Arr
|
|
|
+ JSONArray datas = values.getJSONArray("datas");
|
|
|
+ // 将json数据转化为ListMap
|
|
|
+ List<Map<String, Object>> dqListMap = getDqListMap(station,datas, station.getName());
|
|
|
+ // 短期文件模板
|
|
|
+ String vmsPath = SystermUtils.getResourceBasePath() + "/vms/DQ.vm";
|
|
|
+ // 生成dq文件
|
|
|
+ JSONObject result = genFile(station, dqListMap, vmsPath);
|
|
|
+ if(JsonResultUtil.Type.failure.value().equals(result.get(JsonResultUtil.CODE_TAG))){
|
|
|
+ Record record = new Record(CommonStant.RECORD_TYPE_PUSH_CORRECT_TO_MIN_IO,"CSGS",requestJson.getStr("wfId"),null,LocalDateTime.now(),LocalDateTime.now(),JsonResultUtil.Type.failure.msg(),JsonResultUtil.Type.failure.value());
|
|
|
+ recordService.save(record);
|
|
|
+ }
|
|
|
+ return JsonResultUtil.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从minIo上获取超短期文件并解析返回json格式
|
|
|
+ *
|
|
|
+ * @param requestJson
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject getSShortWpfData(JSONObject requestJson) {
|
|
|
+ JSONObject result;
|
|
|
+ String stationCode = requestJson.getStr("wfId");
|
|
|
+ // 根据场站编号查询场站信息
|
|
|
+ Station station = stationService.findByStationCode(stationCode);
|
|
|
+ // 从minIo下载文件
|
|
|
+ File file = downLoadFileFromMinIo(station, "cdq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"));
|
|
|
+ //解析短期文件
|
|
|
+ result = fileAnalysis(file, station, "cdq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收修正超短期数据
|
|
|
+ *
|
|
|
+ * @param requestJson
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JSONObject putSShortWpfData(JSONObject requestJson) {
|
|
|
+ // 根据场站编号查询场站信息
|
|
|
+ Station station = stationService.findByStationCode(requestJson.getStr("wfId"));
|
|
|
+ // 功率json
|
|
|
+ JSONObject values = JSONUtil.parseObj(requestJson.getJSONArray("values").get(0));
|
|
|
+ // 文件生成时间
|
|
|
+ String recDate = requestJson.getStr("recDate");
|
|
|
+ // 所有日期的数据Arr
|
|
|
+ JSONArray datas = values.getJSONArray("datas");
|
|
|
+ // 将json数据转化为ListMap
|
|
|
+ List<Map<String, Object>> dqListMap = getDqListMap(station,datas, station.getName());
|
|
|
+ // 短期文件模板
|
|
|
+ String vmsPath = SystermUtils.getResourceBasePath() + "/vms/DQ.vm";
|
|
|
+ // 生成dq文件
|
|
|
+ genFile(station, dqListMap, vmsPath);
|
|
|
+ return JsonResultUtil.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析短期文件
|
|
|
+ *
|
|
|
+ * @param dqFile
|
|
|
+ * @param station
|
|
|
+ * @param startDate
|
|
|
+ * @param endDate
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public JSONObject fileAnalysis(File dqFile, Station station, String type, String startDate, String endDate) {
|
|
|
+ if (dqFile == null){
|
|
|
+ log.info("从minIo下载的文件为空");
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ JSONArray resultArr = new JSONArray();
|
|
|
+ boolean jx = true;
|
|
|
+ if (dqFile.renameTo(dqFile)) {
|
|
|
+ InputStreamReader dqRead = null;
|
|
|
+ BufferedReader dqBufferedReader = null;
|
|
|
+ String stringLine;
|
|
|
+ String compareDate = "";
|
|
|
+ // 获取短期文件生成日期
|
|
|
+ String recDate = dqFile.getName().substring(3, 11);
|
|
|
+ // 超短期起始时间
|
|
|
+ String cdqFileStartTime = "";
|
|
|
+ // 获取短期文件生成时间在几点
|
|
|
+ String fileTime = dqFile.getName().substring(11, 13);
|
|
|
+ // 如果文件生成时间>=12点,则为pm(下午),否则为上午
|
|
|
+ String version = "AM";
|
|
|
+ if (Integer.valueOf(fileTime) >= 12) {
|
|
|
+ version = "PM";
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 按照每行来解析文件
|
|
|
+ dqRead = new InputStreamReader(new FileInputStream(dqFile), "utf-8");
|
|
|
+ dqBufferedReader = new BufferedReader(dqRead);
|
|
|
+ JSONObject dayInfoJson = new JSONObject();
|
|
|
+ //一天中的96条数据信息
|
|
|
+ JSONArray valuesArr = new JSONArray();
|
|
|
+ JSONObject oneJson;
|
|
|
+ JSONArray datas = new JSONArray();
|
|
|
+ // 如果是短期
|
|
|
+ if ("dq".equals(type)) {
|
|
|
+ while ((stringLine = dqBufferedReader.readLine()) != null) {
|
|
|
+ String[] string_arr = stringLine.split("\t");
|
|
|
+ if (string_arr.length == 4 && string_arr[0].startsWith("#")) {
|
|
|
+ if (StrUtil.isNotEmpty(string_arr[2])) {
|
|
|
+ //当条的日期
|
|
|
+ String thisDate = string_arr[2].split(" ")[0];
|
|
|
+ // 如果是短期
|
|
|
+ if("dq".equals(type)){
|
|
|
+ // 如果 当条日期<开始时间 || 当条日期>结束时间 跳过当次循环
|
|
|
+ if (thisDate.compareTo(startDate) < 0 || thisDate.compareTo(endDate) > 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果当条的日期和上调日期不一致,新建dayInfoJson(日数据json)
|
|
|
+ if (!thisDate.equals(compareDate)) {
|
|
|
+ // 如果不是第一条,且和上一条日期不是同一天,则将上条日期的96条数据放入日json数据
|
|
|
+ if (!"".equals(compareDate)) {
|
|
|
+ dayInfoJson.set("datas", datas);
|
|
|
+ valuesArr.add(dayInfoJson);
|
|
|
+ datas = new JSONArray();
|
|
|
+ }
|
|
|
+ // 将当条日期放入compareDate
|
|
|
+ compareDate = thisDate;
|
|
|
+ // 新建日json数据
|
|
|
+ dayInfoJson = new JSONObject();
|
|
|
+ dayInfoJson.set("date", thisDate);
|
|
|
+ dayInfoJson.set("version", version);
|
|
|
+ dayInfoJson.set("recDate", recDate);
|
|
|
+ }
|
|
|
+ // 每一条数据的json,放入预测数据和预测时间
|
|
|
+ oneJson = new JSONObject();
|
|
|
+ BigDecimal bigData = new BigDecimal(string_arr[3]);
|
|
|
+ bigData = bigData.multiply(new BigDecimal("1000"));
|
|
|
+ oneJson.set("data", bigData);
|
|
|
+ oneJson.set("time", string_arr[2]);
|
|
|
+ // 将一每条数据放入datas(一天的json)中
|
|
|
+ datas.add(oneJson);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将最后一日数据放入valuesArr
|
|
|
+ dayInfoJson.set("datas", datas);
|
|
|
+ valuesArr.add(dayInfoJson);
|
|
|
+
|
|
|
+ // 将短期预测数据放入powerJson中
|
|
|
+ JSONObject powerJson = new JSONObject();
|
|
|
+ powerJson.set("values", valuesArr);
|
|
|
+ powerJson.set("type", "power");
|
|
|
+ powerJson.set("wfId", station.getStationCode());
|
|
|
+ //返回短期数据JSONArray
|
|
|
+ resultArr.add(powerJson);
|
|
|
+ // 如果是超短期
|
|
|
+ } else if ("cdq".equals(type)) {
|
|
|
+ while ((stringLine = dqBufferedReader.readLine()) != null) {
|
|
|
+ String[] string_arr = stringLine.split("\t");
|
|
|
+ if (string_arr.length == 4 && string_arr[0].startsWith("#")) {
|
|
|
+ if (StrUtil.isNotEmpty(string_arr[2])) {
|
|
|
+ if ("#1".equals(string_arr[0])) {
|
|
|
+ cdqFileStartTime = string_arr[2];
|
|
|
+ datas = new JSONArray();
|
|
|
+ dayInfoJson = new JSONObject();
|
|
|
+ dayInfoJson.set("date", cdqFileStartTime);
|
|
|
+ dayInfoJson.set("version", version);
|
|
|
+ dayInfoJson.set("recDate", recDate);
|
|
|
+ }
|
|
|
+ oneJson = new JSONObject();
|
|
|
+ oneJson.set("data", string_arr[3]);
|
|
|
+ oneJson.set("time", string_arr[2]);
|
|
|
+ // 将一每条数据放入datas(一天的json)中
|
|
|
+ datas.add(oneJson);
|
|
|
+ // 每一条数据的json,放入预测数据和预测时间
|
|
|
+ oneJson = new JSONObject();
|
|
|
+ BigDecimal bigData = new BigDecimal(string_arr[3]);
|
|
|
+ oneJson.set("data", new BigDecimal("1000").multiply(bigData));
|
|
|
+ oneJson.set("time", string_arr[2]);
|
|
|
+ // 将一每条数据放入datas(一天的json)中
|
|
|
+ datas.add(oneJson);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 将最后一日数据放入vaulesArr
|
|
|
+ dayInfoJson.set("datas", datas);
|
|
|
+ valuesArr.add(dayInfoJson);
|
|
|
+ // 将短期预测数据放入powerJson中
|
|
|
+ JSONObject powerJson = new JSONObject();
|
|
|
+ powerJson.set("type", "power");
|
|
|
+ powerJson.set("values", valuesArr);
|
|
|
+ powerJson.set("wfId", station.getStationCode());
|
|
|
+ //返回短期数据JSONArray
|
|
|
+ resultArr.add(powerJson);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ jx = false;
|
|
|
+ log.error(station.getStationCode() + " 解析当天DQ文件错误:", e);
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ } finally {
|
|
|
+ close(dqBufferedReader, dqRead);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //如果解析成功
|
|
|
+ if (jx) {
|
|
|
+ return JsonResultUtil.success(resultArr);
|
|
|
+ } else {
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭文件流
|
|
|
+ *
|
|
|
+ * @param bufferedReader 字符数据
|
|
|
+ * @param read 字节流
|
|
|
+ */
|
|
|
+ private void close(BufferedReader bufferedReader, InputStreamReader read) {
|
|
|
+ try {
|
|
|
+ if (bufferedReader != null) {
|
|
|
+ bufferedReader.close();
|
|
|
+ }
|
|
|
+ if (read != null) {
|
|
|
+ read.close();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("关闭文件流失败:", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼接短期修正后数据Map
|
|
|
+ *
|
|
|
+ * @param dqDate
|
|
|
+ * @param stationName
|
|
|
+ * @param station
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<Map<String, Object>> getDqListMap(Station station ,JSONArray dqDate, String stationName) {
|
|
|
+ List<Map<String, Object>> result = new ArrayList<>();
|
|
|
+ BigDecimal rowData = BigDecimal.ZERO;
|
|
|
+ // 获取当前时间
|
|
|
+ String dateNow = DateUtil.format(new Date(), "yyyy-MM-dd");
|
|
|
+ // 下载当天文件
|
|
|
+ File file = downLoadFileFromMinIo(station, "dq", dateNow,dateNow);
|
|
|
+ //解析短期文件,并获取当天数据
|
|
|
+ JSONObject todayData = fileAnalysis(file, station, "dq", dateNow, dateNow);
|
|
|
+ if(JsonResultUtil.Type.success.value().equals(todayData.get(JsonResultUtil.CODE_TAG))){
|
|
|
+ addListData(result,todayData,stationName,"minIo");
|
|
|
+ }
|
|
|
+ // 将修正后的明天的数据放入
|
|
|
+ addListData(result,JsonResultUtil.success(dqDate),stationName,"other");
|
|
|
+ // 获取后天日期
|
|
|
+ LocalDateTime dayAfterTomorrowDateTime = LocalDateTime.now().plus(2, ChronoUnit.DAYS);
|
|
|
+ String dayAfterTomorrowStr = dayAfterTomorrowDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
|
+ //解析短期文件,并获取后天之后的数据
|
|
|
+ JSONObject otherData = fileAnalysis(file, station, "dq", dayAfterTomorrowStr, "2123-01-01");
|
|
|
+ // 放入后天之后的数据
|
|
|
+ if(JsonResultUtil.Type.success.value().equals(otherData.get(JsonResultUtil.CODE_TAG))){
|
|
|
+ addListData(result,otherData,stationName,"minIo");
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成文件
|
|
|
+ *
|
|
|
+ * @param station
|
|
|
+ * @param listDate
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public JSONObject genFile(Station station, List<Map<String, Object>> listDate, String vmsPath) {
|
|
|
+ Template template = this.velocityEngine.getTemplate(vmsPath);
|
|
|
+ if (template == null) {
|
|
|
+ log.info("模板为空");
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ // 初始化模板
|
|
|
+ VelocityContext velocityContext = new VelocityContext();
|
|
|
+ // 将数据放入模板中
|
|
|
+ velocityContext.put("date", DateUtil.format(new Date(), "yyyy-MM-dd"));
|
|
|
+ velocityContext.put("stationName", station.getName());
|
|
|
+ velocityContext.put("vList", listDate);
|
|
|
+ // 将数据写入模板
|
|
|
+ StringWriter writer = new StringWriter();
|
|
|
+ template.merge(velocityContext, writer);
|
|
|
+ // 生成文件的路径
|
|
|
+ String fUrl = fileDir + File.separatorChar + "correct" + File.separatorChar + station.getStationCode();
|
|
|
+ log.info("生成文件的路径" + fUrl);
|
|
|
+ // 初始化文件路径
|
|
|
+ File fileUrl = new File(fUrl);
|
|
|
+ if (!fileUrl.exists()) {// 判断目录是否存在
|
|
|
+ fileUrl.mkdirs();
|
|
|
+ }
|
|
|
+ // 文件名
|
|
|
+ String fileName = "DQ_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + "0.RB";
|
|
|
+ // 根据文件路径和文件名,初始化文件
|
|
|
+ File file = new File(fUrl + File.separatorChar + fileName);
|
|
|
+ // 文件输出入流
|
|
|
+ FileOutputStream os = null;
|
|
|
+ try {
|
|
|
+ // 创建文件
|
|
|
+ boolean res = file.createNewFile();
|
|
|
+ // 如果创建成功,将数据写入
|
|
|
+ if (res) {
|
|
|
+ os = new FileOutputStream(file);
|
|
|
+ // 采用UTF-8字符集
|
|
|
+ os.write(writer.toString().getBytes("UTF-8"));
|
|
|
+ os.flush();
|
|
|
+ } else {
|
|
|
+ log.warn(station.getStationCode() + " 生成DQ文件失败");
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.warn(station.getStationCode() + " 创建DQ文件失败");
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ } finally {
|
|
|
+ if (os != null) {
|
|
|
+ try {
|
|
|
+ os.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("文件生成关闭流失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("生成文件名" + file.getName());
|
|
|
+ // 将生成的文件放入MinIo
|
|
|
+ JSONObject pushMinIoResult = pushFileToMinIo(file, station.getStationCode());
|
|
|
+ if (JsonResultUtil.Type.failure.value().equals(pushMinIoResult.get(JsonResultUtil.CODE_TAG))) {
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+
|
|
|
+ String minIoFileUrl = pushMinIoResult.getStr(JsonResultUtil.DATA_TAG);
|
|
|
+ String [] minIoFileUrlArr = minIoFileUrl.split(";");
|
|
|
+ if(minIoFileUrlArr.length>1){
|
|
|
+ for(String url : minIoFileUrlArr ){
|
|
|
+ postFileCreateInfoToCloud(station.getStationCode(), file.getName(), url);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ // 如果文件放成功,回传文件生成信息到云端
|
|
|
+ postFileCreateInfoToCloud(station.getStationCode(), file.getName(), pushMinIoResult.getStr(JsonResultUtil.DATA_TAG));
|
|
|
+ }
|
|
|
+
|
|
|
+ return JsonResultUtil.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 向minIo中放入文件
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @param stationCode
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public JSONObject pushFileToMinIo(File file, String stationCode) {
|
|
|
+ boolean flag = false;
|
|
|
+ // 存放完文件后返回的文件路径
|
|
|
+ String minIoFileUrl = "";
|
|
|
+ try {
|
|
|
+ // 查看桶名称是否存在
|
|
|
+ flag = minioUtilService.bucketExists(bucketName);
|
|
|
+ if (!flag) {
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ // 向minIo中放入文件
|
|
|
+ InputStream in = new FileInputStream(file);
|
|
|
+ String fileName = "/" + stationCode + "/" + file.getName();
|
|
|
+ minIoFileUrl = minioUtilService.putObject(bucketName, fileName, in);
|
|
|
+ // 如果是AB机,向B中也放入文件
|
|
|
+ if(stationCode.indexOf("-A")>0){
|
|
|
+ String fileNameB = "/" + stationCode.replace("-A","-B") + "/" + file.getName();
|
|
|
+ minIoFileUrl = minIoFileUrl + ";"+minioUtilService.putObject(bucketName, fileNameB, in);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return JsonResultUtil.failure();
|
|
|
+ }
|
|
|
+ return JsonResultUtil.success(minIoFileUrl);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param stationCode
|
|
|
+ * @param fileName
|
|
|
+ * @param fileDownloadUrl
|
|
|
+ */
|
|
|
+ public void postFileCreateInfoToCloud(String stationCode, String fileName, String fileDownloadUrl) {
|
|
|
+ fileDownloadUrl = fileDownloadUrl.split("\\?")[0];
|
|
|
+ Map<String, Object> urlMap = new HashMap<>();
|
|
|
+ urlMap.put("stationCode", stationCode);
|
|
|
+ urlMap.put("stationName", stationCode);
|
|
|
+ urlMap.put("fileName", fileName);
|
|
|
+ urlMap.put("fileDownloadUrl", fileDownloadUrl);
|
|
|
+ urlMap.put("sign", SystermUtils.caluMd5Sign(stationCode + DateUtil.today()));
|
|
|
+ try {
|
|
|
+ String body = HttpUtil.post(cloudFileCreateLog, urlMap, 10000);
|
|
|
+ JSONObject result = JSONUtil.parseObj(body);
|
|
|
+ if (!"0".equals(result.getStr(JsonResultUtil.CODE_TAG))) {
|
|
|
+ log.info("请求V3云平台失败");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.info("请求V3云平台失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从minIo下载文件
|
|
|
+ *
|
|
|
+ * @param station
|
|
|
+ * @param type
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public File downLoadFileFromMinIo(Station station, String type, String startTime, String endTime) {
|
|
|
+ // 如果场站信息为空
|
|
|
+ if (station == null) {
|
|
|
+ log.info("场站信息为空");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startTime == null || "".equals(startTime)) {
|
|
|
+ log.info("超短期文件获取失败,开始时间为空");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Record record = new Record();
|
|
|
+ log.info("下载minIo原始RB文件 --> {}" + station.getStationCode());
|
|
|
+ try {
|
|
|
+ HttpRequest httpRequest = HttpRequest.get(url + station.getStationCode());
|
|
|
+ httpRequest.setGlobalTimeout(20000);
|
|
|
+ String body = httpRequest.execute().body();
|
|
|
+ JSONObject json = JSONUtil.parseObj(body);
|
|
|
+ String code = json.get("code").toString();
|
|
|
+ String data = json.get("data").toString();
|
|
|
+ if (!code.equals("0") || data.length() <= 0) {
|
|
|
+ record.setState(StatusEnum.RESPONSE_FAIL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 获取文件文件内容
|
|
|
+ JSONArray array = JSONUtil.parseArray(data);
|
|
|
+ // 文件列表
|
|
|
+ List<FileCreateLog> list = array.toList(FileCreateLog.class);
|
|
|
+ // 获取当前时间
|
|
|
+ String dateNow = DateUtil.format(new Date(), "yyyyMMdd");
|
|
|
+ // 如果文件列表为空,则未获取到文件
|
|
|
+ if (CollectionUtil.isEmpty(list)) {
|
|
|
+ record.setState(StatusEnum.FILE_NULL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存文件路径
|
|
|
+ String fileSaveUrl = fileDir + File.separatorChar + "init" + File.separatorChar + station.getStationCode();
|
|
|
+ log.info(fileSaveUrl);
|
|
|
+ File dir = new File(fileSaveUrl);
|
|
|
+ if (!dir.exists()) {// 判断目录是否存在
|
|
|
+ dir.mkdirs();
|
|
|
+ log.info("创建目录:" + fileSaveUrl);
|
|
|
+ }
|
|
|
+ // 筛选当日短期文件
|
|
|
+ List<FileCreateLog> listNow = new ArrayList<>();
|
|
|
+ String nowUrl = "";
|
|
|
+ String downloadFileName = "";
|
|
|
+ // 如果是短期
|
|
|
+ if ("dq".equals(type)) {
|
|
|
+ listNow = list.stream().filter(f -> f.getFileName().contains("DQ_" + dateNow.replace("-", ""))).collect(Collectors.toList());
|
|
|
+ // 如果文件为空,
|
|
|
+ if (CollectionUtil.isEmpty(listNow)) {
|
|
|
+ record.setState(StatusEnum.FILE_NULL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode()+" DQ文件", StatusEnum.FILE_NULL.getMsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 将短期文件倒序,获取最新的文件
|
|
|
+ listNow.sort(Comparator.comparing(FileCreateLog::getFileName).reversed());
|
|
|
+ // 拼接下载文件url=fileUrl(下载文件请求地址)+从minIo获取的最新一条的文件id
|
|
|
+ nowUrl = fileurl + listNow.get(0).getId();
|
|
|
+ downloadFileName = listNow.get(0).getFileName();
|
|
|
+ // 如果是超短期
|
|
|
+ } else if ("cdq".equals(type)) {
|
|
|
+ // 格式化开始时间 将时间2019-10-10 01:15 转为=》201910100115
|
|
|
+ String formatStartTime = startTime.replace("-", "").replace(" ", "").replace(":", "");
|
|
|
+ // 根据CDQ_201910100115 筛选超短期文件
|
|
|
+ listNow = list.stream().filter(f -> f.getFileName().contains("CDQ_" + formatStartTime)).collect(Collectors.toList());
|
|
|
+ // 如果文件为空,
|
|
|
+ if (CollectionUtil.isEmpty(listNow)) {
|
|
|
+ record.setState(StatusEnum.FILE_NULL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果文件为空,
|
|
|
+ if (CollectionUtil.isEmpty(listNow)) {
|
|
|
+ record.setState(StatusEnum.FILE_NULL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 通过url下载文件
|
|
|
+ File nowFile = HttpUtil.downloadFileFromUrl(nowUrl, fileSaveUrl + File.separatorChar + downloadFileName);
|
|
|
+ if (nowFile == null) {
|
|
|
+ record.setState(StatusEnum.DOWNLOAD_FILE_ERROR.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_ERROR.getMsg());
|
|
|
+ }
|
|
|
+ // 返回文件
|
|
|
+ return nowFile;
|
|
|
+ } catch (Exception e) {
|
|
|
+ record.setState(StatusEnum.DOWNLOAD_FILE_FAIL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_FAIL.getMsg());
|
|
|
+ e.printStackTrace();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ record.setState(StatusEnum.RESPONSE_FAIL.getCode());
|
|
|
+ log.error("下载minIo原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
|
|
|
+ e.printStackTrace();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Map<String, Object>> addListData(List<Map<String, Object>> list,JSONObject data,String stationName,String type){
|
|
|
+ if(JsonResultUtil.Type.success.value().equals(data.get(JsonResultUtil.CODE_TAG))) {
|
|
|
+ JSONArray dataArr = new JSONArray();
|
|
|
+ if("minIo".equals(type)){
|
|
|
+// dataArr = data.getJSONArray("data").getJSONObject(0).getJSONArray("values").getJSONObject(0).getJSONArray("datas");
|
|
|
+ dataArr = data.getJSONArray("data").getJSONObject(0).getJSONArray("values");
|
|
|
+ for(Object one :dataArr){
|
|
|
+ JSONArray oneDaysData = JSONUtil.parseObj(one).getJSONArray("datas");
|
|
|
+ addOneDay(list,oneDaysData,stationName);
|
|
|
+ }
|
|
|
+ }else if("other".equals(type)){
|
|
|
+ dataArr = data.getJSONArray("data");
|
|
|
+ addOneDay(list,dataArr,stationName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Map<String, Object>> addOneDay(List<Map<String, Object>> list,JSONArray dataArr,String stationName){
|
|
|
+ for(Object one :dataArr){
|
|
|
+ JSONObject oneJson = JSONUtil.parseObj(one);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("stationName", stationName);
|
|
|
+ map.put("fpValue", oneJson.getStr("data") == null ? "-99" : new BigDecimal(oneJson.getStr("data")).divide(new BigDecimal("1000"),2,BigDecimal.ROUND_HALF_UP));
|
|
|
+ map.put("forecastTime", oneJson.getStr("time").length()==16? oneJson.getStr("time")+ CommonStant.CHARACTER_TIME_ZERO:oneJson.getStr("time"));
|
|
|
+ list.add(map);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+}
|