RyTask.java 102 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803
  1. package com.slibra.quartz.task;
  2. import cn.hutool.core.date.DateUtil;
  3. import cn.hutool.http.HttpRequest;
  4. import cn.hutool.http.HttpUtil;
  5. import com.alibaba.fastjson2.JSON;
  6. import com.alibaba.fastjson2.JSONArray;
  7. import com.alibaba.fastjson2.JSONObject;
  8. import com.alibaba.fastjson2.JSONWriter;
  9. import com.google.protobuf.ByteString;
  10. import com.slibra.business.domain.*;
  11. import com.slibra.business.mapper.*;
  12. import com.slibra.business.req.ChatReq;
  13. import com.slibra.business.req.ChatRequest;
  14. import com.slibra.business.req.PredictorRequest;
  15. import com.slibra.business.res.ChartBasic;
  16. import com.slibra.business.res.ShowValueChartBasic;
  17. import com.slibra.business.service.ITXinyiForecastComparisonService;
  18. import com.slibra.common.DecimalUtils;
  19. import com.slibra.common.constant.MyConstants;
  20. import com.slibra.common.enums.BusinessEnum;
  21. import com.slibra.common.enums.DataSourceType;
  22. import com.slibra.common.utils.DateUtils;
  23. import com.slibra.common.utils.ip.IpUtils;
  24. import com.slibra.common.utils.uuid.IdUtils;
  25. import com.slibra.framework.datasource.DynamicDataSourceContextHolder;
  26. import inference.InferenceAPIsServiceGrpc;
  27. import inference.PredictionResponse;
  28. import inference.PredictionsRequest;
  29. import io.grpc.ManagedChannel;
  30. import io.grpc.ManagedChannelBuilder;
  31. import lombok.extern.slf4j.Slf4j;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.stereotype.Component;
  34. import com.slibra.common.utils.StringUtils;
  35. import org.springframework.util.CollectionUtils;
  36. import java.io.IOException;
  37. import java.math.BigDecimal;
  38. import java.text.ParseException;
  39. import java.time.LocalDateTime;
  40. import java.time.format.DateTimeFormatter;
  41. import java.util.*;
  42. import java.util.stream.Collectors;
  43. import static com.slibra.common.constant.MyConstants.*;
  44. /**
  45. * 定时任务调度测试
  46. *
  47. *
  48. */
  49. @Component("ryTask")
  50. @Slf4j
  51. public class RyTask
  52. {
  53. public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
  54. {
  55. System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i));
  56. }
  57. public void ryParams(String params)
  58. {
  59. System.out.println("执行有参方法:" + params);
  60. }
  61. public void ryNoParams()
  62. {
  63. System.out.println("执行无参方法");
  64. }
  65. //----------------------------------------------下面是新增的方法----------------------------------------------
  66. @Autowired
  67. private TXinyiIndustryMapper xinyiIndustryMapper;
  68. @Autowired
  69. private TXinyiRobotMapper xinyiRobotMapper;
  70. @Autowired
  71. private TXinyiNormConfigMapper xinyiNormConfigMapper;
  72. @Autowired
  73. private TXinyiWarningRecordMapper xinyiWarningRecordMapper;
  74. @Autowired
  75. private TXinyiChatRecordMapper xinyiChatRecordMapper;
  76. @Autowired
  77. private TXinyiDailyMapper xinyiDailyMapper;
  78. @Autowired
  79. private AsyncTask asyncTask;
  80. @Autowired
  81. private ITXinyiForecastComparisonService xinyiForecastComparisonService;
  82. // public final static StopWatch watch = new StopWatch("task");
  83. public static final String[] queryTags = {"信义污水厂JS_COD_Value","信义污水厂JS_PH_Value","信义污水厂JS_SS_Value","信义污水厂JS_ZL_Value","信义污水厂JS_ZA_Value","信义污水厂JS_AD_Value","信义污水厂JS_T_Value","信义污水厂进水泵房液位","信义污水厂出水瞬时流量","信义污水厂升级出水COD","信义污水厂升级出水PH","信义污水厂升级出水SS","信义污水厂升级出水TN","信义污水厂升级出水TP","信义污水厂升级出水氨氮","信义污水厂AIT202_Value","信义污水厂AIT203_Value","信义污水厂AIT207_Value","信义污水厂AIT206_Value","信义污水厂AIT209_Value","信义污水厂AIT210_Value","信义污水厂进水TDS","信义污水厂FT101_Value","信义污水厂SWCHHYHLB1_R_Value","信义污水厂SWCHHYHLB2_R_Value","信义污水厂SWCHHYHLB3_R_Value","信义污水厂SWCHHYHLB4_R_Value","信义污水厂SWCHHYHLB5_R_Value","信义污水厂SWCHHYHLB6_R_Value","信义污水厂SWCWNHLB1_R_Value","信义污水厂SWCWNHLB2_R_Value","信义污水厂SWCWNHLB3_R_Value","信义污水厂SWCWNHLB4_R_Value","信义污水厂SWCWNHLB5_R_Value","信义污水厂GFJ1_R_Value","信义污水厂GFJ2_R_Value","信义污水厂GFJ3_R_Value","信义污水厂GFJ4_R_Value","信义污水厂GFJ5_R_Value","信义污水厂GFJ6_R_Value","信义污水厂GFJ1_KQLL_Value","信义污水厂GFJ2_KQLL_Value","信义污水厂GFJ3_KQLL_Value","信义污水厂GFJ4_KQLL_Value","信义污水厂GFJ5_KQLL_Value","信义污水厂GFJ6_KQLL_Value","信义污水厂实际碳源加药量","信义污水厂除磷加药瞬时流量", "信义污水厂_除磷P04预测值_"};
  84. /**
  85. *
  86. * 2024年6月21日14:52:05 调整逻辑:
  87. * 出水总氮 的预测:使用 (xsy1 + xsy2) /2 /0.8 做为出水总氮的结果
  88. *
  89. */
  90. public static final String[] predictorArr = {"出水COD", "出水SS", "出水总磷", "出水氨氮"};
  91. public static final String[] predictorArrSpecial = {"xsy1", "xsy2"};
  92. /**
  93. * 定时从工业库获取数据
  94. *
  95. * 2024年4月17日17:44:15 调整逻辑:考虑到因断电等情况导致服务断电,所以不再同步最近一小时,而是同步从上次成功的最后一条数据开始。
  96. */
  97. public void getIndustryData(){
  98. log.info("进入了定时同步工业库数据的任务");
  99. //耗时工具
  100. // watch.start("parseJob");
  101. // 给定时间段的起始时间和结束时间
  102. LocalDateTime endTime = LocalDateTime.now();
  103. // LocalDateTime startTime = endTime.plusMinutes(-60);
  104. //获取上次最后一条同步的数据的日期到 分钟维度
  105. String lastDateHour = this.xinyiIndustryMapper.getLastMinute();
  106. log.info("获取上次同步工业库的最后一条记录的时间是{}", lastDateHour);
  107. lastDateHour = lastDateHour + ":00";
  108. //开始时间
  109. LocalDateTime startTime = LocalDateTime.parse(lastDateHour.replaceAll("/", "-").replace(" ", "T"));
  110. startTime = startTime.plusMinutes(60L);//加一分钟 从上次最后一条记录的下一分钟开始
  111. /*LocalDateTime startTime = LocalDateTime.parse("2024-02-26T00:00:00");
  112. LocalDateTime endTime = LocalDateTime.parse("2024-02-27T00:00:00");*/
  113. // 每个小时的时间格式
  114. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  115. // 循环按小时分割
  116. LocalDateTime currentHour = startTime;
  117. //最终获取的数据
  118. Map<String, TXinyiIndustry> needMap = new LinkedHashMap<>();
  119. while (currentHour.isBefore(endTime)) {
  120. String begin = currentHour.format(formatter);
  121. String end = currentHour.plusMinutes(5).format(formatter);
  122. // 输出当前小时的起始时间和结束时间
  123. System.out.println("起始时间:" + begin);
  124. System.out.println("结束时间:" + end);
  125. // 当前小时加一小时,作为下一个小时的起始时间
  126. currentHour = currentHour.plusMinutes(5);
  127. //每个小时查询一次数据
  128. String url = "http://10.0.0.27:4568/api/v1/khquerydata";
  129. HashMap<String, Object> req = new HashMap<>();
  130. req.put("tagNames", queryTags);
  131. req.put("startTime", begin);
  132. req.put("endTime", end);
  133. req.put("recordNumbers", 100000);
  134. String body = HttpRequest.post(url).header("Authorization", "c2E6c2E=").header("clientName", "hongshan").body(JSON.toJSONString(req)).execute().body();
  135. // System.out.println("body = " + body);
  136. List<HashMap<String, String>> list = new ArrayList<>();
  137. //行转列数据处理
  138. for (String queryTag : queryTags) {
  139. JSONArray array = JSON.parseObject(body).getJSONArray(queryTag);
  140. //特殊数据处理一
  141. if(Objects.isNull(array) || array.isEmpty()){
  142. System.out.println(queryTag + "查询到了空的数据,跳过本次循环");
  143. continue;
  144. }
  145. int size = array.size();
  146. //特殊数据处理二
  147. if("0".equals(array.get(1) + "")){
  148. System.out.println(queryTag + "查询到了数据,但是数据集合只有一条,且都是0");
  149. continue;
  150. }
  151. //结合至少62个数据才满足条件(有可能获取不到)
  152. /*if(size < 62){
  153. System.out.println(queryTag + "查询到了不符合条件的数据,跳过本次循环");
  154. continue;
  155. }*/
  156. //存放的数据集
  157. //利用map去重
  158. HashMap<String, String> map = new LinkedHashMap<>();
  159. for (int i = 2; i < size; i++) {
  160. // System.out.println(i + "" + array.get(i));
  161. JSONArray oneRecord = JSON.parseArray(JSON.toJSONString(array.get(i)));
  162. //处理为空或者为0的数据
  163. Object timeStampValue = oneRecord.get(2);
  164. if(Objects.isNull(timeStampValue) || "0".equals(timeStampValue + ""))
  165. continue;
  166. BigDecimal value = Objects.isNull(oneRecord.get(0)) ? null : new BigDecimal(oneRecord.get(0) + "");
  167. long timestamp = (long) timeStampValue;
  168. String format = DateUtil.format(new Date(timestamp), DateUtils.YYYYMMDDHH_TS);
  169. map.put(format, queryTag + "-" + value);
  170. }
  171. list.add(map);
  172. }
  173. Set<String> recordTimeSet = new HashSet<>();
  174. Map<String, TXinyiIndustry> recordMap = new HashMap<>();
  175. for (int i = 0; i < list.size(); i++) {
  176. HashMap<String, String> map = list.get(i);
  177. int finalJ = i;
  178. map.forEach((k, v) ->{
  179. TXinyiIndustry industry = null;
  180. if(!recordTimeSet.contains(k)){//第一次
  181. industry = new TXinyiIndustry();
  182. recordTimeSet.add(k);
  183. recordMap.put(k, industry);
  184. }else{
  185. industry = recordMap.get(k);
  186. }
  187. industry.setTestTime(k + ":00");
  188. //2024年4月15日11:19:52 额外增加2个字段
  189. industry.setTestDate(k.substring(0,10));
  190. industry.setTestHour(k.substring(0,13));
  191. //解析值
  192. String[] split = v.split("-");
  193. String type = split[0];
  194. BigDecimal value = new BigDecimal(split[1]);
  195. if ("信义污水厂JS_COD_Value".equals(type)) {
  196. industry.setJsCod(value);
  197. } else if ("信义污水厂JS_PH_Value".equals(type)) {
  198. industry.setJsPh(value);
  199. } else if ("信义污水厂JS_SS_Value".equals(type)) {
  200. // log.info("************----------真实的进水SS的值为{}\n时间为{}", value, k);
  201. industry.setJsSs(value);
  202. } else if ("信义污水厂JS_ZL_Value".equals(type)) {
  203. industry.setJsTp(value);
  204. } else if ("信义污水厂JS_ZA_Value".equals(type)) {
  205. industry.setJsTn(value);
  206. } else if ("信义污水厂JS_AD_Value".equals(type)) {
  207. industry.setJsNh3(value);
  208. } else if ("信义污水厂JS_T_Value".equals(type)) {
  209. industry.setJsSwPh(value);
  210. } else if ("信义污水厂进水泵房液位".equals(type)) {
  211. industry.setJsBfyw(value);
  212. } else if ("信义污水厂出水瞬时流量".equals(type)) {
  213. industry.setCsSlqc(value);
  214. } else if ("信义污水厂升级出水COD".equals(type)) {
  215. industry.setCsCod(value);
  216. } else if ("信义污水厂升级出水PH".equals(type)) {
  217. industry.setCsPh(value);
  218. } else if ("信义污水厂升级出水SS".equals(type)) {
  219. industry.setCsSs(value);
  220. } else if ("信义污水厂升级出水TN".equals(type)) {
  221. // log.info("************----------真实的出水总氮的值为{}\n时间为{}", value, k);
  222. // industry.setCsTn(new BigDecimal(17));
  223. industry.setCsTn(value);
  224. } else if ("信义污水厂升级出水TP".equals(type)) {
  225. industry.setCsTp(value);
  226. } else if ("信义污水厂升级出水氨氮".equals(type)) {
  227. industry.setCsNh3(value);
  228. } else if ("信义污水厂AIT202_Value".equals(type)) {
  229. industry.setOneHyzdDo(value);
  230. } else if ("信义污水厂AIT203_Value".equals(type)) {
  231. industry.setOneHymdDo(value);
  232. } else if ("信义污水厂AIT207_Value".equals(type)) {
  233. industry.setTwoHyzdDo(value);
  234. } else if ("信义污水厂AIT206_Value".equals(type)) {
  235. industry.setTwoHymdDo(value);
  236. } else if ("信义污水厂AIT209_Value".equals(type)) {
  237. industry.setOneMlss(value);
  238. } else if ("信义污水厂AIT210_Value".equals(type)) {
  239. industry.setTwoMlss(value);
  240. } else if ("信义污水厂进水TDS".equals(type)) {
  241. industry.setJsTds(value);
  242. } else if ("信义污水厂FT101_Value".equals(type)) {
  243. industry.setJsSlq(value);
  244. } else if ("信义污水厂SWCHHYHLB1_R_Value".equals(type)) {
  245. industry.setNHlbOneGp(value);
  246. } else if ("信义污水厂SWCHHYHLB2_R_Value".equals(type)) {
  247. industry.setNHlbTwoGp(value);
  248. } else if ("信义污水厂SWCHHYHLB3_R_Value".equals(type)) {
  249. industry.setNHlbThreeGp(value);
  250. } else if ("信义污水厂SWCHHYHLB4_R_Value".equals(type)) {
  251. industry.setNHlbFourGp(value);
  252. } else if ("信义污水厂SWCHHYHLB5_R_Value".equals(type)) {
  253. industry.setNhlBFiveGp(value);
  254. } else if ("信义污水厂SWCHHYHLB6_R_Value".equals(type)) {
  255. industry.setNHlbSixGp(value);
  256. } else if ("信义污水厂SWCWNHLB1_R_Value".equals(type)) {
  257. industry.setWHlbOneGp(value);
  258. } else if ("信义污水厂SWCWNHLB2_R_Value".equals(type)) {
  259. industry.setWHlbTwoGp(value);
  260. } else if ("信义污水厂SWCWNHLB3_R_Value".equals(type)) {
  261. industry.setWHlbThreeGp(value);
  262. } else if ("信义污水厂SWCWNHLB4_R_Value".equals(type)) {
  263. industry.setWHlbFourGp(value);
  264. } else if ("信义污水厂SWCWNHLB5_R_Value".equals(type)) {
  265. industry.setWHlbFiveGp(value);
  266. } else if ("信义污水厂GFJ1_R_Value".equals(type)) {
  267. industry.setFjOne(value);
  268. } else if ("信义污水厂GFJ2_R_Value".equals(type)) {
  269. industry.setFjTwo(value);
  270. } else if ("信义污水厂GFJ3_R_Value".equals(type)) {
  271. industry.setFjThree(value);
  272. } else if ("信义污水厂GFJ4_R_Value".equals(type)) {
  273. industry.setFjFour(value);
  274. } else if ("信义污水厂GFJ5_R_Value".equals(type)) {
  275. industry.setFjFive(value);
  276. } else if ("信义污水厂GFJ6_R_Value".equals(type)) {
  277. industry.setFjSix(value);
  278. } else if ("信义污水厂GFJ1_KQLL_Value".equals(type)) {
  279. industry.setKqllOne(value);
  280. } else if ("信义污水厂GFJ2_KQLL_Value".equals(type)) {
  281. industry.setKqllTwo(value);
  282. } else if ("信义污水厂GFJ3_KQLL_Value".equals(type)) {
  283. industry.setKqllThree(value);
  284. } else if ("信义污水厂GFJ4_KQLL_Value".equals(type)) {
  285. industry.setKqllFour(value);
  286. } else if ("信义污水厂GFJ5_KQLL_Value".equals(type)) {
  287. industry.setKqllFive(value);
  288. } else if ("信义污水厂GFJ6_KQLL_Value".equals(type)) {
  289. industry.setKqllSix(value);
  290. }else if ("信义污水厂实际碳源加药量".equals(type)) {
  291. industry.setSJTYJLY(value);
  292. }else if ("信义污水厂除磷加药瞬时流量".equals(type)) {
  293. industry.setCLJYSSLL(value);
  294. } else if ("信义污水厂_除磷P04预测值_".equals(type)) {
  295. industry.setCLP04YCZ(value);
  296. }
  297. //只有最后一次才执行数据库添加
  298. if(finalJ == list.size()-1){
  299. needMap.put(industry.getTestHour(), industry);
  300. }
  301. });
  302. }
  303. }
  304. //保存数据 触发告警 决策 问答记录等等
  305. needMap.forEach((k, industry) ->{
  306. //2024年4月22日15:45:24 额外保存两个字段 数组
  307. List<BigDecimal> extraList = new ArrayList<>();
  308. extraList.add(industry.getOneHymdDo());
  309. extraList.add(industry.getTwoHymdDo());
  310. industry.setHycRjyAll(JSON.toJSONString(extraList));
  311. extraList.clear();
  312. extraList.add(industry.getOneHyzdDo());
  313. extraList.add(industry.getTwoHyzdDo());
  314. industry.setHycRjyZdAll(JSON.toJSONString(extraList));
  315. extraList.clear();
  316. extraList.add(industry.getOneMlss());
  317. extraList.add(industry.getTwoMlss());
  318. industry.setHycWnndAll(JSON.toJSONString(extraList));
  319. //插入数据库
  320. xinyiIndustryMapper.insertTXinyiIndustry(industry);
  321. //判断是否触发告警、接触告警、保存决策等等
  322. // this.handleWarning(industry);
  323. //2024年5月30日18:29:20 改为异步处理
  324. asyncTask.handleWarning(industry);
  325. });
  326. //执行完成 测试执行时间
  327. //计时结束
  328. // watch.stop();
  329. // System.out.println(watch.getLastTaskName() + " 执行耗时:" + watch.getLastTaskTimeMillis() + " ms");
  330. }
  331. private String buildShowValueDeviceErr(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
  332. JSONObject result = new JSONObject();
  333. JSONObject basic = new JSONObject();
  334. Integer status = tXinyiWarningRecord.getStatus();
  335. Date warningTime = tXinyiWarningRecord.getTime();
  336. int count = DateUtils.differentHoursByMillisecond(warningTime, DateUtils.getNowDate()) + 1;
  337. basic.put("title", tXinyiWarningRecord.getReason());
  338. basic.put("报警时间", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM ,warningTime));
  339. basic.put("报警值", tXinyiWarningRecord.getWarningVal());
  340. basic.put("标准值", tXinyiWarningRecord.getDesignVal());
  341. basic.put("管控值", tXinyiWarningRecord.getControlVal());
  342. basic.put("报警次数", Math.min(count, MAX_COUNT));
  343. if(tXinyiWarningRecord.getType() != 2)
  344. basic.put("状态", status == 0 ? "报警中" : status == 1 ? "用户关闭" : status == 2 ? "系统关闭" : "应急处理中");
  345. else
  346. basic.put("状态", status == 0 ? "预警中" : "已完成");
  347. //2024年5月27日14:04:22 额外返回2个字段 [管控值 和 告警级别] 返回的json没有数据是因为value没有值
  348. // basic.put("管控值", tXinyiWarningRecord.getControlVal());
  349. basic.put("告警级别", tXinyiWarningRecord.getLevel());
  350. result.put("basic", basic);
  351. JSONObject jsData = getJsonObject(tXinyiIndustry, normConfig);//进水数据
  352. result.put("jsData", jsData);
  353. JSONObject csData = getCsonObject(tXinyiIndustry, normConfig);//出水数据
  354. result.put("csData", csData);
  355. return JSON.toJSONString(result, JSONWriter.Feature.WriteNulls);
  356. }
  357. /**
  358. * 带图形的构建展示数据
  359. *
  360. * @param tXinyiWarningRecord
  361. * @param tXinyiIndustry
  362. * @param normConfig
  363. * @param date
  364. * @param yjHour
  365. * @param nowDate
  366. * @return
  367. */
  368. private String buildShowValueWithCharts(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, List<ChartBasic> chartsDataList, String date, String yjHour, Date nowDate) {
  369. JSONObject result = new JSONObject();
  370. // JSONObject basic = new JSONObject();
  371. Integer status = tXinyiWarningRecord.getStatus();
  372. /*Date warningTime = tXinyiWarningRecord.getTime();
  373. String remark = tXinyiWarningRecord.getRemark();
  374. int count = DateUtils.differentHoursByMillisecond(warningTime, DateUtils.getNowDate()) + 1;*/
  375. ShowValueChartBasic showValueChartBasic = new ShowValueChartBasic();
  376. /*if("0".equals(remark)){//水质报警
  377. showValueChartBasic.setH("在线仪表");
  378. }else if("1".equals(remark)){//生化报警
  379. showValueChartBasic.setH("在线仪表");
  380. }else if("2".equals(remark)){//预测报错
  381. showValueChartBasic.setH("预测");
  382. }else {//机器人化验室报警
  383. showValueChartBasic.setH("化验室");
  384. }*/
  385. //通用的
  386. // showValueBasic.setA(tXinyiWarningRecord.getReason());
  387. //2024年6月23日17:01:30 预警时间改成当前时间
  388. showValueChartBasic.setB(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM, nowDate));
  389. showValueChartBasic.setC(date + " " + yjHour);//预计超标时间
  390. showValueChartBasic.setD(tXinyiWarningRecord.getWarningVal());//改成现在值 不是报警时候的值(在发现存在告警记录的时候更新)
  391. showValueChartBasic.setE(tXinyiWarningRecord.getForecastVal());//改成预测值 不是报警时候的值(在发现存在告警记录的时候更新)
  392. showValueChartBasic.setF(tXinyiWarningRecord.getControlVal());
  393. showValueChartBasic.setG(tXinyiWarningRecord.getDesignVal());
  394. // showValueChartBasic.setH(Math.min(count, MAX_COUNT));
  395. if(tXinyiWarningRecord.getType() != 2)
  396. showValueChartBasic.setI(status == 0 ? "报警中" : status == 1 ? "用户关闭" : status == 2 ? "系统关闭" : "应急处理中");
  397. else
  398. showValueChartBasic.setI(status == 0 ? "预警中" : "已完成");
  399. result.put("basic", showValueChartBasic);
  400. JSONObject jsData = getJsonObject(tXinyiIndustry, normConfig);//进水数据
  401. result.put("jsData", jsData);
  402. JSONObject csData = getCsonObject(tXinyiIndustry, normConfig);//出水数据
  403. result.put("csData", csData);
  404. // JSONObject chartsData = getChartsCsonObject(tXinyiIndustry, normConfig);//图表数据 因为展示不同,所以要传过来或者判断
  405. result.put("chartsData", chartsDataList);
  406. result.put("chartsTitle", tXinyiWarningRecord.getCategory() + "数据趋势图");
  407. return JSON.toJSONString(result, JSONWriter.Feature.WriteNulls);
  408. }
  409. private static JSONObject getJsonObject(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
  410. JSONObject jsData = new JSONObject();
  411. HashMap<Object, Object> temp1 = new HashMap<>();
  412. BigDecimal jsSlq = tXinyiIndustry.getJsSlq();
  413. temp1.put("value", jsSlq);
  414. temp1.put("exceed", jsSlq.compareTo(normConfig.getJsslSjz()) >0);
  415. jsData.put("流量", temp1);
  416. HashMap<Object, Object> temp2 = new HashMap<>();
  417. BigDecimal jsCod = tXinyiIndustry.getJsCod();
  418. temp2.put("value", jsCod);
  419. temp2.put("exceed", jsCod.compareTo(normConfig.getJscodSjz()) > 0);
  420. jsData.put("COD", temp2);
  421. HashMap<Object, Object> temp3 = new HashMap<>();
  422. BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
  423. temp3.put("value", jsNh3);
  424. temp3.put("exceed", jsNh3.compareTo(normConfig.getJsadSjz()) > 0);
  425. jsData.put("NH3-N", temp3);
  426. HashMap<Object, Object> temp4 = new HashMap<>();
  427. BigDecimal jsTp = tXinyiIndustry.getJsTp();
  428. temp4.put("value", jsTp);
  429. temp4.put("exceed", jsTp.compareTo(normConfig.getJszlSjz()) > 0);
  430. jsData.put("TP", temp4);
  431. HashMap<Object, Object> temp5 = new HashMap<>();
  432. BigDecimal jsSs = tXinyiIndustry.getJsSs();
  433. temp5.put("value", jsSs);
  434. temp5.put("exceed", jsSs.compareTo(normConfig.getJsssSjz()) > 0);
  435. jsData.put("SS", temp5);
  436. HashMap<Object, Object> temp6 = new HashMap<>();
  437. BigDecimal jsTn = tXinyiIndustry.getJsTn();
  438. temp6.put("value", jsTn);
  439. temp6.put("exceed", jsTn.compareTo(normConfig.getJszdSjz()) > 0);
  440. jsData.put("TN", temp6);
  441. return jsData;
  442. }
  443. private static JSONObject getCsonObject(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
  444. JSONObject csData = new JSONObject();
  445. HashMap<Object, Object> temp1 = new HashMap<>();
  446. BigDecimal csSlq = tXinyiIndustry.getCsSlqc();
  447. temp1.put("value", csSlq);
  448. temp1.put("exceed", false);//出水水量没有管控值
  449. csData.put("流量", temp1);
  450. HashMap<Object, Object> temp2 = new HashMap<>();
  451. BigDecimal csCod = tXinyiIndustry.getCsCod();
  452. temp2.put("value", csCod);
  453. temp2.put("exceed", csCod.compareTo(normConfig.getCscodGkz()) > 0);
  454. csData.put("COD", temp2);
  455. HashMap<Object, Object> temp3 = new HashMap<>();
  456. BigDecimal csNh3 = tXinyiIndustry.getCsNh3();
  457. temp3.put("value", csNh3);
  458. temp3.put("exceed", csNh3.compareTo(normConfig.getCsadGkz()) > 0);
  459. csData.put("NH3-N", temp3);
  460. HashMap<Object, Object> temp4 = new HashMap<>();
  461. BigDecimal csTp = tXinyiIndustry.getCsTp();
  462. temp4.put("value", csTp);
  463. temp4.put("exceed", csTp.compareTo(normConfig.getCszlGkz()) > 0);
  464. csData.put("TP", temp4);
  465. HashMap<Object, Object> temp5 = new HashMap<>();
  466. BigDecimal csSs = tXinyiIndustry.getCsSs();
  467. temp5.put("value", csSs);
  468. temp5.put("exceed", csSs.compareTo(normConfig.getCsssGkz()) > 0);
  469. csData.put("SS", temp5);
  470. HashMap<Object, Object> temp6 = new HashMap<>();
  471. BigDecimal csTn = tXinyiIndustry.getCsTn();
  472. temp6.put("value", csTn);
  473. temp6.put("exceed", csTn.compareTo(normConfig.getCszzGkz()) > 0);
  474. csData.put("TN", temp6);
  475. return csData;
  476. }
  477. private void addChatRecordByDeviceErr(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
  478. ChatReq chatReq = new ChatReq();
  479. //保存聊天记录
  480. //将问答更新到数据库中
  481. chatReq.setSessionId(IdUtils.simpleUUID());
  482. chatReq.setType(1);//0问答 1决策 2本地 3仿真预测
  483. chatReq.setModule(3);
  484. /*String userId = SecurityUtils.getUserId().toString();
  485. String username = SecurityUtils.getUsername();*/
  486. chatReq.setUserId(WARNING_DEFAULT_CREATE);
  487. String showVal = this.buildShowValueDeviceErr(tXinyiWarningRecord, tXinyiIndustry, normConfig);
  488. chatReq.setShowVal(showVal);//前端展示的数据和提问的数据不一致
  489. chatReq.setQuestion(WARNING_DEFAULT_QUESTION);//本地问题
  490. chatReq.setAnswer(tXinyiWarningRecord.getReason() + ",请检查设备是否正常运行");
  491. chatReq.setWarningId(String.valueOf(tXinyiWarningRecord.getId()));
  492. chatReq.setCounts(1);//问答次数
  493. chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
  494. chatReq.setCreateTime(DateUtils.getNowDate());
  495. this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
  496. }
  497. /**
  498. * 定时从sqlserver获取数据
  499. */
  500. public void sqlserverData(){
  501. log.info("进入了定时同步SqlServer的任务");
  502. //主库获取上次最新的同步日期
  503. String lastTime = this.xinyiRobotMapper.selectLastTime();
  504. log.info("上次同步的日期是{}", lastTime);
  505. //从
  506. DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
  507. List<TXinyiRobot> tXinyiRobots = xinyiRobotMapper.selectTXinyiRobotListByTime(lastTime);
  508. DynamicDataSourceContextHolder.clearDataSourceType();
  509. // System.out.println(JSON.toJSONString(tXinyiRobots));
  510. // System.out.println("-------------");
  511. //主
  512. List<TXinyiRobot> needHandleList = new ArrayList<>();
  513. if(!CollectionUtils.isEmpty(tXinyiRobots)){
  514. for (TXinyiRobot tXinyiRobot : tXinyiRobots) {
  515. String date = handleDate(tXinyiRobot.getVDate().replaceAll(" ", ""));//有空格
  516. String time = handleDate(tXinyiRobot.getVTime().replaceAll(" ", ""));//有空格
  517. tXinyiRobot.setVDate(date);
  518. tXinyiRobot.setVTime(time);
  519. tXinyiRobot.setVDateTime(date + " " + time);
  520. //处理给前端展示的字段
  521. tXinyiRobot.setTestDate(date);//日期
  522. tXinyiRobot.setTestHour(date + " " + time.substring(0, 2));//小时
  523. tXinyiRobot.setTestTime(date + " " + time.substring(0, 5));//分钟
  524. tXinyiRobot.setCreatedTime(new Date());
  525. //2024年5月29日10:33:32 额外处理几个新增的字段 多个池子数据合并一个
  526. List<BigDecimal> extraList = new ArrayList<>();
  527. extraList.add(tXinyiRobot.getNo3Hlj1Jqr());
  528. extraList.add(tXinyiRobot.getNo3Hlj2Jqr());
  529. tXinyiRobot.setHycxsyAll(JSON.toJSONString(extraList));
  530. extraList.clear();
  531. extraList.add(tXinyiRobot.getNh31Jqr());
  532. extraList.add(tXinyiRobot.getNh32Jqr());
  533. tXinyiRobot.setQyanAll(JSON.toJSONString(extraList));
  534. extraList.clear();
  535. extraList.add(tXinyiRobot.getNo3Qyc1Jqr());
  536. extraList.add(tXinyiRobot.getNo3Qyc2Jqr());
  537. tXinyiRobot.setQyckxsyAll(JSON.toJSONString(extraList));
  538. extraList.clear();
  539. extraList.add(tXinyiRobot.getTpHl1Jqr());
  540. extraList.add(tXinyiRobot.getTpHl2Jqr());
  541. tXinyiRobot.setHyzlsyAll(JSON.toJSONString(extraList));
  542. //按照小时填充集合 然后处理报警相关逻辑
  543. //2024年6月17日13:32:59 因为机器人化验室数据基本几个小时的都一致 改成一小时取一次
  544. needHandleList.add(tXinyiRobot);
  545. // this.xinyiRobotMapper.insertTXinyiRobot(tXinyiRobot);
  546. }
  547. }
  548. if(!CollectionUtils.isEmpty(needHandleList)){
  549. List<TXinyiRobot> uniqueList = needHandleList.stream()
  550. .collect(Collectors.collectingAndThen(
  551. Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(TXinyiRobot::getTestHour))),
  552. ArrayList::new
  553. ));
  554. if(!CollectionUtils.isEmpty(uniqueList))
  555. for (TXinyiRobot tXinyiRobot : uniqueList) {
  556. //判断是否添加过了(小时)
  557. String testHour = tXinyiRobot.getTestHour();
  558. List<TXinyiRobot> tXinyiRobotList = this.xinyiRobotMapper.selectTXinyiRobotList(TXinyiRobot.builder().testHour(testHour).build());
  559. if(CollectionUtils.isEmpty(tXinyiRobotList)){
  560. this.xinyiRobotMapper.insertTXinyiRobot(tXinyiRobot);
  561. //2024年6月18日10:45:20 额外计算一下预测的准确度
  562. asyncTask.updateForecastComparisonByRobot(tXinyiRobot);
  563. }
  564. else
  565. log.info("{}已经吧保存过了,无需重复保存***&&&···", testHour);
  566. }
  567. asyncTask.handleRobotWarning(uniqueList);
  568. }
  569. }
  570. /**
  571. *
  572. * 定时生成每日简报数据
  573. *
  574. */
  575. public void generateShortReport(){
  576. log.info("进入了定时生成每日简报数据");
  577. List<TXinyiDaily> dailyTwoRecords = this.xinyiDailyMapper.selectNRecords(DAILY_REPORT_COUNT_RECORD);
  578. //正常不会有这种问题 因为日报有很多条
  579. if(CollectionUtils.isEmpty(dailyTwoRecords) || dailyTwoRecords.size() < DAILY_REPORT_COUNT_RECORD){
  580. log.error("进入了定时生成每日简报数据 获取最新的{}条数据不足,终止", DAILY_REPORT_COUNT_RECORD);
  581. return;
  582. }
  583. //暂时不考虑因为没有填写日报 导致生成重复数据的问题(后续需要的话再添加)
  584. //处理数据 并 拼装
  585. String queryData = buildShortReportQueryDataNew(dailyTwoRecords);
  586. log.info("定时生成简报,组装好的请求大模型的参数为:{}", queryData);
  587. if(StringUtils.isBlank(queryData)){
  588. log.error("无法拼装请求数据!!!!!!");
  589. return;
  590. }
  591. String showVal = formateDateStr(dailyTwoRecords.get(0).getTestDate()) + JIAN_BAO_END;
  592. //调用模型 并保存结果
  593. this.askBigModel(queryData, showVal);
  594. log.info("定时生成简报任务结束~~~~~~~~~~~~~~");
  595. }
  596. /**
  597. *
  598. * 每小时发一一次预测
  599. *
  600. */
  601. public void predictor(){
  602. //获取最新的6条工业科数据
  603. List<TXinyiIndustry> tXinyiIndustries6 = this.xinyiIndustryMapper.selectNIndustry(6);
  604. List<TXinyiRobot> tXinyiRobots6 = this.xinyiRobotMapper.selectNRobot(6);
  605. //先处理xsy1 和 xsy2 合并成一个数据
  606. this.predictorSpecial(tXinyiIndustries6, tXinyiRobots6);
  607. for (int i = 0; i < predictorArr.length; i++) {
  608. String result = getPredictor(predictorArr[i]);
  609. if(StringUtils.isBlank(result) || "error".equals(result)){
  610. log.info("预测数据返回结果不符合解析条件,返回结果为{}", result);
  611. continue;
  612. }
  613. JSONObject jsonObject = null;
  614. try {
  615. jsonObject = JSON.parseObject(result);
  616. } catch (Exception e) {
  617. log.error("[转JSON的时候]预测数据返回结果不符合解析条件,返回结果为{}", result);
  618. continue;
  619. }
  620. String task = jsonObject.getString("task");
  621. String hour = jsonObject.getString("hour");
  622. String pred = jsonObject.getString("pred");
  623. String date = jsonObject.getString("date");
  624. if(StringUtils.isNotBlank(pred) && pred.contains(",")){
  625. String[] split = pred.split(",");
  626. if(split.length != 3){
  627. log.error("预测数据返回结果为{},长度不是3,无法正常解析", result);
  628. //因为部分预测还不支持 所以不需要
  629. // handleXinYiWarningsYC(cscodBzz, split, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_COD_YC.getCode(), hour, normConfig);
  630. continue;
  631. }
  632. //解析数据 处理报警 调研prompt 保存等
  633. this.handlePredictorWarning(split, hour, task, tXinyiIndustries6, tXinyiRobots6, date);
  634. }else {
  635. log.error("预测数据返回结果为{},无法正常解析", result);
  636. }
  637. }
  638. }
  639. private void predictorSpecial(List<TXinyiIndustry> tXinyiIndustries6, List<TXinyiRobot> tXinyiRobots6) {
  640. //数据1
  641. String result1 = getPredictor(predictorArrSpecial[0]);
  642. if(StringUtils.isBlank(result1) || "error".equals(result1)){
  643. log.info("预测数据返回结果不符合解析条件,返回结果为{}", result1);
  644. return;
  645. }
  646. JSONObject jsonObject1 = null;
  647. try {
  648. jsonObject1 = JSON.parseObject(result1);
  649. } catch (Exception e) {
  650. log.error("[转JSON的时候]预测数据返回结果不符合解析条件,返回结果为{}", result1);
  651. return;
  652. }
  653. String hour1 = jsonObject1.getString("hour");
  654. String pred1 = jsonObject1.getString("pred");
  655. String date1 = jsonObject1.getString("date");
  656. //数据2
  657. String result2 = getPredictor(predictorArrSpecial[0]);
  658. if(StringUtils.isBlank(result2) || "error".equals(result2)){
  659. log.info("预测数据返回结果不符合解析条件,返回结果为{}", result2);
  660. return;
  661. }
  662. JSONObject jsonObject2 = null;
  663. try {
  664. jsonObject2 = JSON.parseObject(result2);
  665. } catch (Exception e) {
  666. log.error("[转JSON的时候]预测数据返回结果不符合解析条件,返回结果为{}", result2);
  667. return;
  668. }
  669. String pred2 = jsonObject2.getString("pred");
  670. if(StringUtils.isNotBlank(pred1) && pred1.contains(",") && StringUtils.isNotBlank(pred2) && pred2.contains(",")){
  671. String[] split1 = pred1.split(",");
  672. String[] split2 = pred2.split(",");
  673. if(split1.length != 3 || split2.length != 3){
  674. return;
  675. }
  676. //构建两个的平均值
  677. String[] splitNew = new String[3];
  678. for (int i = 0; i < split1.length; i++) {
  679. splitNew[i] = String.valueOf((Double.parseDouble(split1[i]) + Double.parseDouble(split2[i]))/2/0.8);
  680. }
  681. log.info("取完平均值再组装的数组为{}", Arrays.toString(splitNew));
  682. //解析数据 处理报警 调研prompt 保存等
  683. this.handlePredictorWarningSpecialTn(splitNew, hour1, "tn", tXinyiIndustries6, tXinyiRobots6, date1);
  684. }else {
  685. log.error("预测数据返回结果为{}和{},无法正常解析", result1, result2);
  686. }
  687. }
  688. private void handlePredictorWarningSpecialTn(String[] split, String hour, String task, List<TXinyiIndustry> tXinyiIndustries6, List<TXinyiRobot> tXinyiRobots6, String date) {
  689. String[] hours = hour.split(",");
  690. //2024年6月23日18:28:55 因为存在跨天问题 所以日期也是逗号拼接的
  691. String[] dates = date.split(",");
  692. //2024年6月18日13:41:10 统一格式,否则查询不到结果
  693. //2024年6月18日10:36:49 增加预测记录,预测准确度计算等
  694. TXinyiForecastComparison tXinyiForecastComparison = new TXinyiForecastComparison();
  695. tXinyiForecastComparison.setCategory(task);
  696. tXinyiForecastComparison.setForecastTimeOne(dates[0].replaceAll("-", "/") + " " + hours[0]);
  697. tXinyiForecastComparison.setForecastTimeTwo(dates[1].replaceAll("-", "/") + " " + hours[1]);
  698. tXinyiForecastComparison.setForecastTimeThree(dates[2].replaceAll("-", "/") + " " + hours[2]);
  699. tXinyiForecastComparison.setHsForecastOne(new BigDecimal(split[0]));
  700. tXinyiForecastComparison.setHsForecastTwo(new BigDecimal(split[1]));
  701. tXinyiForecastComparison.setHsForecastThree(new BigDecimal(split[2]));
  702. //2024年6月20日14:28:31 增加字段,方便查询
  703. tXinyiForecastComparison.setRemark(DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYYMMDDHH_TS));
  704. //防止工业库挂掉以后持续预测同一数据
  705. //2024年6月20日14:59:23 因为预测bug 判断是否生成过了否则不生成
  706. String remark = tXinyiForecastComparison.getRemark();
  707. String category = tXinyiForecastComparison.getCategory();
  708. TXinyiForecastComparison tXinyiForecastComparisonReq = new TXinyiForecastComparison();
  709. tXinyiForecastComparisonReq.setRemark(remark);
  710. tXinyiForecastComparisonReq.setCategory(category);
  711. List<TXinyiForecastComparison> tXinyiForecastComparisons = this.xinyiForecastComparisonService.selectTXinyiForecastComparisonList(tXinyiForecastComparisonReq);
  712. if(!CollectionUtils.isEmpty(tXinyiForecastComparisons)){
  713. log.error("预测已经进行过了,无需重复运行~~~~~~~~~~~@@@@@@@,时间为{}\n类型为{}", remark, category);
  714. return;
  715. }
  716. //获取配置表
  717. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  718. if(CollectionUtils.isEmpty(tXinyiNormConfigs)) {
  719. log.error( "未查询到配置信息");
  720. return;
  721. }
  722. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  723. //获取最新的工业库的数据
  724. TXinyiIndustry tXinyiIndustry = this.xinyiIndustryMapper.selectTXinyiIndustryNewest();
  725. List<ChartBasic> chartsDataList = new ArrayList<>(9);
  726. //同时调用跃渊的预测接口 保存记录值
  727. try {
  728. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=3&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  729. if(!StringUtils.isBlank(result)){
  730. JSONArray array = JSON.parseArray(result);
  731. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  732. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  733. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  734. }
  735. } catch (Exception e) {
  736. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  737. }
  738. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  739. BigDecimal cscodBzz = normConfig.getCscodBzz();
  740. BigDecimal cscodGkz = normConfig.getCscodGkz();
  741. //处理展示数据
  742. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  743. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  744. ChartBasic chartBasic = new ChartBasic();
  745. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  746. //todo 2024年6月25日10:09:24 目前就存放工业库的,后续看是否调整取化验室的
  747. chartBasic.setVal(tXinyiIndustryTemp.getCsTn());
  748. chartsDataList.add(chartBasic);
  749. }
  750. for (int i = 0; i < split.length; i++) {
  751. String val = split[i];
  752. ChartBasic chartBasic = new ChartBasic();
  753. chartBasic.setTime(hours[i]);
  754. chartBasic.setVal(new BigDecimal(val));
  755. chartsDataList.add(chartBasic);
  756. }
  757. handleXinYiWarningsYC(cscodBzz, split, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_TN_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsTn(), tXinyiIndustry, chartsDataList, date);
  758. //插入到数据库
  759. //2024年6月21日14:18:55 如果红杉预测和跃渊预测都有数据再保存
  760. if(Objects.isNull(tXinyiForecastComparison.getHsForecastOne()) || Objects.isNull(tXinyiForecastComparison.getHsForecastTwo()) ||Objects.isNull(tXinyiForecastComparison.getHsForecastThree())
  761. || Objects.isNull(tXinyiForecastComparison.getYyForecastOne()) || Objects.isNull(tXinyiForecastComparison.getYyForecastTwo()) || Objects.isNull(tXinyiForecastComparison.getYyForecastThree())){
  762. log.error("保存预测对比数据时,有存在不满足条件的数据,不再保存数据,数据为{}", JSON.toJSONString(tXinyiForecastComparison));
  763. }else
  764. this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  765. }
  766. private void handlePredictorWarning(String[] split, String hour, String task, List<TXinyiIndustry> tXinyiIndustries6, List<TXinyiRobot> tXinyiRobots6, String date) {
  767. String[] hours = hour.split(",");
  768. //2024年6月23日18:28:55 因为存在跨天问题 所以日期也是逗号拼接的
  769. String[] dates = date.split(",");
  770. //2024年6月18日13:41:10 统一格式,否则查询不到结果
  771. //2024年6月18日10:36:49 增加预测记录,预测准确度计算等
  772. TXinyiForecastComparison tXinyiForecastComparison = new TXinyiForecastComparison();
  773. tXinyiForecastComparison.setCategory(task);
  774. tXinyiForecastComparison.setForecastTimeOne(dates[0].replaceAll("-", "/") + " " + hours[0]);
  775. tXinyiForecastComparison.setForecastTimeTwo(dates[1].replaceAll("-", "/") + " " + hours[1]);
  776. tXinyiForecastComparison.setForecastTimeThree(dates[2].replaceAll("-", "/") + " " + hours[2]);
  777. tXinyiForecastComparison.setHsForecastOne(new BigDecimal(split[0]));
  778. tXinyiForecastComparison.setHsForecastTwo(new BigDecimal(split[1]));
  779. tXinyiForecastComparison.setHsForecastThree(new BigDecimal(split[2]));
  780. //2024年6月20日14:28:31 增加字段,方便查询
  781. tXinyiForecastComparison.setRemark(DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYYMMDDHH_TS));
  782. //防止工业库挂掉以后持续预测同一数据
  783. //2024年6月20日14:59:23 因为预测bug 判断是否生成过了否则不生成
  784. String remark = tXinyiForecastComparison.getRemark();
  785. String category = tXinyiForecastComparison.getCategory();
  786. TXinyiForecastComparison tXinyiForecastComparisonReq = new TXinyiForecastComparison();
  787. tXinyiForecastComparisonReq.setRemark(remark);
  788. tXinyiForecastComparisonReq.setCategory(category);
  789. List<TXinyiForecastComparison> tXinyiForecastComparisons = this.xinyiForecastComparisonService.selectTXinyiForecastComparisonList(tXinyiForecastComparisonReq);
  790. if(!CollectionUtils.isEmpty(tXinyiForecastComparisons)){
  791. log.error("预测已经进行过了,无需重复运行~~~~~~~~~~~@@@@@@@,时间为{}\n类型为{}", remark, category);
  792. return;
  793. }
  794. //获取配置表
  795. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  796. if(CollectionUtils.isEmpty(tXinyiNormConfigs)) {
  797. log.error( "未查询到配置信息");
  798. return;
  799. }
  800. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  801. //获取最新的工业库的数据
  802. TXinyiIndustry tXinyiIndustry = this.xinyiIndustryMapper.selectTXinyiIndustryNewest();
  803. List<ChartBasic> chartsDataList = new ArrayList<>(9);
  804. if("cod".equals(task)){
  805. //同时调用跃渊的预测接口 保存记录值
  806. try {
  807. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=2&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  808. if(!StringUtils.isBlank(result)){
  809. JSONArray array = JSON.parseArray(result);
  810. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  811. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  812. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  813. }
  814. } catch (Exception e) {
  815. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  816. }
  817. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  818. BigDecimal cscodBzz = normConfig.getCscodBzz();
  819. BigDecimal cscodGkz = normConfig.getCscodGkz();
  820. //处理展示数据
  821. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  822. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  823. ChartBasic chartBasic = new ChartBasic();
  824. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  825. //2024年6月25日10:10:38 bug修改,需要判断类型赋不同的值
  826. if("tn".equals(category))//这种情况没有了
  827. chartBasic.setVal(tXinyiIndustryTemp.getCsTn());
  828. if("cod".equals(category))
  829. chartBasic.setVal(tXinyiIndustryTemp.getCsCod());
  830. if("ss".equals(category))
  831. chartBasic.setVal(tXinyiIndustryTemp.getCsSs());
  832. if("tp".equals(category))
  833. chartBasic.setVal(tXinyiIndustryTemp.getCsTp());
  834. if("nh3".equals(category))
  835. chartBasic.setVal(tXinyiIndustryTemp.getCsNh3());
  836. chartsDataList.add(chartBasic);
  837. }
  838. for (int i = 0; i < split.length; i++) {
  839. String val = split[i];
  840. ChartBasic chartBasic = new ChartBasic();
  841. chartBasic.setTime(hours[i]);
  842. chartBasic.setVal(new BigDecimal(val));
  843. chartsDataList.add(chartBasic);
  844. }
  845. handleXinYiWarningsYC(cscodBzz, split, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_COD_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsCod(), tXinyiIndustry, chartsDataList, date);
  846. }else if("ss".equals(task)){
  847. //同时调用跃渊的预测接口 保存记录值
  848. try {
  849. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=5&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  850. if(!StringUtils.isBlank(result)){
  851. JSONArray array = JSON.parseArray(result);
  852. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  853. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  854. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  855. }
  856. } catch (Exception e) {
  857. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  858. }
  859. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  860. BigDecimal csSSBzz = normConfig.getCsssBzz();
  861. BigDecimal csssGkz = normConfig.getCsssGkz();
  862. //处理展示数据
  863. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  864. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  865. ChartBasic chartBasic = new ChartBasic();
  866. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  867. chartBasic.setVal(tXinyiIndustryTemp.getCsSs());
  868. chartsDataList.add(chartBasic);
  869. }
  870. for (int i = 0; i < split.length; i++) {
  871. String val = split[i];
  872. ChartBasic chartBasic = new ChartBasic();
  873. chartBasic.setTime(hours[i]);
  874. chartBasic.setVal(new BigDecimal(val));
  875. chartsDataList.add(chartBasic);
  876. }
  877. handleXinYiWarningsYC(csSSBzz, split, csssGkz, BusinessEnum.WarningCategoryEnum.CS_SS_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsSs(), tXinyiIndustry, chartsDataList, date);
  878. }/*else if("tn".equals(task)){
  879. //同时调用跃渊的预测接口 保存记录值
  880. try {
  881. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=3&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  882. if(!StringUtils.isBlank(result)){
  883. JSONArray array = JSON.parseArray(result);
  884. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  885. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  886. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  887. }
  888. } catch (Exception e) {
  889. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  890. }
  891. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  892. BigDecimal cszzBzz = normConfig.getCszzBzz();
  893. BigDecimal cszzGkz = normConfig.getCszzGkz();
  894. //处理展示数据
  895. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  896. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  897. ChartBasic chartBasic = new ChartBasic();
  898. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  899. chartBasic.setVal(tXinyiIndustryTemp.getCsTn());
  900. chartsDataList.add(chartBasic);
  901. }
  902. for (int i = 0; i < split.length; i++) {
  903. String val = split[i];
  904. ChartBasic chartBasic = new ChartBasic();
  905. chartBasic.setTime(hours[i]);
  906. chartBasic.setVal(new BigDecimal(val));
  907. chartsDataList.add(chartBasic);
  908. }
  909. handleXinYiWarningsYC(cszzBzz, split, cszzGkz, BusinessEnum.WarningCategoryEnum.CS_TN_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsCod(), tXinyiIndustry, chartsDataList, date);
  910. }*/else if("tp".equals(task)){
  911. //同时调用跃渊的预测接口 保存记录值
  912. try {
  913. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=1&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  914. if(!StringUtils.isBlank(result)){
  915. JSONArray array = JSON.parseArray(result);
  916. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  917. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  918. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  919. }
  920. } catch (Exception e) {
  921. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  922. }
  923. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  924. BigDecimal cszlBzz = normConfig.getCszlBzz();
  925. BigDecimal cszlGkz = normConfig.getCszlGkz();
  926. //处理展示数据
  927. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  928. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  929. ChartBasic chartBasic = new ChartBasic();
  930. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  931. chartBasic.setVal(tXinyiIndustryTemp.getCsTp());
  932. chartsDataList.add(chartBasic);
  933. }
  934. for (int i = 0; i < split.length; i++) {
  935. String val = split[i];
  936. ChartBasic chartBasic = new ChartBasic();
  937. chartBasic.setTime(hours[i]);
  938. chartBasic.setVal(new BigDecimal(val));
  939. chartsDataList.add(chartBasic);
  940. }
  941. handleXinYiWarningsYC(cszlBzz, split, cszlGkz, BusinessEnum.WarningCategoryEnum.CS_TP_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsTp(), tXinyiIndustry, chartsDataList, date);
  942. }else if("nh3".equals(task)){
  943. //同时调用跃渊的预测接口 保存记录值
  944. try {
  945. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=4&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  946. if(!StringUtils.isBlank(result)){
  947. JSONArray array = JSON.parseArray(result);
  948. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  949. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  950. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  951. }
  952. } catch (Exception e) {
  953. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  954. }
  955. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  956. BigDecimal csadBzz = normConfig.getCsadBzz();
  957. BigDecimal csadGkz = normConfig.getCsadGkz();
  958. //处理展示数据
  959. for (int i = 0; i < tXinyiIndustries6.size(); i++) {
  960. TXinyiIndustry tXinyiIndustryTemp = tXinyiIndustries6.get(5 - i);
  961. ChartBasic chartBasic = new ChartBasic();
  962. chartBasic.setTime(tXinyiIndustryTemp.getTestHour().substring(11));
  963. chartBasic.setVal(tXinyiIndustryTemp.getCsNh3());
  964. chartsDataList.add(chartBasic);
  965. }
  966. for (int i = 0; i < split.length; i++) {
  967. String val = split[i];
  968. ChartBasic chartBasic = new ChartBasic();
  969. chartBasic.setTime(hours[i]);
  970. chartBasic.setVal(new BigDecimal(val));
  971. chartsDataList.add(chartBasic);
  972. }
  973. handleXinYiWarningsYC(csadBzz, split, csadGkz, BusinessEnum.WarningCategoryEnum.CS_AD_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsNh3(), tXinyiIndustry, chartsDataList, date);
  974. }/*else if("xsy1".equals(task)){
  975. //2024年6月21日14:57:02 红杉的出水总氮预测改成 不用工业库的,用化验科的两个xsy 相关指标
  976. //同时调用跃渊的预测接口 保存记录值
  977. try {
  978. String result = HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=3&time=" + DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH));
  979. if(!StringUtils.isBlank(result)){
  980. JSONArray array = JSON.parseArray(result);
  981. tXinyiForecastComparison.setYyForecastOne(array.getBigDecimal(6));
  982. tXinyiForecastComparison.setYyForecastTwo(array.getBigDecimal(7));
  983. tXinyiForecastComparison.setYyForecastThree(array.getBigDecimal(8));
  984. }
  985. } catch (Exception e) {
  986. log.error("调用跃渊的预测接口出现异常,异常信息为{}", e.getMessage());
  987. }
  988. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  989. BigDecimal cscodBzz = new BigDecimal(XIAOSUANYAN_BZK);
  990. BigDecimal cscodGkz = new BigDecimal(XIAOSUANYAN_GKZ);
  991. //处理展示数据
  992. for (int i = 0; i < tXinyiRobots6.size(); i++) {
  993. TXinyiRobot tXinyiRobotTemp = tXinyiRobots6.get(5 - i);
  994. ChartBasic chartBasic = new ChartBasic();
  995. chartBasic.setTime(tXinyiRobotTemp.getTestHour().substring(11));
  996. chartBasic.setVal(tXinyiRobotTemp.getNo3Hlj1Jqr());
  997. chartsDataList.add(chartBasic);
  998. }
  999. for (int i = 0; i < split.length; i++) {
  1000. String val = split[i];
  1001. ChartBasic chartBasic = new ChartBasic();
  1002. chartBasic.setTime(hours[i]);
  1003. chartBasic.setVal(new BigDecimal(val));
  1004. chartsDataList.add(chartBasic);
  1005. }
  1006. handleXinYiWarningsYC(cscodBzz, split, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_XSY_1_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsCod(), tXinyiIndustry, chartsDataList, date);
  1007. }else if("xsy2".equals(task)){
  1008. // this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  1009. BigDecimal cscodBzz = new BigDecimal(XIAOSUANYAN_BZK);
  1010. BigDecimal cscodGkz = new BigDecimal(XIAOSUANYAN_GKZ);
  1011. //处理展示数据
  1012. for (int i = 0; i < tXinyiRobots6.size(); i++) {
  1013. TXinyiRobot tXinyiRobotTemp = tXinyiRobots6.get(5 - i);
  1014. ChartBasic chartBasic = new ChartBasic();
  1015. chartBasic.setTime(tXinyiRobotTemp.getTestHour().substring(11));
  1016. chartBasic.setVal(tXinyiRobotTemp.getNo3Hlj2Jqr());
  1017. chartsDataList.add(chartBasic);
  1018. }
  1019. for (int i = 0; i < split.length; i++) {
  1020. String val = split[i];
  1021. ChartBasic chartBasic = new ChartBasic();
  1022. chartBasic.setTime(hours[i]);
  1023. chartBasic.setVal(new BigDecimal(val));
  1024. chartsDataList.add(chartBasic);
  1025. }
  1026. handleXinYiWarningsYC(cscodBzz, split, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_XSY_2_YC.getCode(), hour, normConfig,tXinyiIndustry.getCsCod(), tXinyiIndustry, chartsDataList, date);
  1027. }*/else {
  1028. log.error("暂未支持的类型{}", task);
  1029. }
  1030. //插入到数据库
  1031. //2024年6月21日14:18:55 如果红杉预测和跃渊预测都有数据再保存
  1032. if(Objects.isNull(tXinyiForecastComparison.getHsForecastOne()) || Objects.isNull(tXinyiForecastComparison.getHsForecastTwo()) ||Objects.isNull(tXinyiForecastComparison.getHsForecastThree())
  1033. || Objects.isNull(tXinyiForecastComparison.getYyForecastOne()) || Objects.isNull(tXinyiForecastComparison.getYyForecastTwo()) || Objects.isNull(tXinyiForecastComparison.getYyForecastThree())){
  1034. log.error("保存预测对比数据时,有存在不满足条件的数据,不再保存数据,数据为{}", JSON.toJSONString(tXinyiForecastComparison));
  1035. }else
  1036. this.xinyiForecastComparisonService.insertTXinyiForecastComparison(tXinyiForecastComparison);
  1037. }
  1038. private void handleXinYiWarningsYC(BigDecimal csBzz, String[] split, BigDecimal csGkz, String category, String hour, TXinyiNormConfig normConfig, BigDecimal currentVal, TXinyiIndustry tXinyiIndustry, List<ChartBasic> chartsDataList, String date) {
  1039. BigDecimal multiply = csBzz.multiply(new BigDecimal(MyConstants.SCALE_VALUE));
  1040. TXinyiWarningRecord tXinyiWarningRecord = null;
  1041. String yjHour = null;
  1042. for (int i = 0, splitLength = split.length; i < splitLength; i++) {
  1043. String forecast = split[i];
  1044. /*BigDecimal forecastVal = new BigDecimal("10000");*/
  1045. BigDecimal forecastVal = new BigDecimal(forecast);
  1046. tXinyiWarningRecord = new TXinyiWarningRecord();
  1047. /*String category = BusinessEnum.WarningCategoryEnum.CS_AD.getCode();*/
  1048. tXinyiWarningRecord.setStatus(0);
  1049. tXinyiWarningRecord.setType(2);
  1050. tXinyiWarningRecord.setCategory(category);
  1051. tXinyiWarningRecord.setWarningVal(currentVal);//当前值
  1052. tXinyiWarningRecord.setForecastVal(forecastVal);
  1053. tXinyiWarningRecord.setDesignVal(csBzz);
  1054. tXinyiWarningRecord.setControlVal(csGkz);
  1055. tXinyiWarningRecord.setCreateBy(WARNING_DEFAULT_CREATE);
  1056. tXinyiWarningRecord.setCreateTime(DateUtils.getNowDate());
  1057. tXinyiWarningRecord.setRemark("2");
  1058. //2024年5月25日17:52:33 如果工业库获取不到数据,也触发报警,但是不调用决策接口
  1059. if (Objects.isNull(forecastVal)) {
  1060. tXinyiWarningRecord.setReason(category + EXCEPTION_WARNING_YC);
  1061. tXinyiWarningRecord.setLevel(WARNING_LEVEL_NO_DATE);
  1062. } else if (forecastVal.compareTo(multiply) > 0) {//一级
  1063. tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING_YC);
  1064. tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
  1065. } else if (forecastVal.compareTo(csBzz) >= 0 && forecastVal.compareTo(multiply) <= 0) {//二级
  1066. tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING_YC);
  1067. tXinyiWarningRecord.setLevel(WARNING_LEVEL_TWO);
  1068. } else if (!Objects.isNull(csGkz) && forecastVal.compareTo(csGkz) > 0) {
  1069. tXinyiWarningRecord.setReason(category + CHAOGUANKONG_WARNING_YC);
  1070. tXinyiWarningRecord.setLevel(WARNING_LEVEL_THREE);
  1071. } else {
  1072. tXinyiWarningRecord = null;//这种的无需处理
  1073. }
  1074. if (!Objects.isNull(tXinyiWarningRecord)) {
  1075. log.info("预测报警中出现了超标的情况,循环可以退出了");
  1076. yjHour = hour.split(",")[i];
  1077. date = date.split(",")[i];//2024年6月23日18:34:49 日期也是多个了
  1078. //预计超标时间 不是当前值,是预测超标的时间。
  1079. try {
  1080. tXinyiWarningRecord.setTime(DateUtils.parseDate(date + " " + yjHour, DateUtils.YYYY_MM_DD_HH));
  1081. } catch (ParseException e) {
  1082. log.error("处理语句的预计超标时间是,异常,异常信息为{}", e.getMessage());
  1083. }
  1084. break;
  1085. }
  1086. }
  1087. //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
  1088. List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().delFlag(0).type(2).category(category).warningStatus(0).build());
  1089. if(Objects.isNull(tXinyiWarningRecord)){//数据正常,无告警信息
  1090. if(!CollectionUtils.isEmpty(tXinyiWarningRecords)){
  1091. log.info( "{}:现在恢复正常,历史报警数据为{}", category,JSON.toJSONString(tXinyiWarningRecords));
  1092. for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {
  1093. xinyiWarningRecord.setStatus(2);
  1094. Date nowDate = DateUtils.getNowDate();
  1095. xinyiWarningRecord.setOffTime(nowDate);
  1096. xinyiWarningRecord.setUpdateTime(nowDate);
  1097. xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
  1098. this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
  1099. }
  1100. }
  1101. }else{//有告警信息
  1102. //2024年6月27日10:45:49 列表的预警时间和showval里的预警时间保持一致(用同一个,否则可能有一分钟左右的误差)
  1103. Date nowDate = DateUtils.getNowDate();
  1104. if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
  1105. //保存到数据库中
  1106. this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
  1107. if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
  1108. //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
  1109. this.addChatRecordByDeviceErr(tXinyiWarningRecord, tXinyiIndustry, normConfig);
  1110. }else {
  1111. //继续调用大模型prompt
  1112. this.askBigModelForYC(tXinyiWarningRecord, tXinyiIndustry, normConfig, chartsDataList, date, yjHour, nowDate);
  1113. }
  1114. }else{
  1115. log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
  1116. for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
  1117. if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
  1118. //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
  1119. this.addChatRecordByDeviceErr(tXinyiWarningRecord, tXinyiIndustry, normConfig);
  1120. }else {
  1121. //2024年6月25日11:32:13 预测的相对特殊:因为前端不展示次数,所以这里把 超标时间+现在值+预测值更新一下
  1122. xinyiWarningRecord.setForecastVal(tXinyiWarningRecord.getForecastVal());
  1123. xinyiWarningRecord.setWarningVal(currentVal);
  1124. xinyiWarningRecord.setTime(tXinyiWarningRecord.getTime());
  1125. xinyiWarningRecord.setUpdateTime(nowDate);
  1126. xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
  1127. //更新数据库
  1128. this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
  1129. //继续调用决策
  1130. this.askBigModelForYC(xinyiWarningRecord, tXinyiIndustry, normConfig, chartsDataList, date, yjHour, nowDate);
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. private void askBigModelForYC(TXinyiWarningRecord xinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, List<ChartBasic> chartsDataList, String date, String yjHour, Date nowDate) {
  1137. log.info("预测进入了后台接口调⽤⼤模型获取问答结果处理(预测)");
  1138. StringBuilder sb = new StringBuilder();
  1139. String sessionId = IdUtils.simpleUUID();
  1140. ChatReq chatReq = new ChatReq();
  1141. // String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
  1142. String ipAddr = "";//获取用户的ip地址 传给大模型 定时任务获取不到ip地址
  1143. int counts = 1;//默认是第一次
  1144. //这种问答 没有历史问答的概念 直接把问题扔进去就行 无需查询历史记录
  1145. List<String> historyDates = new ArrayList<>();
  1146. //构建问题(替换提示词中的占位符)
  1147. String shWarningPrompt = YC_WARNING_PROMPT;
  1148. shWarningPrompt =shWarningPrompt.replace("#{0}", xinyiWarningRecord.getReason());
  1149. shWarningPrompt =shWarningPrompt.replace("#{1}", String.valueOf(DecimalUtils.getAbsAndScale(xinyiWarningRecord.getDesignVal(), INT_2)));
  1150. shWarningPrompt =shWarningPrompt.replace("#{2}", String.valueOf(DecimalUtils.getAbsAndScale(xinyiWarningRecord.getWarningVal(), INT_2)));
  1151. shWarningPrompt =shWarningPrompt.replace("#{3}", String.valueOf(DecimalUtils.getAbsAndScale(xinyiWarningRecord.getForecastVal(), INT_2)));
  1152. historyDates.add(shWarningPrompt);
  1153. // 获取输出流
  1154. ManagedChannel channel = null;
  1155. try {
  1156. channel = ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
  1157. .usePlaintext()
  1158. .build();
  1159. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  1160. // String dataJson = "{\"bot_id\":\"721\",\"exp_id\":\"721\",\"session_id\":\"" + sessionId + "\",\"use_rag\":\"true\",\"prompt\":\"你是⼀个资深⽔务领域专家,能回答各种⽔务相关问题\",\"history_dia\":" + JSON.toJSONString(historyDates) + ",\"generate_args\":{\"max_new_tokens\":2048,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{ \"ip_address\": \"" + ipAddr + "\" },\"strengthen\":" + (true) + "}";
  1161. //2024年6月27日10:51:47 优化:不再手动拼接JSON字符串
  1162. String dataJson = buildBigModelReqForChat(sessionId, historyDates);
  1163. log.info("请求大模型的问答参数为{}", dataJson);
  1164. PredictionsRequest request = PredictionsRequest.newBuilder()
  1165. .setModelName("slibra_bot")
  1166. .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
  1167. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  1168. .buildPartial();
  1169. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  1170. //将结果记录到问答表
  1171. while (predictions.hasNext()) {
  1172. String responseStr = predictions.next().getPrediction().toStringUtf8();
  1173. log.info("大模型问答返回的原始结果为{}", responseStr);
  1174. responseStr = JSON.parseObject(responseStr).getString("message");
  1175. if("complete".equals(responseStr)){
  1176. log.info("结尾语句并且是非JSON,无需处理");
  1177. }else{
  1178. sb.append(responseStr);
  1179. }
  1180. }
  1181. //将问答更新到数据库中
  1182. chatReq.setSessionId(sessionId);
  1183. chatReq.setType(1);//0问答 1决策 2本地 3仿真预测 预测报警这里也算是决策 仿真预测是在调用仿真那里使用的
  1184. chatReq.setModule(3);//0专家问答 1智能工单 2智能体助手 3告警 4简报
  1185. String showVal = this.buildShowValueWithCharts(xinyiWarningRecord, tXinyiIndustry, normConfig, chartsDataList, date, yjHour, nowDate);
  1186. chatReq.setShowVal(showVal);
  1187. chatReq.setQuestion(shWarningPrompt);
  1188. chatReq.setAnswer(sb.toString());
  1189. chatReq.setWarningId(String.valueOf(xinyiWarningRecord.getId()));
  1190. chatReq.setCounts(counts);//问答次数
  1191. chatReq.setUserId(WARNING_DEFAULT_CREATE);
  1192. chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
  1193. chatReq.setCreateTime(DateUtils.getNowDate());
  1194. this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
  1195. } catch (IOException e) {
  1196. throw new RuntimeException(e);
  1197. } finally {
  1198. // 关闭输出流
  1199. channel.shutdown();
  1200. }
  1201. }
  1202. private static String buildBigModelReqForChat(String sessionId, List<String> historyDates) {
  1203. ChatRequest chatRequest = new ChatRequest();
  1204. chatRequest.setSessionId(sessionId);
  1205. chatRequest.setHistoryDia(historyDates);
  1206. Map<String, Object> extra = new HashMap<>();
  1207. extra.put("ip_address", IpUtils.getIpAddr());
  1208. chatRequest.setExtra(extra);
  1209. chatRequest.setStrengthen(true);
  1210. return JSON.toJSONString(chatRequest);
  1211. }
  1212. public static String getPredictor(String type){
  1213. // 获取输出流
  1214. ManagedChannel channel = null;
  1215. try {
  1216. channel = ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
  1217. .usePlaintext()
  1218. .build();
  1219. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  1220. // String dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"" + type + "\",\"session_id\":\" " + IdUtils.simpleUUID() + " \",\"extra\":{}}";
  1221. //2024年6月27日13:23:25 优化:改成非拼接JSON字符串
  1222. String dataJson = buildBigModelReqForPredictor(type);
  1223. log.info("请求大模型的预测的参数为{}", dataJson);
  1224. PredictionsRequest request = PredictionsRequest.newBuilder()
  1225. .setModelName("slibra_bot")
  1226. .putInput("method", ByteString.copyFrom("predictor", "utf-8"))//推理
  1227. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  1228. .buildPartial();
  1229. /*Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  1230. //将结果记录到问答表
  1231. String responseStr = predictions.next().getPrediction().toStringUtf8();
  1232. log.info("大模型的预测的返回结果为{}", responseStr);*/
  1233. //2024年6月21日11:46:36 改成非流式输出
  1234. PredictionResponse predictions = stub.predictions(request);
  1235. String responseStr = predictions.getPrediction().toStringUtf8();
  1236. log.info("大模型问答返回的原始结果为{}", responseStr);
  1237. // return JSON.parseObject(responseStr).getString("pred");
  1238. return responseStr;
  1239. } catch (IOException e) {
  1240. throw new RuntimeException(e);
  1241. } finally {
  1242. assert channel != null;
  1243. channel.shutdown();
  1244. }
  1245. }
  1246. private static String buildBigModelReqForPredictor(String type) {
  1247. PredictorRequest predictorRequest = new PredictorRequest();
  1248. predictorRequest.setNorm(type);
  1249. predictorRequest.setSessionId(IdUtils.simpleUUID());
  1250. return JSON.toJSONString(predictorRequest);
  1251. }
  1252. /**
  1253. *
  1254. * 2022/01/01 转成2022年01月01日 数据
  1255. * @param testDate
  1256. * @return
  1257. */
  1258. private String formateDateStr(String testDate) {
  1259. if(StringUtils.isBlank(testDate))
  1260. return "";
  1261. if(!testDate.contains("/"))
  1262. return testDate;
  1263. String[] split = testDate.split("/");
  1264. return split[0] + "年" + split[1] + "月" + split[2] + "日";
  1265. }
  1266. private void askBigModel(String question, String showVal) {
  1267. log.info("进入了后台接口调⽤⼤模型获取问答结果处理");
  1268. StringBuilder sb = new StringBuilder();
  1269. String sessionId = IdUtils.simpleUUID();
  1270. ChatReq chatReq = new ChatReq();
  1271. // String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
  1272. String ipAddr = "";//获取用户的ip地址 传给大模型 定时任务获取不到ip地址
  1273. int counts = 1;//默认是第一次
  1274. //这种问答 没有历史问答的概念 直接把问题扔进去就行 无需查询历史记录
  1275. List<String> historyDates = new ArrayList<>();
  1276. historyDates.add(question);
  1277. // 获取输出流
  1278. ManagedChannel channel = null;
  1279. try {
  1280. channel = ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
  1281. .usePlaintext()
  1282. .build();
  1283. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  1284. // String dataJson = "{\"bot_id\":\"721\",\"exp_id\":\"721\",\"session_id\":\"" + sessionId + "\",\"use_rag\":\"true\",\"prompt\":\"你是⼀个资深⽔务领域专家,能回答各种⽔务相关问题\",\"history_dia\":" + JSON.toJSONString(historyDates) + ",\"generate_args\":{\"max_new_tokens\":2048,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{ \"ip_address\": \"" + ipAddr + "\" },\"strengthen\":" + (true) + "}";
  1285. //2024年6月27日10:51:47 优化:不再手动拼接JSON字符串
  1286. String dataJson = buildBigModelReqForChat(sessionId, historyDates);
  1287. log.info("请求大模型的问答参数为{}", dataJson);
  1288. PredictionsRequest request = PredictionsRequest.newBuilder()
  1289. .setModelName("slibra_bot")
  1290. .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
  1291. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  1292. .buildPartial();
  1293. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  1294. //将结果记录到问答表
  1295. while (predictions.hasNext()) {
  1296. String responseStr = predictions.next().getPrediction().toStringUtf8();
  1297. log.info("大模型问答返回的原始结果为{}", responseStr);
  1298. responseStr = JSON.parseObject(responseStr).getString("message");
  1299. if("complete".equals(responseStr)){
  1300. System.out.println("结尾语句并且是非JSON,无需处理");
  1301. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  1302. /*outputStream.write(responseStr.getBytes());
  1303. outputStream.flush();*/
  1304. }else{
  1305. sb.append(responseStr);
  1306. }
  1307. }
  1308. //将问答更新到数据库中
  1309. chatReq.setSessionId(sessionId);
  1310. chatReq.setType(2);//0问答 1决策 2本地 3仿真预测
  1311. chatReq.setModule(4);//0专家问答 1智能工单 2智能体助手 3告警 4简报
  1312. chatReq.setShowVal(showVal);
  1313. chatReq.setQuestion(question);
  1314. chatReq.setAnswer(sb.toString());
  1315. chatReq.setCounts(counts);//问答次数
  1316. chatReq.setUserId(WARNING_DEFAULT_CREATE);
  1317. chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
  1318. chatReq.setCreateTime(DateUtils.getNowDate());
  1319. this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
  1320. } catch (IOException e) {
  1321. throw new RuntimeException(e);
  1322. } finally {
  1323. // 关闭输出流
  1324. channel.shutdown();
  1325. }
  1326. }
  1327. /**
  1328. * @see buildShortReportQueryDataNew
  1329. * @param dailyTwoRecords
  1330. * @return
  1331. */
  1332. @Deprecated
  1333. private String buildShortReportQueryData(List<TXinyiDaily> dailyTwoRecords) {
  1334. //查询配置信息
  1335. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  1336. if(CollectionUtils.isEmpty(tXinyiNormConfigs))
  1337. return null;
  1338. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  1339. //获取数据
  1340. TXinyiDaily yesterdayData = dailyTwoRecords.get(0);
  1341. TXinyiDaily beforeYesterdayData = dailyTwoRecords.get(1);
  1342. String originStr = JIAN_BAO_PROMPT;
  1343. String yesterdayStr = yesterdayData.getTestDate().substring(5).replace("/", "月") + "日";
  1344. String beforeYesterdayStr = beforeYesterdayData.getTestDate().substring(5).replace("/", "月") + "日";
  1345. originStr = originStr.replace("#{0}", yesterdayStr);
  1346. originStr = originStr.replace("#{1}", beforeYesterdayStr);
  1347. originStr = originStr.replace("#{2}", String.valueOf(yesterdayData.getJsCod()));
  1348. originStr = originStr.replace("#{3}", String.valueOf(yesterdayData.getJsTn()));
  1349. originStr = originStr.replace("#{4}", String.valueOf(yesterdayData.getJsTp()));
  1350. originStr = originStr.replace("#{5}", String.valueOf(yesterdayData.getJsNh3()));
  1351. originStr = originStr.replace("#{6}", String.valueOf(yesterdayData.getJsSs()));
  1352. originStr = originStr.replace("#{7}", String.valueOf(yesterdayData.getJSL()));
  1353. originStr = originStr.replace("#{8}", String.valueOf(yesterdayData.getCsCod()));
  1354. originStr = originStr.replace("#{9}", String.valueOf(yesterdayData.getCsTn()));
  1355. originStr = originStr.replace("#{10}", String.valueOf(yesterdayData.getCsTp()));
  1356. originStr = originStr.replace("#{11}", String.valueOf(yesterdayData.getCsNh3()));
  1357. originStr = originStr.replace("#{12}", String.valueOf(yesterdayData.getCsSs()));
  1358. originStr = originStr.replace("#{13}", String.valueOf(yesterdayData.getCSL()));
  1359. originStr = originStr.replace("#{14}", String.valueOf(beforeYesterdayData.getJsCod()));
  1360. originStr = originStr.replace("#{15}", String.valueOf(beforeYesterdayData.getJsTn()));
  1361. originStr = originStr.replace("#{16}", String.valueOf(beforeYesterdayData.getJsTp()));
  1362. originStr = originStr.replace("#{17}", String.valueOf(beforeYesterdayData.getJsNh3()));
  1363. originStr = originStr.replace("#{18}", String.valueOf(beforeYesterdayData.getJsSs()));
  1364. originStr = originStr.replace("#{19}", String.valueOf(beforeYesterdayData.getJSL()));
  1365. originStr = originStr.replace("#{20}", String.valueOf(beforeYesterdayData.getCsCod()));
  1366. originStr = originStr.replace("#{21}", String.valueOf(beforeYesterdayData.getCsTn()));
  1367. originStr = originStr.replace("#{22}", String.valueOf(beforeYesterdayData.getCsTp()));
  1368. originStr = originStr.replace("#{23}", String.valueOf(beforeYesterdayData.getCsNh3()));
  1369. originStr = originStr.replace("#{24}", String.valueOf(beforeYesterdayData.getCsSs()));
  1370. originStr = originStr.replace("#{25}", String.valueOf(beforeYesterdayData.getCSL()));
  1371. originStr = originStr.replace("#{26}", String.valueOf(normConfig.getJscodSjz()));
  1372. originStr = originStr.replace("#{27}", String.valueOf(normConfig.getJszdSjz()));
  1373. originStr = originStr.replace("#{28}", String.valueOf(normConfig.getJszlSjz()));
  1374. originStr = originStr.replace("#{29}", String.valueOf(normConfig.getJsadSjz()));
  1375. originStr = originStr.replace("#{30}", String.valueOf(normConfig.getJsssSjz()));
  1376. originStr = originStr.replace("#{31}", String.valueOf(normConfig.getCscodBzz()));
  1377. originStr = originStr.replace("#{32}", String.valueOf(normConfig.getCszzBzz()));
  1378. originStr = originStr.replace("#{33}", String.valueOf(normConfig.getCszlBzz()));
  1379. originStr = originStr.replace("#{34}", String.valueOf(normConfig.getCsadBzz()));
  1380. originStr = originStr.replace("#{35}", String.valueOf(normConfig.getCsssBzz()));
  1381. return originStr;
  1382. }
  1383. //2024年6月23日19:58:21 简报生成的prompt调整。
  1384. private String buildShortReportQueryDataNew(List<TXinyiDaily> dailyTwoRecords) {
  1385. //查询配置信息
  1386. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  1387. if(CollectionUtils.isEmpty(tXinyiNormConfigs))
  1388. return null;
  1389. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  1390. //获取数据
  1391. TXinyiDaily yesterdayData = dailyTwoRecords.get(0);
  1392. String originStr = SHORT_REPORT_BEGIN.replace("#{0}", yesterdayData.getTestDate());
  1393. StringBuilder sb = new StringBuilder(originStr);
  1394. for (TXinyiDaily dailyTwoRecord : dailyTwoRecords) {
  1395. sb.append(formateDateStr(dailyTwoRecord.getTestDate())).append("进出水质数据:\n");
  1396. sb.append("进水:\n");
  1397. sb.append("进水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsCod(), 2)).append("mg/L、");
  1398. sb.append("进水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTn(), 2)).append("mg/L、");
  1399. sb.append("进水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTp(), 2)).append("mg/L、");
  1400. sb.append("进水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsNh3(), 2)).append("mg/L、");
  1401. sb.append("进水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsSs(), 2)).append("mg/L、");
  1402. sb.append("进水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJSL(), 2)).append("m³/d").append(";\n");
  1403. sb.append("出水:\n");
  1404. sb.append("出水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsCod(), 2)).append("mg/L、");
  1405. sb.append("出水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTn(), 2)).append("mg/L、");
  1406. sb.append("出水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTp(), 2)).append("mg/L、");
  1407. sb.append("出水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsNh3(), 2)).append("mg/L、");
  1408. sb.append("出水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsSs(), 2)).append("mg/L、");
  1409. sb.append("出水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCSL(), 2)).append("m³/d").append("。\n");
  1410. }
  1411. sb.append(SHORT_REPORT_END);
  1412. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getJscodSjz(), 2)).append("mg/L、");
  1413. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJszdSjz(), 2)).append("mg/L、");
  1414. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getJszlSjz(), 2)).append("mg/L、");
  1415. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJsadSjz(), 2)).append("mg/L、");
  1416. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getJsssSjz(), 2)).append("mg/L、");
  1417. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getCscodBzz(), 2)).append("mg/L、");
  1418. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCszzBzz(), 2)).append("mg/L、");
  1419. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getCszlBzz(), 2)).append("mg/L、");
  1420. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCsadBzz(), 2)).append("mg/L、");
  1421. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getCsssBzz(), 2)).append("mg/L").append("。");
  1422. return sb.toString();
  1423. }
  1424. public static String handleDate(String str){
  1425. StringBuilder sb = new StringBuilder();
  1426. if(str.contains(" ")){//包含空格 就是年月日时分秒了
  1427. String[] split = str.split(" ");
  1428. addBeforeZero(sb, split[0], "/");
  1429. sb.append(" ");
  1430. addBeforeZero(sb, split[1], ":");
  1431. }else{
  1432. if(str.contains("/")){//年月日
  1433. addBeforeZero(sb, str, "/");
  1434. }else if(str.contains(":")){//时分秒
  1435. addBeforeZero(sb, str, ":");
  1436. }else {
  1437. sb.append(str);
  1438. }
  1439. }
  1440. return sb.toString();
  1441. }
  1442. public static StringBuilder addBeforeZero(StringBuilder sb, String str, String tag){
  1443. String[] split = str.split(tag);
  1444. int length = split.length;
  1445. for (int i = 0; i < length; i++) {
  1446. String value = split[i];
  1447. Integer intValue = Integer.parseInt(value);
  1448. if(intValue < 10 && value.length() == 1){////防止有正确的情况 额外再补充字符串
  1449. sb.append(0).append(value);
  1450. }else{
  1451. sb.append(value);
  1452. }
  1453. if(i < length-1){
  1454. sb.append(tag);
  1455. }
  1456. }
  1457. return sb;
  1458. }
  1459. public static void main(String[] args) throws ParseException {
  1460. /*LocalDateTime endTime = LocalDateTime.now();
  1461. System.out.println("endTime = " + endTime);
  1462. endTime = endTime.plusMinutes(60);
  1463. System.out.println("endTime = " + endTime);*/
  1464. /*String str = "2024/04/15 09:55";
  1465. System.out.println(str);
  1466. System.out.println(str.substring(0,10));
  1467. System.out.println(str.substring(0,13));*/
  1468. /*String str = "2024/04/18 08:00";
  1469. str = str + ":00";
  1470. System.out.println(str);
  1471. LocalDateTime startTime = LocalDateTime.parse(str.replaceAll("/", "-").replace(" ", "T"));
  1472. System.out.println(startTime.plusMinutes(1L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));*/
  1473. /*ArrayList<Integer> objects = new ArrayList<>();
  1474. objects.add(1);
  1475. objects.add(2);
  1476. objects.add(3);
  1477. System.out.println(objects);
  1478. objects.clear();
  1479. System.out.println(objects);
  1480. // test();
  1481. Date date = new Date();
  1482. System.out.println(DateUtils.differentHoursByMillisecond(date, date));
  1483. HashMap<Object, Object> map = new HashMap<>();
  1484. map.put("a", null);
  1485. map.put("b", "ab");
  1486. map.put("c", "");
  1487. map.put("d", '1');
  1488. System.out.println(JSON.toJSONString(map, JSONWriter.Feature.WriteNulls));
  1489. TXinyiIndustry tXinyiIndustry = new TXinyiIndustry();
  1490. System.out.println(JSON.toJSONString(tXinyiIndustry, JSONWriter.Feature.WriteNulls));*/
  1491. /*String s = "2022/01/01".substring(5).replace("/", "月") + "日";
  1492. System.out.println("s = " + s);
  1493. // System.out.println(new BigDecimal("1").compareTo(null));//空指针 要判断
  1494. System.out.println("2022/01/01 10".substring(11));
  1495. String date = DateUtil.format(DateUtils.getNowDate(), DateUtils.YYYY_MM_DD_HH);
  1496. System.out.println("date = " + date);
  1497. System.out.println(HttpUtil.get("http://10.0.3.52:10003/system/forecast?type=2&time=" + date));*/
  1498. System.out.println("2024-06-18 14".replaceAll("-", "/"));
  1499. String[] splitNew = new String[3];
  1500. splitNew[0] = "0";
  1501. splitNew[1] = "1";
  1502. splitNew[2] = "2";
  1503. System.out.println(Arrays.toString(splitNew));
  1504. System.out.println(DateUtils.parseDate("2024-06-25 10", DateUtils.YYYY_MM_DD_HH));
  1505. }
  1506. //测试工业库 没小时保存一条记录是否可行
  1507. public static void test() {
  1508. // 每个小时的时间格式
  1509. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  1510. LocalDateTime startTime = LocalDateTime.parse("2024-05-18T00:00:00");
  1511. LocalDateTime endTime = LocalDateTime.now();
  1512. // 循环按小时分割
  1513. LocalDateTime currentHour = startTime;
  1514. //最终获取的数据
  1515. Map<String, TXinyiIndustry> needMap = new LinkedHashMap<>();
  1516. while (currentHour.isBefore(endTime)) {
  1517. String begin = currentHour.format(formatter);
  1518. String end = currentHour.plusMinutes(5).format(formatter);
  1519. // 输出当前小时的起始时间和结束时间
  1520. System.out.println("起始时间:" + begin);
  1521. System.out.println("结束时间:" + end);
  1522. // 当前小时加一小时,作为下一个小时的起始时间
  1523. currentHour = currentHour.plusMinutes(5);
  1524. //每个小时查询一次数据
  1525. String url = "http://10.0.0.27:4568/api/v1/khquerydata";
  1526. HashMap<String, Object> req = new HashMap<>();
  1527. req.put("tagNames", queryTags);
  1528. req.put("startTime", begin);
  1529. req.put("endTime", end);
  1530. req.put("recordNumbers", 100000);
  1531. String body = HttpRequest.post(url).header("Authorization", "c2E6c2E=").header("clientName", "hongshan").body(JSON.toJSONString(req)).execute().body();
  1532. // System.out.println("body = " + body);
  1533. List<HashMap<String, String>> list = new ArrayList<>();
  1534. //行转列数据处理
  1535. for (String queryTag : queryTags) {
  1536. JSONArray array = JSON.parseObject(body).getJSONArray(queryTag);
  1537. //特殊数据处理一
  1538. if(Objects.isNull(array) || array.isEmpty()){
  1539. System.out.println(queryTag + "查询到了空的数据,跳过本次循环");
  1540. continue;
  1541. }
  1542. int size = array.size();
  1543. //特殊数据处理二
  1544. if("0".equals(array.get(1) + "")){
  1545. System.out.println(queryTag + "查询到了数据,但是数据集合只有一条,且都是0");
  1546. continue;
  1547. }
  1548. //结合至少62个数据才满足条件(有可能获取不到)
  1549. /*if(size < 62){
  1550. System.out.println(queryTag + "查询到了不符合条件的数据,跳过本次循环");
  1551. continue;
  1552. }*/
  1553. //存放的数据集
  1554. //利用map去重
  1555. HashMap<String, String> map = new LinkedHashMap<>();
  1556. for (int i = 2; i < size; i++) {
  1557. // System.out.println(i + "" + array.get(i));
  1558. JSONArray oneRecord = JSON.parseArray(JSON.toJSONString(array.get(i)));
  1559. //处理为空或者为0的数据
  1560. Object timeStampValue = oneRecord.get(2);
  1561. if(Objects.isNull(timeStampValue) || "0".equals(timeStampValue + ""))
  1562. continue;
  1563. BigDecimal value = Objects.isNull(oneRecord.get(0)) ? null : new BigDecimal(oneRecord.get(0) + "");
  1564. long timestamp = (long) timeStampValue;
  1565. String format = DateUtil.format(new Date(timestamp), DateUtils.YYYYMMDDHH_TS);
  1566. map.put(format, queryTag + "-" + value);
  1567. }
  1568. list.add(map);
  1569. }
  1570. Set<String> recordTimeSet = new HashSet<>();
  1571. Map<String, TXinyiIndustry> recordMap = new HashMap<>();
  1572. for (int i = 0; i < list.size(); i++) {
  1573. HashMap<String, String> map = list.get(i);
  1574. int finalJ = i;
  1575. map.forEach((k, v) ->{
  1576. TXinyiIndustry industry = null;
  1577. if(!recordTimeSet.contains(k)){//第一次
  1578. industry = new TXinyiIndustry();
  1579. recordTimeSet.add(k);
  1580. recordMap.put(k, industry);
  1581. }else{
  1582. industry = recordMap.get(k);
  1583. }
  1584. industry.setTestTime(k + ":00");
  1585. //2024年4月15日11:19:52 额外增加2个字段
  1586. industry.setTestDate(k.substring(0,10));
  1587. industry.setTestHour(k.substring(0,13));
  1588. //解析值
  1589. String[] split = v.split("-");
  1590. String type = split[0];
  1591. BigDecimal value = new BigDecimal(split[1]);
  1592. if ("信义污水厂JS_COD_Value".equals(type)) {
  1593. industry.setJsCod(value);
  1594. } else if ("信义污水厂JS_PH_Value".equals(type)) {
  1595. industry.setJsPh(value);
  1596. } else if ("信义污水厂JS_SS_Value".equals(type)) {
  1597. industry.setJsSs(value);
  1598. } else if ("信义污水厂JS_ZL_Value".equals(type)) {
  1599. industry.setJsTp(value);
  1600. } else if ("信义污水厂JS_ZA_Value".equals(type)) {
  1601. industry.setJsTn(value);
  1602. } else if ("信义污水厂JS_AD_Value".equals(type)) {
  1603. industry.setJsNh3(value);
  1604. } else if ("信义污水厂JS_T_Value".equals(type)) {
  1605. industry.setJsSwPh(value);
  1606. } else if ("信义污水厂进水泵房液位".equals(type)) {
  1607. industry.setJsBfyw(value);
  1608. } else if ("信义污水厂出水瞬时流量".equals(type)) {
  1609. industry.setCsSlqc(value);
  1610. } else if ("信义污水厂升级出水COD".equals(type)) {
  1611. industry.setCsCod(value);
  1612. } else if ("信义污水厂升级出水PH".equals(type)) {
  1613. industry.setCsPh(value);
  1614. } else if ("信义污水厂升级出水SS".equals(type)) {
  1615. industry.setCsSs(value);
  1616. } else if ("信义污水厂升级出水TN".equals(type)) {
  1617. industry.setCsTn(value);
  1618. } else if ("信义污水厂升级出水TP".equals(type)) {
  1619. industry.setCsTp(value);
  1620. } else if ("信义污水厂升级出水氨氮".equals(type)) {
  1621. industry.setCsNh3(value);
  1622. } else if ("信义污水厂AIT202_Value".equals(type)) {
  1623. industry.setOneHyzdDo(value);
  1624. } else if ("信义污水厂AIT203_Value".equals(type)) {
  1625. industry.setOneHymdDo(value);
  1626. } else if ("信义污水厂AIT207_Value".equals(type)) {
  1627. industry.setTwoHyzdDo(value);
  1628. } else if ("信义污水厂AIT206_Value".equals(type)) {
  1629. industry.setTwoHymdDo(value);
  1630. } else if ("信义污水厂AIT209_Value".equals(type)) {
  1631. industry.setOneMlss(value);
  1632. } else if ("信义污水厂AIT210_Value".equals(type)) {
  1633. industry.setTwoMlss(value);
  1634. } else if ("信义污水厂进水TDS".equals(type)) {
  1635. industry.setJsTds(value);
  1636. } else if ("信义污水厂FT101_Value".equals(type)) {
  1637. industry.setJsSlq(value);
  1638. } else if ("信义污水厂SWCHHYHLB1_R_Value".equals(type)) {
  1639. industry.setNHlbOneGp(value);
  1640. } else if ("信义污水厂SWCHHYHLB2_R_Value".equals(type)) {
  1641. industry.setNHlbTwoGp(value);
  1642. } else if ("信义污水厂SWCHHYHLB3_R_Value".equals(type)) {
  1643. industry.setNHlbThreeGp(value);
  1644. } else if ("信义污水厂SWCHHYHLB4_R_Value".equals(type)) {
  1645. industry.setNHlbFourGp(value);
  1646. } else if ("信义污水厂SWCHHYHLB5_R_Value".equals(type)) {
  1647. industry.setNhlBFiveGp(value);
  1648. } else if ("信义污水厂SWCHHYHLB6_R_Value".equals(type)) {
  1649. industry.setNHlbSixGp(value);
  1650. } else if ("信义污水厂SWCWNHLB1_R_Value".equals(type)) {
  1651. industry.setWHlbOneGp(value);
  1652. } else if ("信义污水厂SWCWNHLB2_R_Value".equals(type)) {
  1653. industry.setWHlbTwoGp(value);
  1654. } else if ("信义污水厂SWCWNHLB3_R_Value".equals(type)) {
  1655. industry.setWHlbThreeGp(value);
  1656. } else if ("信义污水厂SWCWNHLB4_R_Value".equals(type)) {
  1657. industry.setWHlbFourGp(value);
  1658. } else if ("信义污水厂SWCWNHLB5_R_Value".equals(type)) {
  1659. industry.setWHlbFiveGp(value);
  1660. } else if ("信义污水厂GFJ1_R_Value".equals(type)) {
  1661. industry.setFjOne(value);
  1662. } else if ("信义污水厂GFJ2_R_Value".equals(type)) {
  1663. industry.setFjTwo(value);
  1664. } else if ("信义污水厂GFJ3_R_Value".equals(type)) {
  1665. industry.setFjThree(value);
  1666. } else if ("信义污水厂GFJ4_R_Value".equals(type)) {
  1667. industry.setFjFour(value);
  1668. } else if ("信义污水厂GFJ5_R_Value".equals(type)) {
  1669. industry.setFjFive(value);
  1670. } else if ("信义污水厂GFJ6_R_Value".equals(type)) {
  1671. industry.setFjSix(value);
  1672. } else if ("信义污水厂GFJ1_KQLL_Value".equals(type)) {
  1673. industry.setKqllOne(value);
  1674. } else if ("信义污水厂GFJ2_KQLL_Value".equals(type)) {
  1675. industry.setKqllTwo(value);
  1676. } else if ("信义污水厂GFJ3_KQLL_Value".equals(type)) {
  1677. industry.setKqllThree(value);
  1678. } else if ("信义污水厂GFJ4_KQLL_Value".equals(type)) {
  1679. industry.setKqllFour(value);
  1680. } else if ("信义污水厂GFJ5_KQLL_Value".equals(type)) {
  1681. industry.setKqllFive(value);
  1682. } else if ("信义污水厂GFJ6_KQLL_Value".equals(type)) {
  1683. industry.setKqllSix(value);
  1684. }else if ("信义污水厂实际碳源加药量".equals(type)) {
  1685. industry.setSJTYJLY(value);
  1686. }else if ("信义污水厂除磷加药瞬时流量".equals(type)) {
  1687. industry.setCLJYSSLL(value);
  1688. } else if ("信义污水厂_除磷P04预测值_".equals(type)) {
  1689. industry.setCLP04YCZ(value);
  1690. }
  1691. //只有最后一次才执行数据库添加
  1692. if(finalJ == list.size()-1){
  1693. needMap.put(industry.getTestHour(), industry);
  1694. }
  1695. });
  1696. }
  1697. }
  1698. //保存数据 触发告警 决策 问答记录等等
  1699. needMap.forEach((k, industry) ->{
  1700. System.out.println(JSON.toJSONString(industry));
  1701. });
  1702. }
  1703. }