DataCollectionSysyem.cs 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. using Microsoft.AspNetCore.DataProtection.KeyManagement;
  2. using ServiceCenter.Extensions;
  3. using ServiceCenter.SqlSugars;
  4. using SqlSugar;
  5. using System.Collections.Concurrent;
  6. using System.ComponentModel;
  7. using System.Data;
  8. using System.Reflection;
  9. using System.Text;
  10. using PlcSiemens.Core.Extension;
  11. using WCS.Core;
  12. using WCS.Entity.Protocol.DataStructure;
  13. using WCS.Entity.Protocol.HUB;
  14. using WCS.Entity.Protocol.Protocol.Robot;
  15. using WCS.Entity.Protocol.RGV;
  16. using WCS.Entity.Protocol.Robot;
  17. using WCS.Entity.Protocol.SRM;
  18. using WCS.Entity.Protocol.Station;
  19. using WCS.Entity.Protocol.Truss;
  20. using WCS.WorkEngineering.Worlds;
  21. using WCS.Entity;
  22. namespace WCS.WorkEngineering.Systems
  23. {
  24. /// <summary>
  25. /// 数据处理系统
  26. /// </summary>
  27. [BelongTo(typeof(MainWorld))]
  28. [Description("数据处理系统")]
  29. public class DataCollectionSysyem : DeviceSystem<Device<IStation520>>
  30. {
  31. public static DeviceDataPack pack = new DeviceDataPack();
  32. private static object locker = new object();
  33. public DataCollectionSysyem()
  34. {
  35. }
  36. /// <summary>
  37. /// 所有设备数据
  38. /// Key 是不同设备所使用的类型 例如DeviceDataCollection<SRMData>
  39. /// value 不同设备的具体数据
  40. /// </summary>
  41. public static ConcurrentDictionary<string, DeviceData> AllDatas = new ConcurrentDictionary<string, DeviceData>();
  42. protected override bool ParallelDo => true;
  43. public override bool Select(Device dev)
  44. {
  45. return dev.Code == "1";
  46. }
  47. public override void Do(Device<IStation520> objDev)
  48. {
  49. //通过数据条数处理
  50. var db = new SqlSugarHelper().PLC;
  51. var plcEx = new SqlSugarHelper().PLCEX;
  52. var time = DateTime.Now.AddDays(-1).Date;
  53. //Type parentType = typeof(IProtocol);
  54. //var childTypes = AppDomain.CurrentDomain.GetAssemblies()
  55. // .First(x => x.FullName.Contains("WCS.Entity.Protocol")).GetTypes().Where(x => x.IsClass)
  56. // .Where(x => x.GetInterfaces().Any(t => t == parentType)).ToList();
  57. //foreach (Type childType in childTypes)
  58. //{
  59. // //获取表名
  60. // var sugarTablea = childType.GetCustomAttributes(typeof(SugarTable), true).Select(x => (SugarTable)x).FirstOrDefault();
  61. // if (sugarTablea != null)
  62. // {
  63. // var table = db.Queryable<dynamic>().AS("information_schema.tables").Where("table_name=@name", new { name = sugarTablea.TableName }).ToList();
  64. // if (table.Count > 0)
  65. // {
  66. // var sql = $"ALTER TABLE {sugarTablea.TableName} DROP PARTITION WHERE frame < to_timestamp('{time}', 'yyyy-MM-dd:HH:mm:ss')";
  67. // db.Ado.ExecuteCommand(sql);
  68. // }
  69. // }
  70. //}
  71. //var sysTypes = AppDomain.CurrentDomain.GetAssemblies().Select(v => v.GetTypes()).SelectMany(v => v)
  72. // .Where(v => !v.IsAbstract)
  73. // .Where(v => typeof(SystemBase).IsAssignableFrom(v))
  74. // .Where(v =>
  75. // {
  76. // var attr = v.GetCustomAttribute<BelongToAttribute>();
  77. // if (attr == null) return GetType() == typeof(World);
  78. // if (attr.WorldType == this.GetType()) return true;
  79. // return false;
  80. // }).ToArray();
  81. ExRobotRunInfo(db, plcEx);
  82. ExSrmRunInfo(db, plcEx);
  83. ExRgvRunInfo(db, plcEx);
  84. ExTrussRunInfo(db, plcEx);
  85. //ExRobotAlarmInfo(db, plcEx);
  86. //ExSrmAlarmInfo(db, plcEx);
  87. //ExRgvAlarmInfo(db, plcEx);
  88. //ExTrussAlarmInfo(db, plcEx);
  89. ExRobotTaskSumRunInfo(db, plcEx);
  90. ExTrussTaskSumRunInfo(db, plcEx);
  91. }
  92. #region 设备运行信息收集
  93. /// <summary>
  94. /// 机械臂
  95. /// </summary>
  96. /// <param name="db"></param>
  97. public void ExRobotRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  98. {
  99. var startTime = DateTime.Now;
  100. var endTime = DateTime.Now;
  101. IEnumerable<IGrouping<string, WCS_Robot521>> robot521 = new List<IGrouping<string, WCS_Robot521>>();
  102. var type = DevType.SRM.ToString();
  103. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  104. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  105. {
  106. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  107. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  108. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  109. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  110. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  111. }
  112. else
  113. {
  114. if (!db.Queryable<WCS_Robot521>().Any()) return;
  115. startTime = db.Queryable<WCS_Robot521>().OrderBy(x => x.Frame).First().Frame;
  116. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  117. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  118. }
  119. //取上一小时的第一秒
  120. var now = DateTime.Now;
  121. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  122. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  123. if (endTime > now) return; //当前时间之前
  124. if (nowEndTime == now) return; //是当前这一个小时
  125. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  126. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  127. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  128. robot521 = db.Queryable<WCS_Robot521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  129. if (!robot521.Any())
  130. {
  131. plcEx.Insertable(new DevRunInfo()
  132. {
  133. Frame = endTime,
  134. Code = "当前时段无有效数据",
  135. RunMode = "当前时段无有效数据",
  136. RunStatus = "当前时段无有效数据",
  137. StartTime = startTime,
  138. EndTime = endTime,
  139. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  140. Type = type
  141. }).ExecuteCommand();
  142. }
  143. Parallel.ForEach(robot521, infos =>
  144. {
  145. // 获取第一条数据与最后一条数据
  146. var start = infos.OrderBy(x => x.Frame).First();
  147. var end = infos.OrderByDescending(x => x.Frame).First();
  148. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  149. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  150. //获取前一天最后的一条数据
  151. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  152. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  153. foreach (var info in infos.OrderBy(x => x.Frame))
  154. {
  155. if (info.Frame == start.Frame) //当天的第一条数据
  156. {
  157. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  158. {
  159. runInfos.Add(new DevRunInfo()
  160. {
  161. Frame = info.Frame,
  162. Code = info.Code,
  163. RunMode = info.RobotMode.GetDescription(),
  164. RunStatus = info.RunStatus.GetDescription(),
  165. StartTime = startTime,
  166. EndTime = info.Frame,
  167. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  168. Type = type
  169. });
  170. }
  171. else //如果有就用前一天的最后一条数据做计算
  172. {
  173. runInfos.Add(new DevRunInfo()
  174. {
  175. Frame = info.Frame,
  176. Code = info.Code,
  177. RunMode = yesterEnd.RunMode,
  178. RunStatus = yesterEnd.RunStatus,
  179. StartTime = startTime,
  180. EndTime = info.Frame,
  181. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  182. Type = type
  183. });
  184. }
  185. }
  186. else if (info.Frame == end.Frame) //当天的最后一条数据
  187. {
  188. runInfos.Add(new DevRunInfo()
  189. {
  190. Frame = info.Frame,
  191. Code = info.Code,
  192. RunMode = info.RobotMode.GetDescription(),
  193. RunStatus = info.RunStatus.GetDescription(),
  194. StartTime = info.Frame,
  195. EndTime = endTime,
  196. Duration = Convert.ToInt64((endTime - info.Frame).TotalMilliseconds),
  197. Type = type
  198. });
  199. }
  200. else //中间数据
  201. {
  202. if (start.RobotMode == info.RobotMode && start.RunStatus == info.RunStatus) continue;
  203. runInfos.Add(new DevRunInfo()
  204. {
  205. Frame = info.Frame,
  206. Code = info.Code,
  207. RunMode = start.RobotMode.GetDescription(),
  208. RunStatus = start.RunStatus.GetDescription(),
  209. StartTime = start.Frame,
  210. EndTime = info.Frame,
  211. Duration = Convert.ToInt64((info.Frame - start.Frame).TotalMilliseconds),
  212. Type = type
  213. });
  214. start = info;
  215. }
  216. }
  217. var sql = plcEx.Insertable(runInfos).ToSqlString();
  218. plcEx.Ado.ExecuteCommand(GetString(sql));
  219. });
  220. }
  221. /// <summary>
  222. /// 堆垛机
  223. /// </summary>
  224. /// <param name="db"></param>
  225. public void ExSrmRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  226. {
  227. var startTime = DateTime.Now;
  228. var endTime = DateTime.Now;
  229. IEnumerable<IGrouping<string, WCS_SRM521>> srm521 = new List<IGrouping<string, WCS_SRM521>>();
  230. var type = DevType.SRM.ToString();
  231. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  232. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  233. {
  234. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  235. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  236. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  237. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  238. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  239. }
  240. else
  241. {
  242. if (!db.Queryable<WCS_SRM521>().Any()) return;
  243. startTime = db.Queryable<WCS_SRM521>().OrderBy(x => x.Frame).First().Frame;
  244. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  245. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  246. }
  247. //取上一小时的第一秒
  248. var now = DateTime.Now;
  249. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  250. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  251. if (endTime > now) return; //当前时间之前
  252. if (nowEndTime == now) return; //是当前这一个小时
  253. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  254. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  255. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  256. srm521 = db.Queryable<WCS_SRM521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  257. if (!srm521.Any())
  258. {
  259. plcEx.Insertable(new DevRunInfo()
  260. {
  261. Frame = endTime,
  262. Code = "当前时段无有效数据",
  263. RunMode = "当前时段无有效数据",
  264. RunStatus = "当前时段无有效数据",
  265. StartTime = startTime,
  266. EndTime = endTime,
  267. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  268. Type = type
  269. }).ExecuteCommand();
  270. }
  271. Parallel.ForEach(srm521, infos =>
  272. {
  273. // 获取第一条数据与最后一条数据
  274. var start = infos.OrderBy(x => x.Frame).First();
  275. var end = infos.OrderByDescending(x => x.Frame).First();
  276. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  277. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  278. //获取前一天最后的一条数据
  279. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  280. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  281. foreach (var info in infos.OrderBy(x => x.Frame))
  282. {
  283. if (info.Frame == start.Frame) //当天的第一条数据
  284. {
  285. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  286. {
  287. runInfos.Add(new DevRunInfo()
  288. {
  289. Frame = info.Frame,
  290. Code = info.Code,
  291. RunMode = info.AutoStatus.GetDescription(),
  292. RunStatus = info.RunStatus.GetDescription(),
  293. StartTime = startTime,
  294. EndTime = info.Frame,
  295. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  296. Type = type
  297. });
  298. }
  299. else //如果有就用前一天的最后一条数据做计算
  300. {
  301. runInfos.Add(new DevRunInfo()
  302. {
  303. Frame = info.Frame,
  304. Code = info.Code,
  305. RunMode = yesterEnd.RunMode,
  306. RunStatus = yesterEnd.RunStatus,
  307. StartTime = startTime,
  308. EndTime = info.Frame,
  309. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  310. Type = type
  311. });
  312. }
  313. }
  314. else if (info.Frame == end.Frame) //当天的最后一条数据
  315. {
  316. runInfos.Add(new DevRunInfo()
  317. {
  318. Frame = info.Frame,
  319. Code = info.Code,
  320. RunMode = info.AutoStatus.GetDescription(),
  321. RunStatus = info.RunStatus.GetDescription(),
  322. StartTime = info.Frame,
  323. EndTime = endTime,
  324. Duration = Convert.ToInt64((endTime - info.Frame).TotalMilliseconds),
  325. Type = type
  326. });
  327. }
  328. else //中间数据
  329. {
  330. if (start.AutoStatus == info.AutoStatus && start.RunStatus == info.RunStatus) continue;
  331. runInfos.Add(new DevRunInfo()
  332. {
  333. Frame = info.Frame,
  334. Code = info.Code,
  335. RunMode = start.AutoStatus.GetDescription(),
  336. RunStatus = start.RunStatus.GetDescription(),
  337. StartTime = start.Frame,
  338. EndTime = info.Frame,
  339. Duration = Convert.ToInt64((info.Frame - start.Frame).TotalMilliseconds),
  340. Type = type
  341. });
  342. start = info;
  343. }
  344. }
  345. var sql = plcEx.Insertable(runInfos).ToSqlString();
  346. plcEx.Ado.ExecuteCommand(GetString(sql));
  347. });
  348. }
  349. /// <summary>
  350. /// rgv
  351. /// </summary>
  352. /// <param name="db"></param>
  353. public void ExRgvRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  354. {
  355. var startTime = DateTime.Now;
  356. var endTime = DateTime.Now;
  357. IEnumerable<IGrouping<string, WCS_RGV521>> rgv521 = new List<IGrouping<string, WCS_RGV521>>();
  358. var type = DevType.SRM.ToString();
  359. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  360. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  361. {
  362. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  363. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  364. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  365. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  366. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  367. }
  368. else
  369. {
  370. if (!db.Queryable<WCS_RGV521>().Any()) return;
  371. startTime = db.Queryable<WCS_RGV521>().OrderBy(x => x.Frame).First().Frame;
  372. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  373. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  374. }
  375. //取上一小时的第一秒
  376. var now = DateTime.Now;
  377. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  378. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  379. if (endTime > now) return; //当前时间之前
  380. if (nowEndTime == now) return; //是当前这一个小时
  381. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  382. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  383. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  384. rgv521 = db.Queryable<WCS_RGV521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  385. if (!rgv521.Any())
  386. {
  387. plcEx.Insertable(new DevRunInfo()
  388. {
  389. Frame = endTime,
  390. Code = "当前时段无有效数据",
  391. RunMode = "当前时段无有效数据",
  392. RunStatus = "当前时段无有效数据",
  393. StartTime = startTime,
  394. EndTime = endTime,
  395. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  396. Type = type
  397. }).ExecuteCommand();
  398. }
  399. Parallel.ForEach(rgv521, infos =>
  400. {
  401. // 获取第一条数据与最后一条数据
  402. var start = infos.OrderBy(x => x.Frame).First();
  403. var end = infos.OrderByDescending(x => x.Frame).First();
  404. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  405. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  406. //获取前一天最后的一条数据
  407. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  408. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  409. foreach (var info in infos.OrderBy(x => x.Frame))
  410. {
  411. if (info.Frame == start.Frame) //当天的第一条数据
  412. {
  413. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  414. {
  415. runInfos.Add(new DevRunInfo()
  416. {
  417. Frame = info.Frame,
  418. Code = info.Code,
  419. RunMode = info.WorkMode.GetDescription(),
  420. RunStatus = info.SystemStatus.GetDescription(),
  421. StartTime = startTime,
  422. EndTime = info.Frame,
  423. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  424. Type = type
  425. });
  426. }
  427. else //如果有就用前一天的最后一条数据做计算
  428. {
  429. runInfos.Add(new DevRunInfo()
  430. {
  431. Frame = info.Frame,
  432. Code = info.Code,
  433. RunMode = yesterEnd.RunMode,
  434. RunStatus = yesterEnd.RunStatus,
  435. StartTime = startTime,
  436. EndTime = info.Frame,
  437. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  438. Type = type
  439. });
  440. }
  441. }
  442. else if (info.Frame == end.Frame) //当天的最后一条数据
  443. {
  444. runInfos.Add(new DevRunInfo()
  445. {
  446. Frame = info.Frame,
  447. Code = info.Code,
  448. RunMode = info.WorkMode.GetDescription(),
  449. RunStatus = info.SystemStatus.GetDescription(),
  450. StartTime = info.Frame,
  451. EndTime = endTime,
  452. Duration = Convert.ToInt64((endTime - info.Frame).TotalMilliseconds),
  453. Type = type
  454. });
  455. }
  456. else //中间数据
  457. {
  458. if (start.WorkMode == info.WorkMode && start.SystemStatus == info.SystemStatus) continue;
  459. runInfos.Add(new DevRunInfo()
  460. {
  461. Frame = info.Frame,
  462. Code = info.Code,
  463. RunMode = start.WorkMode.GetDescription(),
  464. RunStatus = start.SystemStatus.GetDescription(),
  465. StartTime = start.Frame,
  466. EndTime = info.Frame,
  467. Duration = Convert.ToInt64((info.Frame - start.Frame).TotalMilliseconds),
  468. Type = type
  469. });
  470. start = info;
  471. }
  472. }
  473. var sql = plcEx.Insertable(runInfos).ToSqlString();
  474. plcEx.Ado.ExecuteCommand(GetString(sql));
  475. });
  476. }
  477. /// <summary>
  478. /// 桁架
  479. /// </summary>
  480. /// <param name="db"></param>
  481. public void ExTrussRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  482. {
  483. var startTime = DateTime.Now;
  484. var endTime = DateTime.Now;
  485. IEnumerable<IGrouping<string, WCS_Truss521>> truss521 = new List<IGrouping<string, WCS_Truss521>>();
  486. var type = DevType.SRM.ToString();
  487. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  488. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  489. {
  490. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  491. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  492. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  493. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  494. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  495. }
  496. else
  497. {
  498. if (!db.Queryable<WCS_Truss521>().Any()) return;
  499. startTime = db.Queryable<WCS_Truss521>().OrderBy(x => x.Frame).First().Frame;
  500. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  501. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  502. }
  503. //取上一小时的第一秒
  504. var now = DateTime.Now;
  505. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  506. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  507. if (endTime > now) return; //当前时间之前
  508. if (nowEndTime == now) return; //是当前这一个小时
  509. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  510. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  511. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  512. truss521 = db.Queryable<WCS_Truss521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  513. if (!truss521.Any())
  514. {
  515. plcEx.Insertable(new DevRunInfo()
  516. {
  517. Frame = endTime,
  518. Code = "当前时段无有效数据",
  519. RunMode = "当前时段无有效数据",
  520. RunStatus = "当前时段无有效数据",
  521. StartTime = startTime,
  522. EndTime = endTime,
  523. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  524. Type = type
  525. }).ExecuteCommand();
  526. }
  527. Parallel.ForEach(truss521, infos =>
  528. {
  529. // 获取第一条数据与最后一条数据
  530. var start = infos.OrderBy(x => x.Frame).First();
  531. var end = infos.OrderByDescending(x => x.Frame).First();
  532. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  533. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  534. //获取前一天最后的一条数据
  535. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  536. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  537. foreach (var info in infos.OrderBy(x => x.Frame))
  538. {
  539. if (info.Frame == start.Frame) //当天的第一条数据
  540. {
  541. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  542. {
  543. runInfos.Add(new DevRunInfo()
  544. {
  545. Frame = info.Frame,
  546. Code = info.Code,
  547. RunMode = info.Status.GetDescription(),
  548. StartTime = startTime,
  549. EndTime = info.Frame,
  550. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  551. Type = type
  552. });
  553. }
  554. else //如果有就用前一天的最后一条数据做计算
  555. {
  556. runInfos.Add(new DevRunInfo()
  557. {
  558. Frame = info.Frame,
  559. Code = info.Code,
  560. RunMode = yesterEnd.RunMode,
  561. RunStatus = yesterEnd.RunStatus,
  562. StartTime = startTime,
  563. EndTime = info.Frame,
  564. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  565. Type = type
  566. });
  567. }
  568. }
  569. else if (info.Frame == end.Frame) //当天的最后一条数据
  570. {
  571. runInfos.Add(new DevRunInfo()
  572. {
  573. Frame = info.Frame,
  574. Code = info.Code,
  575. RunMode = info.Status.GetDescription(),
  576. StartTime = info.Frame,
  577. EndTime = endTime,
  578. Duration = Convert.ToInt64((endTime - info.Frame).TotalMilliseconds),
  579. Type = type
  580. });
  581. }
  582. else //中间数据
  583. {
  584. if (start.Status == info.Status) continue;
  585. runInfos.Add(new DevRunInfo()
  586. {
  587. Frame = info.Frame,
  588. Code = info.Code,
  589. RunMode = start.Status.GetDescription(),
  590. StartTime = start.Frame,
  591. EndTime = info.Frame,
  592. Duration = Convert.ToInt64((info.Frame - start.Frame).TotalMilliseconds),
  593. Type = type
  594. });
  595. start = info;
  596. }
  597. }
  598. var sql = plcEx.Insertable(runInfos).ToSqlString();
  599. plcEx.Ado.ExecuteCommand(GetString(sql));
  600. });
  601. }
  602. #endregion 设备运行信息收集
  603. #region 异常报警信息
  604. /// <summary>
  605. /// 机械臂
  606. /// </summary>
  607. /// <param name="db"></param>
  608. public void ExRobotAlarmInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  609. {
  610. var startTime = DateTime.Now;
  611. var endTime = DateTime.Now;
  612. IEnumerable<IGrouping<string, QuestDb_Robot522>> robot522 = new List<IGrouping<string, QuestDb_Robot522>>();
  613. var type = DevType.Robot.ToString();
  614. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  615. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Type == type))
  616. {
  617. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  618. var alarmInfo = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  619. startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  620. endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  621. }
  622. else
  623. {
  624. if (!db.Queryable<QuestDb_Robot522>().Any()) return;
  625. startTime = db.Queryable<QuestDb_Robot522>().OrderBy(x => x.Frame).First().Frame.Date;
  626. endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  627. }
  628. if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  629. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  630. robot522 = db.Queryable<QuestDb_Robot522>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  631. if (!robot522.Any())
  632. {
  633. plcEx.Insertable(new DevAlarmInfo()
  634. {
  635. Frame = endTime,
  636. Code = "当前时段无有效数据",
  637. Alarm = "当前时段无有效数据",
  638. StartTime = startTime,
  639. EndTime = endTime,
  640. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  641. Type = type
  642. }).ExecuteCommand();
  643. }
  644. Parallel.ForEach(robot522, infos =>
  645. {
  646. // 获取第一条数据与最后一条数据
  647. var start = infos.OrderBy(x => x.Frame).First();
  648. var end = infos.OrderByDescending(x => x.Frame).First();
  649. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  650. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  651. //获取前一天最后的一条数据
  652. var yesterEnd = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  653. List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  654. var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  655. foreach (var info in infos.OrderBy(x => x.Frame))
  656. {
  657. if (info.Frame == end.Frame) //最后一条数据
  658. {
  659. if (info.Alarm != "无")
  660. {
  661. //先判断是否有没有记录的报警信息
  662. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  663. var msgList = alarmList.Select(x => x.Msg);
  664. //将未记录的报警信息增加到缓存中
  665. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  666. }
  667. if (!alarmList.Any()) continue;
  668. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  669. {
  670. Frame = alarm.Time,
  671. Code = info.Code,
  672. Alarm = alarm.Msg,
  673. StartTime = alarm.Time,
  674. EndTime = endTime,
  675. Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  676. Type = type
  677. }));
  678. }
  679. else
  680. {
  681. if (info.Alarm == "无" && alarmList.Any()) //代表报警全部清空了
  682. {
  683. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  684. {
  685. Frame = alarm.Time,
  686. Code = info.Code,
  687. Alarm = alarm.Msg,
  688. StartTime = alarm.Time,
  689. EndTime = info.Frame,
  690. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  691. Type = type
  692. }));
  693. alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  694. }
  695. else if (info.Alarm != "无")
  696. {
  697. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  698. var msgList = alarmList.Select(x => x.Msg);
  699. //将未记录的报警信息增加到缓存中
  700. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  701. var treatedAlarm = new List<string>();
  702. //将已记录,但当前信息中没有的报警结束
  703. foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  704. {
  705. runInfos.Add(new DevAlarmInfo()
  706. {
  707. Frame = alarm.Time,
  708. Code = info.Code,
  709. Alarm = alarm.Msg,
  710. StartTime = alarm.Time,
  711. EndTime = info.Frame,
  712. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  713. Type = type
  714. });
  715. treatedAlarm.Add(alarm.Msg);
  716. }
  717. alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  718. }
  719. }
  720. }
  721. if (runInfos.Any())
  722. {
  723. var sql = plcEx.Insertable(runInfos).ToSqlString();
  724. plcEx.Ado.ExecuteCommand(GetString(sql));
  725. }
  726. else
  727. {
  728. plcEx.Insertable(new DevAlarmInfo()
  729. {
  730. Frame = endTime,
  731. Code = infos.Key,
  732. Alarm = "当前时段无有效数据",
  733. StartTime = startTime,
  734. EndTime = endTime,
  735. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  736. Type = type
  737. }).ExecuteCommand();
  738. }
  739. });
  740. }
  741. /// <summary>
  742. /// 堆垛机
  743. /// </summary>
  744. /// <param name="db"></param>
  745. public void ExSrmAlarmInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  746. {
  747. var startTime = DateTime.Now;
  748. var endTime = DateTime.Now;
  749. IEnumerable<IGrouping<string, QuestDb_SRM523>> srm523 = new List<IGrouping<string, QuestDb_SRM523>>();
  750. var type = DevType.SRM.ToString();
  751. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  752. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Type == type))
  753. {
  754. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  755. var alarmInfo = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  756. startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  757. endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  758. }
  759. else
  760. {
  761. if (!db.Queryable<QuestDb_SRM523>().Any()) return;
  762. startTime = db.Queryable<QuestDb_SRM523>().OrderBy(x => x.Frame).First().Frame.Date;
  763. endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  764. }
  765. if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  766. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  767. srm523 = db.Queryable<QuestDb_SRM523>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  768. if (!srm523.Any())
  769. {
  770. plcEx.Insertable(new DevAlarmInfo()
  771. {
  772. Frame = endTime,
  773. Code = "当前时段无有效数据",
  774. Alarm = "当前时段无有效数据",
  775. StartTime = startTime,
  776. EndTime = endTime,
  777. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  778. Type = type
  779. }).ExecuteCommand();
  780. }
  781. Parallel.ForEach(srm523, infos =>
  782. {
  783. // 获取第一条数据与最后一条数据
  784. var start = infos.OrderBy(x => x.Frame).First();
  785. var end = infos.OrderByDescending(x => x.Frame).First();
  786. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  787. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  788. //获取前一天最后的一条数据
  789. var yesterEnd = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  790. List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  791. var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  792. foreach (var info in infos.OrderBy(x => x.Frame))
  793. {
  794. if (info.Frame == end.Frame) //最后一条数据
  795. {
  796. if (info.Alarm != "无,无")
  797. {
  798. //先判断是否有没有记录的报警信息
  799. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).Where(x => x != "无").ToList();
  800. var msgList = alarmList.Select(x => x.Msg);
  801. //将未记录的报警信息增加到缓存中
  802. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  803. }
  804. if (!alarmList.Any()) continue;
  805. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  806. {
  807. Frame = alarm.Time,
  808. Code = info.Code,
  809. Alarm = alarm.Msg,
  810. StartTime = alarm.Time,
  811. EndTime = endTime,
  812. Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  813. Type = type
  814. }));
  815. }
  816. else
  817. {
  818. if (info.Alarm == "无,无" && alarmList.Any()) //代表报警全部清空了
  819. {
  820. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  821. {
  822. Frame = alarm.Time,
  823. Code = info.Code,
  824. Alarm = alarm.Msg,
  825. StartTime = alarm.Time,
  826. EndTime = info.Frame,
  827. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  828. Type = type
  829. }));
  830. alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  831. }
  832. else if (info.Alarm != "无,无")
  833. {
  834. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).Where(x => x != "无").ToList();
  835. var msgList = alarmList.Select(x => x.Msg);
  836. //将未记录的报警信息增加到缓存中
  837. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  838. var treatedAlarm = new List<string>();
  839. //将已记录,但当前信息中没有的报警结束
  840. foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  841. {
  842. runInfos.Add(new DevAlarmInfo()
  843. {
  844. Frame = alarm.Time,
  845. Code = info.Code,
  846. Alarm = alarm.Msg,
  847. StartTime = alarm.Time,
  848. EndTime = info.Frame,
  849. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  850. Type = type
  851. });
  852. treatedAlarm.Add(alarm.Msg);
  853. }
  854. alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  855. }
  856. }
  857. }
  858. if (runInfos.Any())
  859. {
  860. var sql = plcEx.Insertable(runInfos).ToSqlString();
  861. plcEx.Ado.ExecuteCommand(GetString(sql));
  862. }
  863. else
  864. {
  865. plcEx.Insertable(new DevAlarmInfo()
  866. {
  867. Frame = endTime,
  868. Code = infos.Key,
  869. Alarm = "当前时段无有效数据",
  870. StartTime = startTime,
  871. EndTime = endTime,
  872. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  873. Type = type
  874. }).ExecuteCommand();
  875. }
  876. });
  877. }
  878. /// <summary>
  879. /// rgv
  880. /// </summary>
  881. /// <param name="db"></param>
  882. public void ExRgvAlarmInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  883. {
  884. var startTime = DateTime.Now;
  885. var endTime = DateTime.Now;
  886. IEnumerable<IGrouping<string, QuestDb_RGV523>> rgv523 = new List<IGrouping<string, QuestDb_RGV523>>();
  887. var type = DevType.RGV.ToString();
  888. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  889. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Type == type))
  890. {
  891. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  892. var alarmInfo = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  893. startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  894. endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  895. }
  896. else
  897. {
  898. if (!db.Queryable<QuestDb_RGV523>().Any()) return;
  899. startTime = db.Queryable<QuestDb_RGV523>().OrderBy(x => x.Frame).First().Frame.Date;
  900. endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  901. }
  902. if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  903. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  904. rgv523 = db.Queryable<QuestDb_RGV523>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  905. if (!rgv523.Any())
  906. {
  907. plcEx.Insertable(new DevAlarmInfo()
  908. {
  909. Frame = endTime,
  910. Code = "当前时段无有效数据",
  911. Alarm = "当前时段无有效数据",
  912. StartTime = startTime,
  913. EndTime = endTime,
  914. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  915. Type = type
  916. }).ExecuteCommand();
  917. }
  918. Parallel.ForEach(rgv523/*.Where(x => x.Key == "RGV4")*/, infos =>
  919. {
  920. // 获取第一条数据与最后一条数据
  921. var start = infos.OrderBy(x => x.Frame).First();
  922. var end = infos.OrderByDescending(x => x.Frame).First();
  923. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  924. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  925. //获取前一天最后的一条数据
  926. var yesterEnd = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  927. List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  928. var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  929. foreach (var info in infos.OrderBy(x => x.Frame))
  930. {
  931. if (info.Frame == end.Frame) //最后一条数据
  932. {
  933. if (info.Alarm != "无")
  934. {
  935. //先判断是否有没有记录的报警信息
  936. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  937. var msgList = alarmList.Select(x => x.Msg);
  938. //将未记录的报警信息增加到缓存中
  939. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  940. }
  941. if (!alarmList.Any()) continue;
  942. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  943. {
  944. Frame = alarm.Time,
  945. Code = info.Code,
  946. Alarm = alarm.Msg,
  947. StartTime = alarm.Time,
  948. EndTime = endTime,
  949. Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  950. Type = type
  951. }));
  952. }
  953. else
  954. {
  955. if (info.Alarm == "无" && alarmList.Any()) //代表报警全部清空了
  956. {
  957. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  958. {
  959. Frame = alarm.Time,
  960. Code = info.Code,
  961. Alarm = alarm.Msg,
  962. StartTime = alarm.Time,
  963. EndTime = info.Frame,
  964. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  965. Type = type
  966. }));
  967. alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  968. }
  969. else if (info.Alarm != "无")
  970. {
  971. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  972. var msgList = alarmList.Select(x => x.Msg);
  973. //将未记录的报警信息增加到缓存中
  974. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  975. var treatedAlarm = new List<string>();
  976. //将已记录,但当前信息中没有的报警结束
  977. foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  978. {
  979. runInfos.Add(new DevAlarmInfo()
  980. {
  981. Frame = alarm.Time,
  982. Code = info.Code,
  983. Alarm = alarm.Msg,
  984. StartTime = alarm.Time,
  985. EndTime = info.Frame,
  986. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  987. Type = type
  988. });
  989. treatedAlarm.Add(alarm.Msg);
  990. }
  991. alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  992. }
  993. }
  994. }
  995. if (runInfos.Any())
  996. {
  997. plcEx.Insertable(runInfos).ExecuteCommand();
  998. }
  999. else
  1000. {
  1001. plcEx.Insertable(new DevAlarmInfo()
  1002. {
  1003. Frame = endTime,
  1004. Code = infos.Key,
  1005. Alarm = "当前时段无有效数据",
  1006. StartTime = startTime,
  1007. EndTime = endTime,
  1008. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  1009. Type = type
  1010. }).ExecuteCommand();
  1011. }
  1012. });
  1013. }
  1014. /// <summary>
  1015. /// Truss
  1016. /// </summary>
  1017. /// <param name="db"></param>
  1018. public void ExTrussAlarmInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  1019. {
  1020. var startTime = DateTime.Now;
  1021. var endTime = DateTime.Now;
  1022. IEnumerable<IGrouping<string, QuestDb_Truss523>> rgv523 = new List<IGrouping<string, QuestDb_Truss523>>();
  1023. var type = DevType.Truss.ToString();
  1024. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  1025. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Type == type))
  1026. {
  1027. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  1028. var alarmInfo = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  1029. startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  1030. endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  1031. }
  1032. else
  1033. {
  1034. if (!db.Queryable<QuestDb_Truss523>().Any()) return;
  1035. startTime = db.Queryable<QuestDb_Truss523>().OrderBy(x => x.Frame).First().Frame.Date;
  1036. endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  1037. }
  1038. if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  1039. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  1040. rgv523 = db.Queryable<QuestDb_Truss523>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  1041. if (!rgv523.Any())
  1042. {
  1043. plcEx.Insertable(new DevAlarmInfo()
  1044. {
  1045. Frame = endTime,
  1046. Code = "当前时段无有效数据",
  1047. Alarm = "当前时段无有效数据",
  1048. StartTime = startTime,
  1049. EndTime = endTime,
  1050. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  1051. Type = type
  1052. }).ExecuteCommand();
  1053. }
  1054. Parallel.ForEach(rgv523/*.Where(x => x.Key == "RGV4")*/, infos =>
  1055. {
  1056. // 获取第一条数据与最后一条数据
  1057. var start = infos.OrderBy(x => x.Frame).First();
  1058. var end = infos.OrderByDescending(x => x.Frame).First();
  1059. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  1060. if (plcEx.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  1061. //获取前一天最后的一条数据
  1062. var yesterEnd = plcEx.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  1063. List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  1064. var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  1065. foreach (var info in infos.OrderBy(x => x.Frame))
  1066. {
  1067. if (info.Frame == end.Frame) //最后一条数据
  1068. {
  1069. if (info.Alarm != "无")
  1070. {
  1071. //先判断是否有没有记录的报警信息
  1072. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  1073. var msgList = alarmList.Select(x => x.Msg);
  1074. //将未记录的报警信息增加到缓存中
  1075. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  1076. }
  1077. if (!alarmList.Any()) continue;
  1078. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  1079. {
  1080. Frame = alarm.Time,
  1081. Code = info.Code,
  1082. Alarm = alarm.Msg,
  1083. StartTime = alarm.Time,
  1084. EndTime = endTime,
  1085. Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  1086. Type = type
  1087. }));
  1088. }
  1089. else
  1090. {
  1091. if (info.Alarm == "无" && alarmList.Any()) //代表报警全部清空了
  1092. {
  1093. runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  1094. {
  1095. Frame = alarm.Time,
  1096. Code = info.Code,
  1097. Alarm = alarm.Msg,
  1098. StartTime = alarm.Time,
  1099. EndTime = info.Frame,
  1100. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  1101. Type = type
  1102. }));
  1103. alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  1104. }
  1105. else if (info.Alarm != "无")
  1106. {
  1107. var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  1108. var msgList = alarmList.Select(x => x.Msg);
  1109. //将未记录的报警信息增加到缓存中
  1110. alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  1111. var treatedAlarm = new List<string>();
  1112. //将已记录,但当前信息中没有的报警结束
  1113. foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  1114. {
  1115. runInfos.Add(new DevAlarmInfo()
  1116. {
  1117. Frame = alarm.Time,
  1118. Code = info.Code,
  1119. Alarm = alarm.Msg,
  1120. StartTime = alarm.Time,
  1121. EndTime = info.Frame,
  1122. Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  1123. Type = type
  1124. });
  1125. treatedAlarm.Add(alarm.Msg);
  1126. }
  1127. alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  1128. }
  1129. }
  1130. }
  1131. if (runInfos.Any())
  1132. {
  1133. plcEx.Insertable(runInfos).ExecuteCommand();
  1134. }
  1135. else
  1136. {
  1137. plcEx.Insertable(new DevAlarmInfo()
  1138. {
  1139. Frame = endTime,
  1140. Code = infos.Key,
  1141. Alarm = "当前时段无有效数据",
  1142. StartTime = startTime,
  1143. EndTime = endTime,
  1144. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  1145. Type = type
  1146. }).ExecuteCommand();
  1147. }
  1148. });
  1149. }
  1150. #endregion 异常报警信息
  1151. #region 任务状态分析
  1152. /// <summary>
  1153. /// 机械臂分析单双爪任务占比,需要按照任务类型分类
  1154. /// </summary>
  1155. /// <param name="db"></param>
  1156. public void ExRobotTaskSumRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  1157. {
  1158. var startTime = DateTime.Now;
  1159. var endTime = DateTime.Now;
  1160. IEnumerable<IGrouping<string, WCS_Robot520>> robot520 = new List<IGrouping<string, WCS_Robot520>>();
  1161. var type = DevType.SRM.ToString();
  1162. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  1163. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  1164. {
  1165. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  1166. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  1167. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  1168. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  1169. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  1170. }
  1171. else
  1172. {
  1173. if (!db.Queryable<WCS_Robot520>().Any()) return;
  1174. startTime = db.Queryable<WCS_Robot520>().OrderBy(x => x.Frame).First().Frame;
  1175. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  1176. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  1177. }
  1178. //取上一小时的第一秒
  1179. var now = DateTime.Now;
  1180. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  1181. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  1182. if (endTime > now) return; //当前时间之前
  1183. if (nowEndTime == now) return; //是当前这一个小时
  1184. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  1185. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  1186. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  1187. robot520 = db.Queryable<WCS_Robot520>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  1188. if (!robot520.Any())
  1189. {
  1190. plcEx.Insertable(new DevRunInfo()
  1191. {
  1192. Frame = endTime,
  1193. Code = "当前时段无有效数据",
  1194. RunMode = "当前时段无有效数据",
  1195. RunStatus = "当前时段无有效数据",
  1196. StartTime = startTime,
  1197. EndTime = endTime,
  1198. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  1199. Type = type
  1200. }).ExecuteCommand();
  1201. }
  1202. Parallel.ForEach(robot520, infos =>
  1203. {
  1204. var infoList = infos.Where(x => x.TaskNumber1 != 0 || x.TaskNumber2 != 0).ToList().DistinctItemBy(x => x.VoucherNo);
  1205. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  1206. foreach (var info in infoList.OrderBy(x => x.Frame))
  1207. {
  1208. var taskSum = 0;
  1209. if (info.TaskNumber1 != 0) taskSum += 1;
  1210. if (info.TaskNumber2 != 0) taskSum += 1;
  1211. runInfos.Add(new DevRunInfo()
  1212. {
  1213. Frame = info.Frame,
  1214. Code = info.Code,
  1215. RunMode = taskSum.ToString(),
  1216. RunStatus = $"{info.TaskNumber1}--{info.TaskNumber2}--{info.TaskType}",
  1217. Duration = 0,
  1218. Type = type
  1219. });
  1220. }
  1221. var sql = plcEx.Insertable(runInfos).ToSqlString();
  1222. plcEx.Ado.ExecuteCommand(GetString(sql));
  1223. });
  1224. }
  1225. /// <summary>
  1226. /// 机械臂分析单双爪任务占比,需要按照任务类型分类
  1227. /// </summary>
  1228. /// <param name="db"></param>
  1229. public void ExTrussTaskSumRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  1230. {
  1231. var startTime = DateTime.Now;
  1232. var endTime = DateTime.Now;
  1233. IEnumerable<IGrouping<string, WCS_Truss520>> truss520 = new List<IGrouping<string, WCS_Truss520>>();
  1234. var type = DevType.SRM.ToString();
  1235. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  1236. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  1237. {
  1238. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  1239. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  1240. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  1241. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  1242. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  1243. }
  1244. else
  1245. {
  1246. if (!db.Queryable<WCS_Truss520>().Any()) return;
  1247. startTime = db.Queryable<WCS_Truss520>().OrderBy(x => x.Frame).First().Frame;
  1248. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  1249. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  1250. }
  1251. //取上一小时的第一秒
  1252. var now = DateTime.Now;
  1253. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  1254. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  1255. if (endTime > now) return; //当前时间之前
  1256. if (nowEndTime == now) return; //是当前这一个小时
  1257. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  1258. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  1259. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  1260. truss520 = db.Queryable<WCS_Truss520>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  1261. if (!truss520.Any())
  1262. {
  1263. plcEx.Insertable(new DevRunInfo()
  1264. {
  1265. Frame = endTime,
  1266. Code = "当前时段无有效数据",
  1267. RunMode = "当前时段无有效数据",
  1268. RunStatus = "当前时段无有效数据",
  1269. StartTime = startTime,
  1270. EndTime = endTime,
  1271. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  1272. Type = type
  1273. }).ExecuteCommand();
  1274. }
  1275. Parallel.ForEach(truss520, infos =>
  1276. {
  1277. var infoList = infos.Where(x => x.Task1_1 != 0 || x.Task1_2 != 0 || x.Task1_3 != 0 || x.Task1_4 != 0 || x.Task1_5 != 0
  1278. || x.Task2_1 != 0 || x.Task2_2 != 0 || x.Task2_3 != 0 || x.Task2_4 != 0 || x.Task2_5 != 0).ToList().DistinctItemBy(x => x.VoucherNo);
  1279. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  1280. foreach (var info in infoList.OrderBy(x => x.Frame))
  1281. {
  1282. var taskSum = 0;
  1283. if (info.Task1_1 != 0) taskSum += 1;
  1284. if (info.Task1_2 != 0) taskSum += 1;
  1285. if (info.Task1_3 != 0) taskSum += 1;
  1286. if (info.Task1_4 != 0) taskSum += 1;
  1287. if (info.Task1_5 != 0) taskSum += 1;
  1288. if (info.Task2_1 != 0) taskSum += 1;
  1289. if (info.Task2_2 != 0) taskSum += 1;
  1290. if (info.Task2_3 != 0) taskSum += 1;
  1291. if (info.Task2_4 != 0) taskSum += 1;
  1292. if (info.Task2_5 != 0) taskSum += 1;
  1293. runInfos.Add(new DevRunInfo()
  1294. {
  1295. Frame = info.Frame,
  1296. Code = info.Code,
  1297. RunMode = taskSum.ToString(),
  1298. RunStatus = $"{info.Task1_1}--{info.Task1_2}--{info.Task1_3}--{info.Task1_4}--{info.Task1_5}--{info.Task2_1}--{info.Task2_2}--{info.Task2_3}--{info.Task2_4}--{info.Task2_5}",
  1299. Duration = 0,
  1300. Type = type
  1301. });
  1302. }
  1303. var sql = plcEx.Insertable(runInfos).ToSqlString();
  1304. plcEx.Ado.ExecuteCommand(GetString(sql));
  1305. });
  1306. }
  1307. #endregion 任务状态分析
  1308. public string GetString(string value)
  1309. {
  1310. return value.Replace(",N'", ",'")
  1311. .Replace("\0", "")
  1312. .Replace("(N'", "('") + "\r";
  1313. }
  1314. }
  1315. /// <summary>
  1316. /// 设备报警
  1317. /// </summary>
  1318. public class EquipmentAlarm
  1319. {
  1320. /// <summary>
  1321. /// 内容
  1322. /// </summary>
  1323. public string Msg { get; set; }
  1324. /// <summary>
  1325. /// 时间
  1326. /// </summary>
  1327. public DateTime Time { get; set; }
  1328. }
  1329. /// <summary>
  1330. /// 设备状态信息
  1331. /// </summary>
  1332. public class EquipmentStatus
  1333. {
  1334. /// <summary>
  1335. /// 设备号
  1336. /// </summary>
  1337. public string Code { get; set; }
  1338. /// <summary>
  1339. /// 内容
  1340. /// </summary>
  1341. public string con { get; set; }
  1342. /// <summary>
  1343. /// 内容
  1344. /// </summary>
  1345. public int Status { get; set; }
  1346. /// <summary>
  1347. /// 时间
  1348. /// </summary>
  1349. public DateTime Time { get; set; }
  1350. }
  1351. /// <summary>
  1352. ///
  1353. /// </summary>
  1354. /// <typeparam name="T"></typeparam>
  1355. public class Quest<T>
  1356. {
  1357. public T Data { get; set; }
  1358. }
  1359. public class KeyValue
  1360. {
  1361. public string key { get; set; }
  1362. public string value { get; set; }
  1363. }
  1364. }