WcsController.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. using System.ComponentModel;
  2. using Microsoft.AspNetCore.Mvc;
  3. using Newtonsoft.Json;
  4. using PlcSiemens.Core.Extension;
  5. using ServiceCenter;
  6. using ServiceCenter.Extensions;
  7. using ServiceCenter.Redis;
  8. using ServiceCenter.SqlSugars;
  9. using System.Net.NetworkInformation;
  10. using System.Text;
  11. using SqlSugar;
  12. using WCS.Core;
  13. using WCS.Entity;
  14. using WCS.Entity.Protocol.DataStructure;
  15. using WCS.Entity.Protocol.HUB;
  16. using WCS.Entity.Protocol.Protocol.Robot;
  17. using WCS.Entity.Protocol.SRM;
  18. using WCS.WorkEngineering.Extensions;
  19. using WCS.WorkEngineering.Systems;
  20. using WCS.WorkEngineering.WebApi.Models.WCS.Request;
  21. using WCS.WorkEngineering.WebApi.Models.WCS.Response;
  22. using WCS.WorkEngineering.WebApi.Models.WMS.Response;
  23. using TaskStatus = WCS.Entity.TaskStatus;
  24. using static Dm.net.buffer.ByteArrayBuffer;
  25. using System.Security.Claims;
  26. using WCS.Entity.Protocol.Truss;
  27. // ReSharper disable PossibleLossOfFraction
  28. namespace WCS.WorkEngineering.WebApi.Controllers
  29. {
  30. /// <summary>
  31. /// 设备Ip通讯检测结构
  32. /// </summary>
  33. public class DeviceIpTestResults
  34. {
  35. public string Ip { get; set; }
  36. public bool Result { get; set; }
  37. }
  38. /// <summary>
  39. /// WCS相关接口控制器
  40. /// </summary>
  41. [ApiController]
  42. [Route("api/[controller]/[action]")]
  43. public class WcsController : ControllerBase
  44. {
  45. /// <summary>
  46. /// 获取设备配置信息接口
  47. /// </summary>
  48. /// <returns></returns>
  49. [HttpGet]
  50. public List<Device> GetDeviceList()
  51. {
  52. return Device.All.ToList();
  53. }
  54. /// <summary>
  55. /// 获取设备运行状态
  56. /// </summary>
  57. /// <param name="req"></param>
  58. /// <returns></returns>
  59. [HttpPost]
  60. public List<RunInfo> GetDevRunInfo([FromBody] DevRunInfoViewMode req)
  61. {
  62. var runInfos = new List<RunInfo>();
  63. var db = new SqlSugarHelper().Default;
  64. var plcEx = new SqlSugarHelper().PLCEX;
  65. var type = "";
  66. switch (req.Type)
  67. {
  68. case DevType.Robot: //机械臂
  69. type = DevType.Robot.ToString();
  70. //获取时段内设备的运行状态
  71. var runInfoList = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type && x.Frame >= req.StateTime && x.Frame < req.EndTime).ToList().GroupBy(x => x.Code);
  72. foreach (var runInfo in runInfoList)
  73. {
  74. var info = new RunInfo()
  75. {
  76. Code = runInfo.Key,
  77. EnterDepot = db.Queryable<WCS_TaskOld>().With(SqlWith.NoLock)
  78. .Where(x => x.Status == TaskStatus.Finish && x.Type == TaskType.SetPlate &&
  79. x.Device == runInfo.Key && x.EndTime >= req.StateTime &&
  80. x.EndTime < req.EndTime)
  81. .SplitTable(x => x.Take(2))
  82. .Count(),
  83. OutDepot = db.Queryable<WCS_TaskOld>().With(SqlWith.NoLock)
  84. .Where(x => x.Status == TaskStatus.Finish && x.Type == TaskType.OutDepot &&
  85. x.Device == runInfo.Key && x.EndTime >= req.StateTime &&
  86. x.EndTime < req.EndTime)
  87. .SplitTable(x => x.Take(2))
  88. .Count(),
  89. Free = runInfo.Where(x =>
  90. x.RunMode == RobotMode.Automatic.GetDescription() &&
  91. x.RunStatus == RobotRunStatus.Idle.GetDescription()).Sum(x => x.Duration) / 1000 / 60,
  92. Alarm = runInfo.Where(x => x.RunMode == RobotMode.Alarm.GetDescription())
  93. .Sum(x => x.Duration) / 1000 / 60,
  94. Manual = runInfo.Where(x => x.RunMode == RobotMode.Manua.GetDescription())
  95. .Sum(x => x.Duration) / 1000 / 60,
  96. Automatic = runInfo.Where(x => x.RunMode == RobotMode.Automatic.GetDescription()
  97. && x.RunStatus != RobotRunStatus.Idle.GetDescription()
  98. && x.RunStatus != RobotRunStatus.Maintain.GetDescription())
  99. .Sum(x => x.Duration) / 1000 / 60,
  100. };
  101. #region 开始分析设备动作,不计算停止时间
  102. var devActions = new List<DevActionViewMode>();
  103. double totalTime = 0; //总耗时
  104. double totalCount = 0; //总次数
  105. //入库
  106. var infos = runInfo.Where(x => x.RunMode == RobotMode.Automatic.GetDescription()).OrderBy(x => x.Frame).ToList();
  107. totalTime = infos.Where(x => x.RunStatus == RobotRunStatus.InboundCrawling.GetDescription() || x.RunStatus == RobotRunStatus.InStorage.GetDescription()).Sum(x => x.Duration);
  108. totalCount = infos.Count(x => x.RunStatus == RobotRunStatus.InboundCrawling.GetDescription());
  109. devActions.Add(new DevActionViewMode()
  110. {
  111. Type = DevActionType.In.GetDescription(),
  112. ActionAmount = totalCount,
  113. ActionTime = totalTime == 0 ? 0 : Math.Round(totalTime / totalCount, 2),
  114. });
  115. //出库
  116. infos = runInfo.Where(x => x.RunMode == RobotMode.Automatic.GetDescription()).ToList();
  117. totalTime = infos.Where(x => x.RunStatus == RobotRunStatus.OutBoundCrawling.GetDescription() || x.RunStatus == RobotRunStatus.OutStorage.GetDescription()).Sum(x => x.Duration);
  118. totalCount = infos.Count(x => x.RunStatus == RobotRunStatus.OutBoundCrawling.GetDescription());
  119. devActions.Add(new DevActionViewMode()
  120. {
  121. Type = DevActionType.Out.GetDescription(),
  122. ActionAmount = totalCount,
  123. ActionTime = totalTime == 0 ? 0 : Math.Round(totalTime / totalCount, 2),
  124. });
  125. info.DevAction = devActions;
  126. #endregion 开始分析设备动作,不计算停止时间
  127. #region 计算任务的工位使用数量
  128. var stationCounts = new List<StationCount>();
  129. type = DevType.RobotTaskSum.ToString();
  130. var taskSum = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == runInfo.Key && x.Type == type && x.Frame >= req.StateTime && x.Frame < req.EndTime)
  131. .ToList().Select(x =>
  132. {
  133. var item = x;
  134. item.Duration = long.Parse(item.RunStatus.Split("--")[2]);
  135. return item;
  136. }).ToList();
  137. //入库
  138. stationCounts.Add(new StationCount()
  139. {
  140. Type = DevActionType.In.GetDescription(),
  141. StationNum = taskSum.Count(x => x is { Duration: 3, RunMode: "1" }),
  142. StationIndex = 1
  143. });
  144. stationCounts.Add(new StationCount()
  145. {
  146. Type = DevActionType.In.GetDescription(),
  147. StationNum = taskSum.Count(x => x is { Duration: 3, RunMode: "2" }),
  148. StationIndex = 2
  149. });
  150. //出库
  151. stationCounts.Add(new StationCount()
  152. {
  153. Type = DevActionType.Out.GetDescription(),
  154. StationNum = taskSum.Count(x => x is { Duration: 4, RunMode: "1" }),
  155. StationIndex = 1
  156. });
  157. stationCounts.Add(new StationCount()
  158. {
  159. Type = DevActionType.Out.GetDescription(),
  160. StationNum = taskSum.Count(x => x is { Duration: 4, RunMode: "2" }),
  161. StationIndex = 2
  162. });
  163. info.StationCount = stationCounts;
  164. #endregion 计算任务的工位使用数量
  165. runInfos.Add(info);
  166. }
  167. break;
  168. case DevType.Truss:
  169. type = DevType.Truss.ToString();
  170. //获取时段内设备的运行状态
  171. var trussInfoList = plcEx.Queryable<DevRunInfo>().Where(x => x.Type == type && x.Frame >= req.StateTime && x.Frame < req.EndTime).ToList().GroupBy(x => x.Code);
  172. foreach (var runInfo in trussInfoList)
  173. {
  174. var info = new RunInfo()
  175. {
  176. Code = runInfo.Key,
  177. EnterDepot = db.Queryable<WCS_TaskOld>().With(SqlWith.NoLock)
  178. .Where(x => x.Status == TaskStatus.Finish && x.Type == TaskType.SetPlate &&
  179. x.Device == runInfo.Key && x.EndTime >= req.StateTime &&
  180. x.EndTime < req.EndTime)
  181. .SplitTable(x => x.Take(2))
  182. .Count(),
  183. Free = runInfo.Where(x => x.RunMode == TrussStatus.Idle.GetDescription()).Sum(x => x.Duration) / 1000 / 60,
  184. Alarm = runInfo.Where(x => x.RunMode == TrussStatus.Alarm.GetDescription()).Sum(x => x.Duration) / 1000 / 60,
  185. Manual = runInfo.Where(x => x.RunMode == TrussStatus.Manual.GetDescription() || x.RunMode == TrussStatus.KeepInRepair.GetDescription()).Sum(x => x.Duration) / 1000 / 60,
  186. Automatic = runInfo.Where(x => x.RunMode == TrussStatus.Execute.GetDescription()).Sum(x => x.Duration) / 1000 / 60,
  187. };
  188. #region 开始分析设备动作,不计算停止时间
  189. var devActions = new List<DevActionViewMode>();
  190. double totalTime = 0; //总耗时
  191. double totalCount = 0; //总次数
  192. //入库
  193. var infos = runInfo.Where(x => x.RunMode == TrussStatus.Execute.GetDescription()).ToList();
  194. totalTime = infos.Where(x => x.RunMode == TrussStatus.Execute.GetDescription()).Sum(x => x.Duration);
  195. totalCount = infos.Count(x => x.RunMode == TrussStatus.Execute.GetDescription());
  196. devActions.Add(new DevActionViewMode()
  197. {
  198. Type = DevActionType.In.GetDescription(),
  199. ActionAmount = totalCount,
  200. ActionTime = totalTime == 0 ? 0 : Math.Round(totalTime / totalCount, 2),
  201. });
  202. info.DevAction = devActions;
  203. #endregion 开始分析设备动作,不计算停止时间
  204. #region 计算任务的工位使用数量
  205. var stationCounts = new List<StationCount>();
  206. type = DevType.TrussTaskSum.ToString();
  207. var taskSum = plcEx.Queryable<DevRunInfo>().Where(x => x.Code == runInfo.Key && x.Type == type && x.Frame >= req.StateTime && x.Frame < req.EndTime)
  208. .ToList();
  209. //入库
  210. stationCounts.Add(new StationCount()
  211. {
  212. Type = DevActionType.In.GetDescription(),
  213. StationNum = taskSum.Count(x => x is { RunMode: "1" }),
  214. StationIndex = 1
  215. });
  216. stationCounts.Add(new StationCount()
  217. {
  218. Type = DevActionType.In.GetDescription(),
  219. StationNum = taskSum.Count(x => x is { RunMode: "2" }),
  220. StationIndex = 2
  221. });
  222. stationCounts.Add(new StationCount()
  223. {
  224. Type = DevActionType.In.GetDescription(),
  225. StationNum = taskSum.Count(x => x is { RunMode: "3" }),
  226. StationIndex = 3
  227. });
  228. stationCounts.Add(new StationCount()
  229. {
  230. Type = DevActionType.In.GetDescription(),
  231. StationNum = taskSum.Count(x => x is { RunMode: "4" }),
  232. StationIndex = 4
  233. });
  234. stationCounts.Add(new StationCount()
  235. {
  236. Type = DevActionType.In.GetDescription(),
  237. StationNum = taskSum.Count(x => x is { RunMode: "5" }),
  238. StationIndex = 5
  239. });
  240. stationCounts.Add(new StationCount()
  241. {
  242. Type = DevActionType.In.GetDescription(),
  243. StationNum = taskSum.Count(x => x is { RunMode: "6" }),
  244. StationIndex = 6
  245. });
  246. stationCounts.Add(new StationCount()
  247. {
  248. Type = DevActionType.In.GetDescription(),
  249. StationNum = taskSum.Count(x => x is { RunMode: "7" }),
  250. StationIndex = 7
  251. });
  252. stationCounts.Add(new StationCount()
  253. {
  254. Type = DevActionType.In.GetDescription(),
  255. StationNum = taskSum.Count(x => x is { RunMode: "8" }),
  256. StationIndex = 8
  257. });
  258. stationCounts.Add(new StationCount()
  259. {
  260. Type = DevActionType.In.GetDescription(),
  261. StationNum = taskSum.Count(x => x is { RunMode: "9" }),
  262. StationIndex = 9
  263. });
  264. stationCounts.Add(new StationCount()
  265. {
  266. Type = DevActionType.In.GetDescription(),
  267. StationNum = taskSum.Count(x => x is { RunMode: "10" }),
  268. StationIndex = 10
  269. });
  270. info.StationCount = stationCounts;
  271. #endregion 计算任务的工位使用数量
  272. runInfos.Add(info);
  273. }
  274. break;
  275. }
  276. return runInfos;
  277. }
  278. #region 设备IP相关
  279. /// <summary>
  280. /// 检查Ip是否正常联通
  281. /// </summary>
  282. /// <param name="strIpOrDName">输入参数,表示IP地址或域名</param>
  283. /// <returns></returns>
  284. [HttpGet]
  285. public static bool PingIpOrDomainName(string strIpOrDName)
  286. {
  287. try
  288. {
  289. var objPingSender = new Ping();
  290. var objPinOptions = new PingOptions
  291. {
  292. DontFragment = true
  293. };
  294. const string data = "";
  295. var buffer = Encoding.UTF8.GetBytes(data);
  296. const int intTimeout = 120;
  297. var objPinReply = objPingSender.Send(strIpOrDName, intTimeout, buffer, objPinOptions);
  298. var strInfo = objPinReply.Status.ToString();
  299. return strInfo == "Success";
  300. }
  301. catch (Exception)
  302. {
  303. return false;
  304. }
  305. }
  306. /// <summary>
  307. /// 获取设备IP检测结果
  308. /// </summary>
  309. /// <returns>设备IP检测结果</returns>
  310. [HttpGet]
  311. public List<DeviceIpTestResults> DeviceIpTest()
  312. {
  313. if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
  314. var deviceIpTestResults = new List<DeviceIpTestResults>();
  315. ServiceHub.DeviceIPList.ForEach(ip =>
  316. {
  317. deviceIpTestResults.Add(new DeviceIpTestResults
  318. {
  319. Ip = ip,
  320. Result = PingIpOrDomainName(ip)
  321. });
  322. });
  323. return deviceIpTestResults;
  324. }
  325. /// <summary>
  326. /// 获取设备Ip集合
  327. /// </summary>
  328. /// <returns>设备Ip集合</returns>
  329. [HttpGet]
  330. public List<string> GetDeviceIpList()
  331. {
  332. if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
  333. return ServiceHub.DeviceIPList;
  334. }
  335. #endregion 设备IP相关
  336. }
  337. /// <summary>
  338. /// 设备运行状态
  339. /// </summary>
  340. public class DevRunInfoViewMode
  341. {
  342. /// <summary>
  343. /// 类型
  344. /// </summary>
  345. public DevType Type { get; set; }
  346. /// <summary>
  347. /// 开始时间
  348. /// </summary>
  349. public DateTime StateTime { get; set; }
  350. /// <summary>
  351. /// 结束时间
  352. /// </summary>
  353. public DateTime EndTime { get; set; }
  354. }
  355. /// <summary>
  356. /// 分页参数
  357. /// </summary>
  358. public class PagedInfo<T>
  359. {
  360. /// <summary>
  361. /// 每页行数
  362. /// </summary>
  363. public int PageSize { get; set; } = 10;
  364. /// <summary>
  365. /// 当前页
  366. /// </summary>
  367. public int PageIndex { get; set; } = 1;
  368. /// <summary>
  369. /// 总记录数
  370. /// </summary>
  371. public int TotalNum { get; set; }
  372. /// <summary>
  373. /// 总页数
  374. /// </summary>
  375. public int TotalPage
  376. {
  377. get
  378. {
  379. if (TotalNum > 0)
  380. {
  381. return TotalNum % this.PageSize == 0 ? TotalNum / this.PageSize : TotalNum / this.PageSize + 1;
  382. }
  383. else
  384. {
  385. return 0;
  386. }
  387. }
  388. set { }
  389. }
  390. public List<T> Result { get; set; }
  391. public Dictionary<string, object> Extra { get; set; } = new Dictionary<string, object>();
  392. public PagedInfo()
  393. {
  394. }
  395. }
  396. public class RunInfo
  397. {
  398. public string Code { get; set; }
  399. /// <summary>
  400. /// 出库任务
  401. /// </summary>
  402. public int OutDepot { get; set; }
  403. /// <summary>
  404. /// 入库任务
  405. /// </summary>
  406. public int EnterDepot { get; set; }
  407. /// <summary>
  408. /// 移库任务
  409. /// </summary>
  410. public int MoveDepot { get; set; }
  411. /// <summary>
  412. /// 空闲
  413. /// </summary>
  414. public double Free { get; set; }
  415. /// <summary>
  416. /// 手动
  417. /// </summary>
  418. public double Manual { get; set; }
  419. /// <summary>
  420. /// 自动
  421. /// </summary>
  422. public double Automatic { get; set; }
  423. /// <summary>
  424. /// 报警
  425. /// </summary>
  426. public double Alarm { get; set; }
  427. /// <summary>
  428. /// 运行
  429. /// </summary>
  430. public double Working { get; set; }
  431. /// <summary>
  432. /// 交互总耗时
  433. /// </summary>
  434. public double InteractTotal { get; set; }
  435. /// <summary>
  436. /// 设备执行分析
  437. /// </summary>
  438. public List<DevActionViewMode> DevAction { get; set; }
  439. /// <summary>
  440. /// 任务执行工位使用数量
  441. /// </summary>
  442. public List<StationCount> StationCount { get; set; }
  443. }
  444. /// <summary>
  445. /// 设备动作分析
  446. /// </summary>
  447. public class DevActionViewMode
  448. {
  449. /// <summary>
  450. /// 动作次数
  451. /// </summary>
  452. public double ActionAmount { get; set; }
  453. /// <summary>
  454. /// 动作平均耗时
  455. /// </summary>
  456. public double ActionTime { get; set; }
  457. /// <summary>
  458. /// 动作类型
  459. /// </summary>
  460. public string Type { get; set; }
  461. }
  462. /// <summary>
  463. /// 设备动作类型
  464. /// </summary>
  465. public enum DevActionType
  466. {
  467. /// <summary>
  468. /// 入库
  469. /// </summary>
  470. [Description("入库")]
  471. In = 0,
  472. /// <summary>
  473. /// 出库
  474. /// </summary>
  475. [Description("出库")]
  476. Out = 1,
  477. /// <summary>
  478. /// 移库
  479. /// </summary>
  480. [Description("移库")]
  481. Move = 2,
  482. }
  483. /// <summary>
  484. /// 任务执行工位数量
  485. /// </summary>
  486. public class StationCount
  487. {
  488. /// <summary>
  489. /// 执行数量
  490. /// </summary>
  491. public double StationNum { get; set; }
  492. /// <summary>
  493. /// 工位数
  494. /// </summary>
  495. public double StationIndex { get; set; }
  496. /// <summary>
  497. /// 任务类型
  498. /// </summary>
  499. public string Type { get; set; }
  500. }
  501. }