RyTask.java 101 KB

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