DataCollectionSysyem.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.SqlSugars;
  3. using SqlSugar;
  4. using System.Collections.Concurrent;
  5. using System.ComponentModel;
  6. using System.Data;
  7. using WCS.Core;
  8. using WCS.Entity.Protocol.DataStructure;
  9. using WCS.Entity.Protocol.HUB;
  10. using WCS.Entity.Protocol.Robot;
  11. using WCS.Entity.Protocol.SRM;
  12. using WCS.Entity.Protocol.Station;
  13. using WCS.WorkEngineering.Worlds;
  14. namespace WCS.WorkEngineering.Systems
  15. {
  16. /// <summary>
  17. /// 数据采集系统
  18. /// </summary>
  19. [BelongTo(typeof(MainWorld))]
  20. [Description("数据采集系统")]
  21. public class DataCollectionSysyem : DeviceSystem<Device<IStation520>>
  22. {
  23. public static DeviceDataPack pack = new DeviceDataPack();
  24. private static object locker = new object();
  25. public DataCollectionSysyem()
  26. {
  27. }
  28. /// <summary>
  29. /// 所有设备数据
  30. /// Key 是不同设备所使用的类型 例如DeviceDataCollection<SRMData>
  31. /// value 不同设备的具体数据
  32. /// </summary>
  33. public static ConcurrentDictionary<string, DeviceData> AllDatas = new ConcurrentDictionary<string, DeviceData>();
  34. protected override bool ParallelDo => true;
  35. public override bool Select(Device dev)
  36. {
  37. return dev.Code == "1";
  38. }
  39. public override void Do(Device<IStation520> objDev)
  40. {
  41. //通过数据条数处理
  42. var db = new SqlSugarHelper().PLC;
  43. var plcEx = new SqlSugarHelper().PLCEX;
  44. //ExRobotRunInfo(db, plcEx);
  45. ExSrmRunInfo(db, plcEx);
  46. //ExRobotAlarmInfo(db);
  47. //ExSrmAlarmInfo(db);
  48. //ExRgvAlarmInfo(db);
  49. ExSrmTaskSumRunInfo(db, plcEx);
  50. }
  51. #region 设备运行信息收集
  52. /// <summary>
  53. /// 机械臂
  54. /// </summary>
  55. /// <param name="db"></param>
  56. public void ExRobotRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  57. {
  58. var startTime = DateTime.Now;
  59. var endTime = DateTime.Now;
  60. IEnumerable<IGrouping<string, WCS_Robot521>> robot521 = new List<IGrouping<string, WCS_Robot521>>();
  61. var type = DevType.Robot.ToString();
  62. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  63. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  64. {
  65. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  66. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  67. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  68. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  69. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  70. }
  71. else
  72. {
  73. if (!db.Queryable<WCS_Robot521>().Any()) return;
  74. startTime = db.Queryable<WCS_Robot521>().OrderBy(x => x.Frame).First().Frame;
  75. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  76. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  77. }
  78. //取上一小时的第一秒
  79. var now = DateTime.Now;
  80. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  81. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  82. if (endTime > now) return; //当前时间之前
  83. if (nowEndTime == now) return; //是当前这一个小时
  84. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 1, 0);
  85. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  86. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  87. robot521 = db.Queryable<WCS_Robot521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  88. if (!robot521.Any())
  89. {
  90. plcEx.Insertable(new DevRunInfo()
  91. {
  92. Frame = endTime,
  93. Code = "当前时段无有效数据",
  94. RunMode = "当前时段无有效数据",
  95. RunStatus = "当前时段无有效数据",
  96. StartTime = startTime,
  97. EndTime = endTime,
  98. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  99. Type = type
  100. }).ExecuteCommand();
  101. }
  102. foreach (var infos in robot521)
  103. {
  104. // 获取第一条数据与最后一条数据
  105. var start = infos.OrderBy(x => x.Frame).First();
  106. var end = infos.OrderByDescending(x => x.Frame).First();
  107. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  108. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  109. //获取前一天最后的一条数据
  110. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  111. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  112. foreach (var info in infos.OrderBy(x => x.Frame))
  113. {
  114. if (info.Frame == start.Frame) //当天的第一条数据
  115. {
  116. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  117. {
  118. runInfos.Add(new DevRunInfo()
  119. {
  120. Frame = info.Frame,
  121. Code = info.Code,
  122. RunMode = info.Mode.GetDescription(),
  123. RunStatus = info.Status.GetDescription(),
  124. StartTime = startTime,
  125. EndTime = info.Frame,
  126. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  127. Type = type
  128. });
  129. }
  130. else //如果有就用前一天的最后一条数据做计算
  131. {
  132. runInfos.Add(new DevRunInfo()
  133. {
  134. Frame = info.Frame,
  135. Code = info.Code,
  136. RunMode = yesterEnd.RunMode,
  137. RunStatus = yesterEnd.RunStatus,
  138. StartTime = startTime,
  139. EndTime = info.Frame,
  140. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  141. Type = type
  142. });
  143. }
  144. }
  145. else //状态出现状态变化时或最后一条数据
  146. {
  147. if (start.Mode != info.Mode || start.Status != info.Status || info.Frame == end.Frame)
  148. {
  149. var runInfo = new DevRunInfo()
  150. {
  151. Frame = info.Frame,
  152. Code = info.Code,
  153. RunMode = start.Mode.GetDescription(),
  154. RunStatus = start.Status.GetDescription(),
  155. StartTime = start.Frame,
  156. Type = type
  157. };
  158. if (info.Frame == end.Frame) runInfo.EndTime = endTime;
  159. else runInfo.EndTime = info.Frame;
  160. runInfo.Duration = Convert.ToInt64((runInfo.EndTime - runInfo.StartTime).TotalMilliseconds);
  161. runInfos.Add(runInfo);
  162. start = info;
  163. }
  164. }
  165. }
  166. var sql = plcEx.Insertable(runInfos).ToSqlString();
  167. plcEx.Ado.ExecuteCommand(GetString(sql));
  168. }
  169. }
  170. /// <summary>
  171. /// 堆垛机
  172. /// </summary>
  173. /// <param name="db"></param>
  174. public void ExSrmRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  175. {
  176. var startTime = DateTime.Now;
  177. var endTime = DateTime.Now;
  178. IEnumerable<IGrouping<string, WCS_SRM521>> srm521 = new List<IGrouping<string, WCS_SRM521>>();
  179. var type = DevType.SRM.ToString();
  180. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  181. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  182. {
  183. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  184. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  185. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  186. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  187. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  188. }
  189. else
  190. {
  191. if (!db.Queryable<WCS_SRM521>().Any()) return;
  192. startTime = db.Queryable<WCS_SRM521>().OrderBy(x => x.Frame).First().Frame;
  193. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  194. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  195. }
  196. //取上一小时的第一秒
  197. var now = DateTime.Now;
  198. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  199. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  200. if (endTime > now) return; //当前时间之前
  201. if (nowEndTime == now) return; //是当前这一个小时
  202. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 10, 0);
  203. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  204. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  205. srm521 = db.Queryable<WCS_SRM521>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  206. if (!srm521.Any())
  207. {
  208. plcEx.Insertable(new DevRunInfo()
  209. {
  210. Frame = endTime,
  211. Code = "当前时段无有效数据",
  212. RunMode = "当前时段无有效数据",
  213. RunStatus = "当前时段无有效数据",
  214. StartTime = startTime,
  215. EndTime = endTime,
  216. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  217. Type = type
  218. }).ExecuteCommand();
  219. }
  220. foreach (var infos in srm521)
  221. {
  222. // 获取第一条数据与最后一条数据
  223. var start = infos.OrderBy(x => x.Frame).First();
  224. var end = infos.OrderByDescending(x => x.Frame).First();
  225. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  226. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  227. //获取前一天最后的一条数据
  228. var yesterEnd = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  229. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  230. foreach (var info in infos.OrderBy(x => x.Frame))
  231. {
  232. if (info.Frame == start.Frame) //当天的第一条数据
  233. {
  234. if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  235. {
  236. runInfos.Add(new DevRunInfo()
  237. {
  238. Frame = info.Frame,
  239. Code = info.Code,
  240. RunMode = info.Mode.GetDescription(),
  241. RunStatus = info.Status.GetDescription(),
  242. StartTime = startTime,
  243. EndTime = info.Frame,
  244. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  245. Type = type
  246. });
  247. }
  248. else //如果有就用前一天的最后一条数据做计算
  249. {
  250. runInfos.Add(new DevRunInfo()
  251. {
  252. Frame = info.Frame,
  253. Code = info.Code,
  254. RunMode = yesterEnd.RunMode,
  255. RunStatus = yesterEnd.RunStatus,
  256. StartTime = startTime,
  257. EndTime = info.Frame,
  258. Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  259. Type = type
  260. });
  261. }
  262. }
  263. else //状态出现状态变化时或最后一条数据
  264. {
  265. if (start.Mode != info.Mode || start.Status != info.Status || info.Frame == end.Frame)
  266. {
  267. var runInfo = new DevRunInfo()
  268. {
  269. Frame = info.Frame,
  270. Code = info.Code,
  271. RunMode = start.Mode.GetDescription(),
  272. RunStatus = start.Status.GetDescription(),
  273. StartTime = start.Frame,
  274. Type = type
  275. };
  276. if (info.Frame == end.Frame) runInfo.EndTime = endTime;
  277. else runInfo.EndTime = info.Frame;
  278. runInfo.Duration = Convert.ToInt64((runInfo.EndTime - runInfo.StartTime).TotalMilliseconds);
  279. runInfos.Add(runInfo);
  280. start = info;
  281. }
  282. }
  283. }
  284. var sql = plcEx.Insertable(runInfos).ToSqlString();
  285. plcEx.Ado.ExecuteCommand(GetString(sql));
  286. }
  287. }
  288. #endregion 设备运行信息收集
  289. #region 异常报警信息
  290. ///// <summary>
  291. ///// 机械臂
  292. ///// </summary>
  293. ///// <param name="db"></param>
  294. //public void ExRobotAlarmInfo(SqlSugarScopeProvider db)
  295. //{
  296. // var startTime = DateTime.Now;
  297. // var endTime = DateTime.Now;
  298. // IEnumerable<IGrouping<string, QuestDb_Robot522>> robot522 = new List<IGrouping<string, QuestDb_Robot522>>();
  299. // //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  300. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Type == DevType.Robot))
  301. // {
  302. // //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  303. // var alarmInfo = db.Queryable<DevAlarmInfo>().Where(x => x.Type == DevType.Robot).OrderByDescending(x => x.Frame).First();
  304. // startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  305. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  306. // }
  307. // else
  308. // {
  309. // if (!db.Queryable<QuestDb_Robot522>().Any()) return;
  310. // startTime = db.Queryable<QuestDb_Robot522>().OrderBy(x => x.Frame).First().Frame.Date;
  311. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  312. // }
  313. // if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  314. // if (db.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == DevType.Robot)) return;
  315. // robot522 = db.Queryable<QuestDb_Robot522>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  316. // if (!robot522.Any())
  317. // {
  318. // db.Insertable(new DevAlarmInfo()
  319. // {
  320. // Frame = endTime,
  321. // Code = "当前时段无有效数据",
  322. // Alarm = "当前时段无有效数据",
  323. // StartTime = startTime,
  324. // EndTime = endTime,
  325. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  326. // Type = DevType.Robot
  327. // }).ExecuteCommand();
  328. // }
  329. // Parallel.ForEach(robot522, infos =>
  330. // {
  331. // // 获取第一条数据与最后一条数据
  332. // var start = infos.OrderBy(x => x.Frame).First();
  333. // var end = infos.OrderByDescending(x => x.Frame).First();
  334. // //通过是否有最后一条数据来确定当前数据是否有分析存储过
  335. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  336. // //获取前一天最后的一条数据
  337. // var yesterEnd = db.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  338. // List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  339. // var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  340. // foreach (var info in infos.OrderBy(x => x.Frame))
  341. // {
  342. // if (info.Frame == end.Frame) //最后一条数据
  343. // {
  344. // if (info.Alarm != "无")
  345. // {
  346. // //先判断是否有没有记录的报警信息
  347. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  348. // var msgList = alarmList.Select(x => x.Msg);
  349. // //将未记录的报警信息增加到缓存中
  350. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  351. // }
  352. // if (!alarmList.Any()) continue;
  353. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  354. // {
  355. // Frame = alarm.Time,
  356. // Code = info.Code,
  357. // Alarm = alarm.Msg,
  358. // StartTime = alarm.Time,
  359. // EndTime = endTime,
  360. // Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  361. // Type = DevType.Robot
  362. // }));
  363. // }
  364. // else
  365. // {
  366. // if (info.Alarm == "无" && alarmList.Any()) //代表报警全部清空了
  367. // {
  368. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  369. // {
  370. // Frame = alarm.Time,
  371. // Code = info.Code,
  372. // Alarm = alarm.Msg,
  373. // StartTime = alarm.Time,
  374. // EndTime = info.Frame,
  375. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  376. // Type = DevType.Robot
  377. // }));
  378. // alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  379. // }
  380. // else if (info.Alarm != "无")
  381. // {
  382. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  383. // var msgList = alarmList.Select(x => x.Msg);
  384. // //将未记录的报警信息增加到缓存中
  385. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  386. // var treatedAlarm = new List<string>();
  387. // //将已记录,但当前信息中没有的报警结束
  388. // foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  389. // {
  390. // runInfos.Add(new DevAlarmInfo()
  391. // {
  392. // Frame = alarm.Time,
  393. // Code = info.Code,
  394. // Alarm = alarm.Msg,
  395. // StartTime = alarm.Time,
  396. // EndTime = info.Frame,
  397. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  398. // Type = DevType.Robot
  399. // });
  400. // treatedAlarm.Add(alarm.Msg);
  401. // }
  402. // alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  403. // }
  404. // }
  405. // }
  406. // if (runInfos.Any())
  407. // {
  408. // var sql = db.Insertable(runInfos).ToSqlString();
  409. // db.Ado.ExecuteCommand(GetString(sql));
  410. // }
  411. // else
  412. // {
  413. // db.Insertable(new DevAlarmInfo()
  414. // {
  415. // Frame = endTime,
  416. // Code = infos.Key,
  417. // Alarm = "当前时段无有效数据",
  418. // StartTime = startTime,
  419. // EndTime = endTime,
  420. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  421. // Type = DevType.Robot
  422. // }).ExecuteCommand();
  423. // }
  424. // });
  425. //}
  426. ///// <summary>
  427. ///// 堆垛机
  428. ///// </summary>
  429. ///// <param name="db"></param>
  430. //public void ExSrmAlarmInfo(SqlSugarScopeProvider db)
  431. //{
  432. // var startTime = DateTime.Now;
  433. // var endTime = DateTime.Now;
  434. // IEnumerable<IGrouping<string, QuestDb_SRM523>> srm523 = new List<IGrouping<string, QuestDb_SRM523>>();
  435. // //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  436. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Type == DevType.SRM))
  437. // {
  438. // //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  439. // var alarmInfo = db.Queryable<DevAlarmInfo>().Where(x => x.Type == DevType.SRM).OrderByDescending(x => x.Frame).First();
  440. // startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  441. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  442. // }
  443. // else
  444. // {
  445. // if (!db.Queryable<QuestDb_SRM523>().Any()) return;
  446. // startTime = db.Queryable<QuestDb_SRM523>().OrderBy(x => x.Frame).First().Frame.Date;
  447. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  448. // }
  449. // if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  450. // if (db.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == DevType.SRM)) return;
  451. // srm523 = db.Queryable<QuestDb_SRM523>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  452. // if (!srm523.Any())
  453. // {
  454. // db.Insertable(new DevAlarmInfo()
  455. // {
  456. // Frame = endTime,
  457. // Code = "当前时段无有效数据",
  458. // Alarm = "当前时段无有效数据",
  459. // StartTime = startTime,
  460. // EndTime = endTime,
  461. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  462. // Type = DevType.SRM
  463. // }).ExecuteCommand();
  464. // }
  465. // Parallel.ForEach(srm523, infos =>
  466. // {
  467. // // 获取第一条数据与最后一条数据
  468. // var start = infos.OrderBy(x => x.Frame).First();
  469. // var end = infos.OrderByDescending(x => x.Frame).First();
  470. // //通过是否有最后一条数据来确定当前数据是否有分析存储过
  471. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  472. // //获取前一天最后的一条数据
  473. // var yesterEnd = db.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  474. // List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  475. // var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  476. // foreach (var info in infos.OrderBy(x => x.Frame))
  477. // {
  478. // if (info.Frame == end.Frame) //最后一条数据
  479. // {
  480. // if (info.Alarm != "无,无")
  481. // {
  482. // //先判断是否有没有记录的报警信息
  483. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).Where(x => x != "无").ToList();
  484. // var msgList = alarmList.Select(x => x.Msg);
  485. // //将未记录的报警信息增加到缓存中
  486. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  487. // }
  488. // if (!alarmList.Any()) continue;
  489. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  490. // {
  491. // Frame = alarm.Time,
  492. // Code = info.Code,
  493. // Alarm = alarm.Msg,
  494. // StartTime = alarm.Time,
  495. // EndTime = endTime,
  496. // Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  497. // Type = DevType.SRM
  498. // }));
  499. // }
  500. // else
  501. // {
  502. // if (info.Alarm == "无,无" && alarmList.Any()) //代表报警全部清空了
  503. // {
  504. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  505. // {
  506. // Frame = alarm.Time,
  507. // Code = info.Code,
  508. // Alarm = alarm.Msg,
  509. // StartTime = alarm.Time,
  510. // EndTime = info.Frame,
  511. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  512. // Type = DevType.SRM
  513. // }));
  514. // alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  515. // }
  516. // else if (info.Alarm != "无,无")
  517. // {
  518. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).Where(x => x != "无").ToList();
  519. // var msgList = alarmList.Select(x => x.Msg);
  520. // //将未记录的报警信息增加到缓存中
  521. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  522. // var treatedAlarm = new List<string>();
  523. // //将已记录,但当前信息中没有的报警结束
  524. // foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  525. // {
  526. // runInfos.Add(new DevAlarmInfo()
  527. // {
  528. // Frame = alarm.Time,
  529. // Code = info.Code,
  530. // Alarm = alarm.Msg,
  531. // StartTime = alarm.Time,
  532. // EndTime = info.Frame,
  533. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  534. // Type = DevType.SRM
  535. // });
  536. // treatedAlarm.Add(alarm.Msg);
  537. // }
  538. // alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  539. // }
  540. // }
  541. // }
  542. // if (runInfos.Any())
  543. // {
  544. // var sql = db.Insertable(runInfos).ToSqlString();
  545. // db.Ado.ExecuteCommand(GetString(sql));
  546. // }
  547. // else
  548. // {
  549. // db.Insertable(new DevAlarmInfo()
  550. // {
  551. // Frame = endTime,
  552. // Code = infos.Key,
  553. // Alarm = "当前时段无有效数据",
  554. // StartTime = startTime,
  555. // EndTime = endTime,
  556. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  557. // Type = DevType.SRM
  558. // }).ExecuteCommand();
  559. // }
  560. // });
  561. //}
  562. ///// <summary>
  563. ///// rgv
  564. ///// </summary>
  565. ///// <param name="db"></param>
  566. //public void ExRgvAlarmInfo(SqlSugarScopeProvider db)
  567. //{
  568. // var startTime = DateTime.Now;
  569. // var endTime = DateTime.Now;
  570. // IEnumerable<IGrouping<string, QuestDb_RGV523>> rgv523 = new List<IGrouping<string, QuestDb_RGV523>>();
  571. // //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  572. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Type == DevType.RGV))
  573. // {
  574. // //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  575. // var alarmInfo = db.Queryable<DevAlarmInfo>().Where(x => x.Type == DevType.RGV).OrderByDescending(x => x.Frame).First();
  576. // startTime = alarmInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  577. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  578. // }
  579. // else
  580. // {
  581. // if (!db.Queryable<QuestDb_RGV523>().Any()) return;
  582. // startTime = db.Queryable<QuestDb_RGV523>().OrderBy(x => x.Frame).First().Frame.Date;
  583. // endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  584. // }
  585. // if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  586. // if (db.Queryable<DevAlarmInfo>().Any(x => x.EndTime == endTime && x.Type == DevType.RGV)) return;
  587. // rgv523 = db.Queryable<QuestDb_RGV523>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  588. // if (!rgv523.Any())
  589. // {
  590. // db.Insertable(new DevAlarmInfo()
  591. // {
  592. // Frame = endTime,
  593. // Code = "当前时段无有效数据",
  594. // Alarm = "当前时段无有效数据",
  595. // StartTime = startTime,
  596. // EndTime = endTime,
  597. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  598. // Type = DevType.RGV
  599. // }).ExecuteCommand();
  600. // }
  601. // Parallel.ForEach(rgv523/*.Where(x => x.Key == "RGV4")*/, infos =>
  602. // {
  603. // // 获取第一条数据与最后一条数据
  604. // var start = infos.OrderBy(x => x.Frame).First();
  605. // var end = infos.OrderByDescending(x => x.Frame).First();
  606. // //通过是否有最后一条数据来确定当前数据是否有分析存储过
  607. // if (db.Queryable<DevAlarmInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  608. // //获取前一天最后的一条数据
  609. // var yesterEnd = db.Queryable<DevAlarmInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  610. // List<DevAlarmInfo> runInfos = new List<DevAlarmInfo>();//需要保存的数据
  611. // var alarmList = new List<EquipmentAlarm>();//未结束的报警信息
  612. // foreach (var info in infos.OrderBy(x => x.Frame))
  613. // {
  614. // if (info.Frame == end.Frame) //最后一条数据
  615. // {
  616. // if (info.Alarm != "无")
  617. // {
  618. // //先判断是否有没有记录的报警信息
  619. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  620. // var msgList = alarmList.Select(x => x.Msg);
  621. // //将未记录的报警信息增加到缓存中
  622. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  623. // }
  624. // if (!alarmList.Any()) continue;
  625. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  626. // {
  627. // Frame = alarm.Time,
  628. // Code = info.Code,
  629. // Alarm = alarm.Msg,
  630. // StartTime = alarm.Time,
  631. // EndTime = endTime,
  632. // Duration = Convert.ToInt64((endTime - alarm.Time).TotalMilliseconds),
  633. // Type = DevType.RGV
  634. // }));
  635. // }
  636. // else
  637. // {
  638. // if (info.Alarm == "无" && alarmList.Any()) //代表报警全部清空了
  639. // {
  640. // runInfos.AddRange(alarmList.Select(alarm => new DevAlarmInfo()
  641. // {
  642. // Frame = alarm.Time,
  643. // Code = info.Code,
  644. // Alarm = alarm.Msg,
  645. // StartTime = alarm.Time,
  646. // EndTime = info.Frame,
  647. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  648. // Type = DevType.RGV
  649. // }));
  650. // alarmList = new List<EquipmentAlarm>(); //清空现有报警信息
  651. // }
  652. // else if (info.Alarm != "无")
  653. // {
  654. // var alarmMsg = Convert.ToString(info.Alarm).Split(",").Select(x => x.Split(",")).SelectMany(x => x).ToList();
  655. // var msgList = alarmList.Select(x => x.Msg);
  656. // //将未记录的报警信息增加到缓存中
  657. // alarmList.AddRange(alarmMsg.Where(msg => !msgList.Contains(msg)).Select(msg => new EquipmentAlarm() { Time = info.Frame, Msg = msg }));
  658. // var treatedAlarm = new List<string>();
  659. // //将已记录,但当前信息中没有的报警结束
  660. // foreach (var alarm in alarmList.Where(x => !alarmMsg.Contains(x.Msg)))
  661. // {
  662. // runInfos.Add(new DevAlarmInfo()
  663. // {
  664. // Frame = alarm.Time,
  665. // Code = info.Code,
  666. // Alarm = alarm.Msg,
  667. // StartTime = alarm.Time,
  668. // EndTime = info.Frame,
  669. // Duration = Convert.ToInt64((info.Frame - alarm.Time).TotalMilliseconds),
  670. // Type = DevType.RGV
  671. // });
  672. // treatedAlarm.Add(alarm.Msg);
  673. // }
  674. // alarmList = alarmList.Where(x => !treatedAlarm.Contains(x.Msg)).ToList();
  675. // }
  676. // }
  677. // }
  678. // if (runInfos.Any())
  679. // {
  680. // db.Insertable(runInfos).ExecuteCommand();
  681. // }
  682. // else
  683. // {
  684. // db.Insertable(new DevAlarmInfo()
  685. // {
  686. // Frame = endTime,
  687. // Code = infos.Key,
  688. // Alarm = "当前时段无有效数据",
  689. // StartTime = startTime,
  690. // EndTime = endTime,
  691. // Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  692. // Type = DevType.RGV
  693. // }).ExecuteCommand();
  694. // }
  695. // });
  696. //}
  697. #endregion 异常报警信息
  698. #region 任务状态分析
  699. /// <summary>
  700. /// 机械臂
  701. /// </summary>
  702. /// <param name="db"></param>
  703. public void ExRobotTaskSumRunInfo(SqlSugarScopeProvider db)
  704. {
  705. var startTime = DateTime.Now;
  706. var endTime = DateTime.Now;
  707. IEnumerable<IGrouping<string, WCS_Robot520>> robot520 = new List<IGrouping<string, WCS_Robot520>>();
  708. var type = DevType.RobotTaskSum.ToString();
  709. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  710. if (db.Queryable<DevRunInfo>().Any(x => x.Type == type))
  711. {
  712. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  713. var runInfo = db.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  714. startTime = runInfo.Frame.AddDays(+1).Date;//后一天的初始时间
  715. endTime = startTime.AddDays(+1).AddMilliseconds(-1);//
  716. }
  717. else
  718. {
  719. if (!db.Queryable<WCS_Robot520>().Any()) return;
  720. startTime = db.Queryable<WCS_Robot520>().OrderBy(x => x.Frame).First().Frame.Date;
  721. endTime = startTime.AddDays(+1).AddMilliseconds(-1);
  722. }
  723. if (endTime > DateTime.Now.AddHours(1)) return; //一次处理24小时的数据
  724. if (db.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  725. robot520 = db.Queryable<WCS_Robot520>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  726. if (!robot520.Any())
  727. {
  728. db.Insertable(new DevRunInfo()
  729. {
  730. Frame = endTime,
  731. Code = "当前时段无有效数据",
  732. RunMode = "当前时段无有效数据",
  733. RunStatus = "当前时段无有效数据",
  734. StartTime = startTime,
  735. EndTime = endTime,
  736. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  737. Type = type
  738. }).ExecuteCommand();
  739. }
  740. Parallel.ForEach(robot520, infos =>
  741. {
  742. //infos = infos.Where(x => x.TaskNumber1 != 0 || x.TaskNumber2 != 0).ToList();
  743. // 获取第一条数据与最后一条数据
  744. var start = infos.OrderBy(x => x.Frame).First();
  745. var end = infos.OrderByDescending(x => x.Frame).First();
  746. //通过是否有最后一条数据来确定当前数据是否有分析存储过
  747. if (db.Queryable<DevRunInfo>().Any(x => x.Code == infos.Key && x.EndTime == end.Frame)) return;
  748. //获取前一天最后的一条数据
  749. var yesterEnd = db.Queryable<DevRunInfo>().Where(x => x.Code == infos.Key && x.Frame < endTime).OrderByDescending(x => x.Frame).First();
  750. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  751. //foreach (var info in infos.OrderBy(x => x.Frame))
  752. //{
  753. // if (info.Frame == start.Frame) //当天的第一条数据
  754. // {
  755. // if (yesterEnd == null) //如果没有前一天的最后一条数据,就有用当天的第一条数据状态做计算
  756. // {
  757. // runInfos.Add(new DevRunInfo()
  758. // {
  759. // Frame = info.Frame,
  760. // Code = info.Code,
  761. // RunMode = info.RobotMode.GetDescription(),
  762. // RunStatus = info.RunStatus.GetDescription(),
  763. // StartTime = startTime,
  764. // EndTime = info.Frame,
  765. // Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  766. // Type = DevType.RobotTaskSum
  767. // });
  768. // }
  769. // else //如果有就用前一天的最后一条数据做计算
  770. // {
  771. // runInfos.Add(new DevRunInfo()
  772. // {
  773. // Frame = info.Frame,
  774. // Code = info.Code,
  775. // RunMode = yesterEnd.RunMode,
  776. // RunStatus = yesterEnd.RunStatus,
  777. // StartTime = startTime,
  778. // EndTime = info.Frame,
  779. // Duration = Convert.ToInt64((info.Frame - startTime).TotalMilliseconds),
  780. // Type = DevType.RobotTaskSum
  781. // });
  782. // }
  783. // }
  784. // else if (info.Frame == end.Frame) //当天的最后一条数据
  785. // {
  786. // runInfos.Add(new DevRunInfo()
  787. // {
  788. // Frame = info.Frame,
  789. // Code = info.Code,
  790. // RunMode = info.RobotMode.GetDescription(),
  791. // RunStatus = info.RunStatus.GetDescription(),
  792. // StartTime = info.Frame,
  793. // EndTime = endTime,
  794. // Duration = Convert.ToInt64((endTime - info.Frame).TotalMilliseconds),
  795. // Type = DevType.RobotTaskSum
  796. // });
  797. // }
  798. // else //中间数据
  799. // {
  800. // if (start.RobotMode == info.RobotMode && start.RunStatus == info.RunStatus) continue;
  801. // runInfos.Add(new DevRunInfo()
  802. // {
  803. // Frame = info.Frame,
  804. // Code = info.Code,
  805. // RunMode = start.RobotMode.GetDescription(),
  806. // RunStatus = start.RunStatus.GetDescription(),
  807. // StartTime = start.Frame,
  808. // EndTime = info.Frame,
  809. // Duration = Convert.ToInt64((info.Frame - start.Frame).TotalMilliseconds),
  810. // Type = DevType.RobotTaskSum
  811. // });
  812. // start = info;
  813. // }
  814. //}
  815. var sql = db.Insertable(runInfos).ToSqlString();
  816. db.Ado.ExecuteCommand(GetString(sql));
  817. });
  818. }
  819. /// <summary>
  820. /// 堆垛机任务数量统计
  821. /// </summary>
  822. /// <param name="db"></param>
  823. public void ExSrmTaskSumRunInfo(SqlSugarScopeProvider db, SqlSugarScopeProvider plcEx)
  824. {
  825. var startTime = DateTime.Now;
  826. var endTime = DateTime.Now;
  827. IEnumerable<IGrouping<string, WCS_SRM520>> srm520 = new List<IGrouping<string, WCS_SRM520>>();
  828. var type = DevType.SrmTaskSum.ToString();
  829. //查看rgv类型是否存在运行信息,用于系统被第一次启用时进行初始化
  830. if (plcEx.Queryable<DevRunInfo>().Any(x => x.Type == type))
  831. {
  832. //已有信息,查找最后一条信息用于获取开始时间,最后一条通常是前一天的最后条数据
  833. var runInfo = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type).OrderByDescending(x => x.Frame).First();
  834. startTime = runInfo.Frame.AddHours(+1);//后一个小时
  835. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  836. endTime = startTime.AddHours(+1).AddMilliseconds(-1);//
  837. }
  838. else
  839. {
  840. if (db.Queryable<WCS_SRM520>().Count() <= 0) return;
  841. startTime = db.Queryable<WCS_SRM520>().OrderBy(x => x.Frame).First().Frame;
  842. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0); //后一个小时的开始时间
  843. endTime = startTime.AddHours(+1).AddMilliseconds(-1);
  844. }
  845. //取上一小时的第一秒
  846. var now = DateTime.Now;
  847. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
  848. var nowEndTime = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, 0, 0);
  849. if (endTime > now) return; //当前时间之前
  850. if (nowEndTime == now) return; //是当前这一个小时
  851. now = new DateTime(now.Year, now.Month, now.Day, now.Hour, 01, 0);
  852. if (DateTime.Now < now) return;// 每个小时的前十分钟不进行数据分析处理,仅在每小时的10-59之内进行处理
  853. if (plcEx.Queryable<DevRunInfo>().Any(x => x.EndTime == endTime && x.Type == type)) return;
  854. srm520 = db.Queryable<WCS_SRM520>().Where(x => x.Frame > startTime && x.Frame <= endTime).ToList().GroupBy(x => x.Code).ToList();
  855. if (!srm520.Any())
  856. {
  857. plcEx.Insertable(new DevRunInfo()
  858. {
  859. Frame = endTime,
  860. Code = "当前时段无有效数据",
  861. RunMode = "当前时段无有效数据",
  862. RunStatus = "当前时段无有效数据",
  863. StartTime = startTime,
  864. EndTime = endTime,
  865. Duration = Convert.ToInt64((endTime - startTime).TotalMilliseconds),
  866. Type = type
  867. }).ExecuteCommand();
  868. }
  869. foreach (var infos in srm520)
  870. {
  871. var infoList = infos.Where(x => x.TaskID1 != 0 || x.TaskID2 != 0).ToList().DistinctItemBy(x => x.VoucherNo);
  872. List<DevRunInfo> runInfos = new List<DevRunInfo>();
  873. foreach (var info in infoList.OrderBy(x => x.Frame))
  874. {
  875. var taskSum = 0;
  876. if (info.TaskID1 != 0) taskSum += 1;
  877. if (info.TaskID2 != 0) taskSum += 1;
  878. var taskType = info.TaskType1 == 0 ? info.TaskType2 : info.TaskType1;
  879. runInfos.Add(new DevRunInfo()
  880. {
  881. Frame = info.Frame,
  882. Code = info.Code,
  883. RunMode = taskSum.ToString(),
  884. RunStatus = $"{info.TaskID1}--{info.TaskID2}--{taskType}",
  885. Duration = 0,
  886. Type = type
  887. });
  888. }
  889. var sql = plcEx.Insertable(runInfos).ToSqlString();
  890. plcEx.Ado.ExecuteCommand(GetString(sql));
  891. }
  892. }
  893. #endregion 任务状态分析
  894. public string GetString(string value)
  895. {
  896. return value.Replace(",N'", ",'")
  897. .Replace("\0", "")
  898. .Replace("(N'", "('") + "\r";
  899. }
  900. }
  901. /// <summary>
  902. /// 设备报警
  903. /// </summary>
  904. public class EquipmentAlarm
  905. {
  906. /// <summary>
  907. /// 内容
  908. /// </summary>
  909. public string Msg { get; set; }
  910. /// <summary>
  911. /// 时间
  912. /// </summary>
  913. public DateTime Time { get; set; }
  914. }
  915. /// <summary>
  916. /// 设备状态信息
  917. /// </summary>
  918. public class EquipmentStatus
  919. {
  920. /// <summary>
  921. /// 设备号
  922. /// </summary>
  923. public string Code { get; set; }
  924. /// <summary>
  925. /// 内容
  926. /// </summary>
  927. public string con { get; set; }
  928. /// <summary>
  929. /// 内容
  930. /// </summary>
  931. public int Status { get; set; }
  932. /// <summary>
  933. /// 时间
  934. /// </summary>
  935. public DateTime Time { get; set; }
  936. }
  937. /// <summary>
  938. ///
  939. /// </summary>
  940. /// <typeparam name="T"></typeparam>
  941. public class Quest<T>
  942. {
  943. public T Data { get; set; }
  944. }
  945. public class KeyValue
  946. {
  947. public string key { get; set; }
  948. public string value { get; set; }
  949. }
  950. }