RyTask.java 118 KB

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