DeviceExtension.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using WCS.Core;
  5. using WCS.Entity;
  6. using WCS.Entity.Protocol;
  7. using WCS.Service.Helpers;
  8. namespace WCS.Service.Extensions
  9. {
  10. /// <summary>
  11. /// 输送机设备组
  12. /// </summary>
  13. public class StationDeviceGroup : DeviceGroup<IStation520, IStation521, IStation523>
  14. {
  15. private List<RGVDevice> RGVs;
  16. public StationDeviceGroup(WCS_DEVICE entity) : base(entity)
  17. {
  18. }
  19. /// <summary>
  20. /// 设备组是否满足任务执行条件
  21. /// </summary>
  22. /// <param name="type">给当前设备组下发任务时需要的请求</param>
  23. /// <returns>true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 </returns>
  24. /// <exception cref="Exception"></exception>
  25. public bool WhetherToExecute(IstationRequest type = IstationRequest.无)
  26. {
  27. //当前组有一个运行的设备就停止执行
  28. if (Items.Any(v => v.Data3.Status.HasFlag(StationStatus.运行状态位))) return true;
  29. //设备组中没有设备有光带信息
  30. if (!Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态))) return true;
  31. ////有光电无任务
  32. //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000))
  33. // throw new Exception(LogHelper.SpliceLogMessage("有光电无任务", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
  34. ////有光电有任务无请求
  35. //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000 && (type != IstationRequest.无 && v.Data2.Request != type)))
  36. // throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type} 请求", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
  37. return false;
  38. }
  39. /// <summary>
  40. /// 获取设备组中需要取货的设备
  41. /// </summary>
  42. /// <param name="obj"></param>
  43. /// <returns></returns>
  44. public List<Device<IStation520, IStation521, IStation523>> RGVGetTaskedDevice()
  45. {
  46. var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
  47. .Where(v => v.Entity.CODE.ToShort() != v.Data2.Goodsend && v.Data2.Goodsend != 0)
  48. .ToList();
  49. return a.Count == 0 ? null : a;
  50. }
  51. /// <summary>
  52. /// 获取设备组中需要分配目标地址的设备
  53. /// </summary>
  54. /// <param name="obj"></param>
  55. /// <returns></returns>
  56. public List<Device<IStation520, IStation521, IStation523>> TaskedDeviceGetNextAddress()
  57. {
  58. var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
  59. .Where(v => v.Data2.Goodsend.ToString() == v.Entity.CODE && v.Data2.Goodsend != 0)
  60. .ToList();
  61. return a.Count == 0 ? null : a;
  62. }
  63. public float Position { get; }
  64. public float Length { get; }
  65. public RGVDevice NextRGV()
  66. {
  67. return new RGVDevice(new WCS_DEVICE());
  68. }
  69. public float Distance(RGVDevice rgv)
  70. {
  71. return Math.Abs((Position - rgv.Position + Length) % Length);
  72. }
  73. public RGVDevice CurrentRGV()
  74. {
  75. return new RGVDevice(new WCS_DEVICE());
  76. }
  77. /// <summary>
  78. ///
  79. /// </summary>
  80. /// <returns></returns>
  81. public bool NeedRgv()
  82. {
  83. return true;
  84. }
  85. }
  86. /// <summary>
  87. /// 输送机设备
  88. /// </summary>
  89. public class StationDevice : Device<IStation520, IStation521, IStation523>
  90. {
  91. public StationDevice(WCS_DEVICE entity) : base(entity)
  92. {
  93. }
  94. /// <summary>
  95. /// 设备组是否满足任务执行条件
  96. /// </summary>
  97. /// <param name="type">给当前设备组下发任务时需要的请求</param>
  98. /// <returns>true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 </returns>
  99. /// <exception cref="Exception"></exception>
  100. public bool WhetherToExecute(IstationRequest type = IstationRequest.无)
  101. {
  102. //正在运行
  103. if (Data3.Status.HasFlag(StationStatus.运行状态位)) return true;
  104. //上一次的任务还未执行
  105. if (Data.VoucherNo != Data2.VoucherNo)
  106. throw new Exception(LogHelper.SpliceLogMessage($"等待任务[{Data2.Tasknum}]执行", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
  107. //没有光电
  108. if (!Data2.Status.HasFlag(IstationStatus.光电状态)) return true;
  109. //没有任务号
  110. switch (type)
  111. {
  112. case IstationRequest.无:
  113. if (Data2.Tasknum > 10000)
  114. throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
  115. break;
  116. case IstationRequest.扫码入库:
  117. if (Data2.Tasknum > 10000)
  118. throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
  119. break;
  120. case IstationRequest.堆垛机放货完成请求目标地址:
  121. if (Data2.Tasknum < 10000)
  122. throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
  123. break;
  124. case IstationRequest.请求分配目标地址:
  125. if (Data2.Tasknum < 10000)
  126. throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
  127. break;
  128. }
  129. //没有请求
  130. if (type != IstationRequest.无 && Data2.Request != type)
  131. throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type}", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
  132. return false;
  133. }
  134. }
  135. /// <summary>
  136. /// RGV设备
  137. /// </summary>
  138. public class RGVDevice : Device<IRGV520, IRGV521, IRGV523>
  139. {
  140. //需要记录每一个站台的位置
  141. /// <summary>
  142. /// 涂布环穿 位置配置
  143. /// </summary>
  144. private static List<RGVStationLocation> Coating = new List<RGVStationLocation>();
  145. /// <summary>
  146. /// 拉膜环穿 位置配置
  147. /// </summary>
  148. private static List<RGVStationLocation> PullFilm = new List<RGVStationLocation>();
  149. public float Position
  150. {
  151. get
  152. {
  153. return Data2.Position;
  154. }
  155. }
  156. private static List<RGVDevice> AllRGVList
  157. {
  158. get; set;
  159. }
  160. static RGVDevice()
  161. {
  162. AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create<RGVDevice>()).ToList();
  163. }
  164. public float Length { get; }
  165. public List<RGVDevice> RGVList
  166. {
  167. get
  168. {
  169. return AllRGVList.Where(v => v.Entity.PROTOCOLS.Any(d => Entity.PROTOCOLS.Any(e => e.DB.ID == d.DB.ID)))
  170. .Where(v => v.Entity.CODE != Entity.CODE).ToList();
  171. }
  172. }
  173. public RGVDevice(WCS_DEVICE entity) : base(entity)
  174. {
  175. }
  176. /// <summary>
  177. /// 前一个RGV
  178. /// </summary>
  179. /// <returns></returns>
  180. public RGVDevice Before()
  181. {
  182. var arr = AllRGVList.OrderBy(v => v.Position);
  183. var rgv = arr.FirstOrDefault(v => v.Position > Position);
  184. if (rgv == null)
  185. rgv = arr.LastOrDefault(v => v.Position < Position);
  186. return rgv;
  187. }
  188. /// <summary>
  189. /// 后一个RGV
  190. /// </summary>
  191. /// <returns></returns>
  192. public RGVDevice After()
  193. {
  194. return new RGVDevice(new WCS_DEVICE());
  195. }
  196. /// <summary>
  197. /// 两个RGV之间的距离
  198. /// </summary>
  199. /// <param name="after"></param>
  200. /// <returns></returns>
  201. public float Distance(RGVDevice after)
  202. {
  203. return Math.Abs((Position - after.Position + Length) % Length);
  204. }
  205. /// <summary>
  206. /// 是否可用
  207. /// </summary>
  208. /// <returns></returns>
  209. public bool Valid()
  210. {
  211. return true;
  212. }
  213. /// <summary>
  214. /// 移动
  215. /// </summary>
  216. /// <param name="addr"></param>
  217. public void Move(StationDeviceGroup addr)
  218. {
  219. }
  220. /// <summary>
  221. /// 选择出库
  222. /// </summary>
  223. /// <param name="addr"></param>
  224. public void Pick(StationDeviceGroup addr)
  225. {
  226. }
  227. public void Put()
  228. {
  229. }
  230. public RGVDevice[] RgvAfter(float distance)
  231. {
  232. return AllRGVList.Where(v => Distance(v) < distance).ToArray();
  233. }
  234. public bool StopedByMe(RGVDevice rgv)
  235. {
  236. var target = rgv.Data2.DestPosition_1;
  237. var station = Device.Find($"G{target}").Create<StationDeviceGroup>();
  238. return station.Distance(this) < station.Distance(rgv);
  239. }
  240. public StationDeviceGroup NextStation()
  241. {
  242. return new StationDeviceGroup(new WCS_DEVICE());
  243. }
  244. }
  245. /// <summary>
  246. /// 堆垛机设备
  247. /// </summary>
  248. public class SRMDevice : Device<ISRM520, ISRM521, ISRM537>
  249. {
  250. public SRMDevice(WCS_DEVICE entity) : base(entity)
  251. {
  252. }
  253. /// <summary>
  254. /// 获取放货点
  255. /// </summary>
  256. public List<StationDevice> GetDeliveryPoint()
  257. {
  258. return Entity.ROUTES.Select(v => v.NEXT) //巷道
  259. .SelectMany(v => v.ROUTES.Select(d => d.NEXT)) //放货点
  260. .Where(v => v.IsConv()) //必须是输送线
  261. .Select(v => new StationDevice(v)).ToList();
  262. }
  263. }
  264. public class RGVStationLocation
  265. {
  266. public RGVStationLocation(string station, string stationLocation, string startingPoint, string endPoint)
  267. {
  268. Station = station;
  269. StationLocation = stationLocation;
  270. StartingPoint = startingPoint;
  271. EndPoint = endPoint;
  272. }
  273. /// <summary>
  274. /// 输送机设备组编号
  275. /// </summary>
  276. public string Station { get; set; }
  277. /// <summary>
  278. /// 输送机在环轨中的位置
  279. /// </summary>
  280. public string StationLocation { get; set; }
  281. /// <summary>
  282. /// RGV起始
  283. /// </summary>
  284. public string StartingPoint { get; set; }
  285. /// <summary>
  286. /// RGV结束
  287. /// </summary>
  288. public string EndPoint { get; set; }
  289. }
  290. }