终端一体化运控平台
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

455 lines
16 KiB

  1. using BPA.Message;
  2. using BPA.Message.Enum;
  3. using BPASmartClient.Device;
  4. using BPA.Helper;
  5. using BPASmartClient.Model;
  6. using BPASmartClient.Model.PLC;
  7. using BPASmartClient.MorkTM;
  8. using BPASmartClient.MorkTM.Model;
  9. using System.Collections.Concurrent;
  10. using static BPA.Helper.EventBus;
  11. namespace BPASmartClient.MorkTM
  12. {
  13. public class Control_MorkTM : BaseDevice
  14. {
  15. public override global::BPA.Message.Enum.DeviceClientType DeviceType { get { return BPA.Message.Enum.DeviceClientType.TMC_MT; } }
  16. GVL_MorkTM morkTM = new GVL_MorkTM();
  17. PolymerBatching polymer = new PolymerBatching();
  18. //浮点数放大倍数
  19. const int expand = 100;
  20. public override void DoMain()
  21. {
  22. ServerInit();
  23. DataParse();
  24. polymer.GetMaterialInfo();
  25. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  26. {
  27. if(o.Length > 0)
  28. {
  29. Dictionary<int, float> res = new Dictionary<int, float>();
  30. res.Add(Convert.ToInt32(o[0]), Convert.ToSingle(o[1]));
  31. SetMatertialWeight(res);
  32. Thread.Sleep(100);
  33. OpenUsePassageWay(Convert.ToInt32(o[0]));
  34. }
  35. }), "通道口出料");
  36. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  37. {
  38. if(o.Length > 0)
  39. {
  40. PosionTurnOnTest(Convert.ToInt32(o[0]));
  41. }
  42. }), "转盘转动");
  43. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  44. {
  45. if (o.Length > 0)
  46. {
  47. OpenPassway(Convert.ToInt32(o[0]));
  48. }
  49. }), "开启通道");
  50. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  51. {
  52. if (o.Length > 0)
  53. {
  54. CheckPassway(Convert.ToInt32(o[0]), Convert.ToInt32(o[1]));
  55. }
  56. }), "开始矫正");
  57. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  58. {
  59. if (o.Length > 0)
  60. {
  61. CheckMaterailWeight(Convert.ToInt32(o[0]), Convert.ToInt32(o[1]));
  62. }
  63. }), "矫正重量");
  64. ActionManage.GetInstance.Register(new Action<object>((o) =>
  65. {
  66. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  67. }), "WriteVW");
  68. ActionManage.GetInstance.Register(new Action<object>((o) =>
  69. {
  70. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  71. }), "WriteBools");
  72. morkTM.ReachPosions = new List<bool>() { morkTM.ReachPosion_1, morkTM.ReachPosion_2, morkTM.ReachPosion_3, morkTM.ReachPosion_4, morkTM.ReachPosion_5, morkTM.ReachPosion_6 , morkTM.ReachOutPosion_0, };
  73. DeviceProcessLogShow("设备初始化完成");
  74. }
  75. private void ServerInit()
  76. {
  77. //物料信息
  78. EventBus.GetInstance().Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  79. {
  80. if (@event == null) return;
  81. if (@event is MaterialDeliveryEvent material)
  82. {
  83. orderMaterialDelivery = material.orderMaterialDelivery;
  84. }
  85. });
  86. //配方数据信息
  87. EventBus.GetInstance().Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  88. {
  89. if (@event == null) return;
  90. if (@event is RecipeBomEvent recipe)
  91. {
  92. recipeBoms = recipe.recipeBoms;
  93. }
  94. });
  95. }
  96. private void DataParse()
  97. {
  98. EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  99. {
  100. if(@event == null) return;
  101. if(@event is DoOrderEvent order)
  102. {
  103. if (order.MorkOrder.GoodBatchings == null) return;
  104. OrderCount++;
  105. morkTM.doOrderEvents.Add(order);
  106. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  107. DeviceProcessLogShow($"接收到{OrderCount}次订单");
  108. Dictionary<int, float> OrderPushes = new Dictionary<int, float>();
  109. foreach (var item in order.MorkOrder.GoodBatchings)
  110. {
  111. var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  112. if (res != null)
  113. {
  114. OrderPushes.TryAdd(int.Parse(res.BatchingLoc), item.BatchingCount);
  115. }
  116. }
  117. morkTM.morkOrderPushesTeaWithMilk.Enqueue(new OrderLocInfo()
  118. {
  119. GoodName = order.MorkOrder.GoodsName,
  120. SuborderId = order.MorkOrder.SuborderId,
  121. GoodPushes = OrderPushes
  122. });
  123. }
  124. });
  125. }
  126. private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
  127. {
  128. var res = morkTM.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  129. string goodName = string.Empty;
  130. string SortNum = string.Empty;
  131. EventBus.GetInstance().Publish(new OrderStatusChangedEvent()
  132. {
  133. SortNum = res.MorkOrder. SortNum.ToString(),
  134. GoodName = res.MorkOrder.GoodsName,
  135. Status = oRDER_STATUS,
  136. SubOrderId = res.MorkOrder.SuborderId,
  137. deviceClientType = DeviceType
  138. });
  139. if(oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK) morkTM.doOrderEvents.Remove(res);
  140. }
  141. public override void MainTask()
  142. {
  143. IsHealth = true;
  144. MakeTeaWithMilkProcess();
  145. }
  146. private void MakeTeaWithMilkProcess()
  147. {
  148. if (morkTM.morkOrderPushesTeaWithMilk.Count > 0)
  149. {
  150. if (morkTM.morkOrderPushesTeaWithMilk.TryDequeue(out OrderLocInfo orderLoc)) //&&原点位置是否有杯子)
  151. {
  152. DeviceProcessLogShow($"开始制作奶茶{orderLoc.GoodName}");
  153. morkTM.MakeCount = 0;
  154. SetMatertialWeight(orderLoc.GoodPushes);//设置物料出料量
  155. morkTM.RecipesPushes.Clear();
  156. morkTM.RecipesPushes = orderLoc.GoodPushes;
  157. MakeProcess(orderLoc.GoodName, morkTM.MakeCount, morkTM.RecipesPushes.Count);//制作进度
  158. OrderChange(orderLoc.SuborderId, ORDER_STATUS.COOKING);
  159. foreach (var item in morkTM.RecipesPushes)
  160. {
  161. morkTM.MakeCount++;
  162. PosionTurnOn(item.Key);//设定转盘位置并等待到位信号
  163. Thread.Sleep(1000);
  164. OpenUsePassageWay(item.Key);//打开通道并等待出料完成
  165. DeviceProcessLogShow($"奶茶{orderLoc.GoodName}:配料{item.Key}:添加量{item.Value}");
  166. MakeProcess(orderLoc.GoodName,morkTM.MakeCount,morkTM.RecipesPushes.Count);
  167. }
  168. TurnOutPosion();
  169. OrderChange(orderLoc.SuborderId, ORDER_STATUS.COMPLETED_COOK);
  170. MakeProcess(orderLoc.GoodName, 1, 1);
  171. DeviceProcessLogShow($"奶茶{orderLoc.GoodName}制作完成");
  172. }
  173. }
  174. }
  175. /// <summary>
  176. /// 打开出料通道
  177. /// </summary>
  178. private void OpenUsePassageWay(int pos)
  179. {
  180. string address = "";
  181. foreach (var item in polymer.OutPosionPLCs)//根据位置筛选物料plc点位
  182. {
  183. if(item.posion is MaterialPosion posion)
  184. {
  185. if(posion == (MaterialPosion)pos)
  186. {
  187. WriteData(item.SetPLCPosion,true);
  188. address = item.GetPLCPosion;
  189. return;
  190. }
  191. }
  192. }
  193. while(!morkTM.outMaterialCompletes[pos]) //等待出料完成
  194. {
  195. Thread.Sleep(1000);
  196. }
  197. WriteData(address, false);
  198. }
  199. /// <summary>
  200. /// 转盘旋转位置设定
  201. /// </summary>
  202. /// <param name="posion"></param>
  203. private void PosionTurnOn(int posion)
  204. {
  205. int i = 0;
  206. string address = "";
  207. foreach (var item in polymer.GoodsMaterialPosion)
  208. {
  209. if (item.Key.Contains((MaterialPosion)posion))
  210. {
  211. WriteData(item.Value.SetPLCPosion,true);
  212. i = Convert.ToInt32(item.Value.posion);
  213. address = item.Value.GetPLCPosion;
  214. return;
  215. }
  216. }
  217. while(!morkTM.ReachPosions[i-1])//等待转盘到达信号
  218. {
  219. Thread.Sleep(1000);
  220. }
  221. if(address != null) WriteData(address, false);//把信号置为0
  222. }
  223. #region 调试功能
  224. /// <summary>
  225. /// 转盘回原点
  226. /// </summary>
  227. private void TurnOutPosion()
  228. {
  229. WriteData("M4.6", true);
  230. while (!morkTM.ReachPosions[6])
  231. {
  232. Thread.Sleep(1000);
  233. }
  234. WriteData("M14.6", false);
  235. }
  236. /// <summary>
  237. /// 调试转盘
  238. /// </summary>
  239. /// <param name="posion"></param>
  240. private void PosionTurnOnTest(int posion)
  241. {
  242. if(posion==0) TurnOutPosion();
  243. else
  244. {
  245. string address = string.Empty;
  246. int i = 0;
  247. foreach (var item in polymer.TurnPosionPLCs)
  248. {
  249. if ((OutMaterialPosion)item.posion == (OutMaterialPosion)posion)
  250. {
  251. WriteData(item.SetPLCPosion, true);
  252. address = item.GetPLCPosion;
  253. i = Convert.ToInt32(item.posion);
  254. return ;
  255. }
  256. }
  257. while(morkTM.ReachPosions[posion - 1])
  258. {
  259. Thread.Sleep(1000);
  260. }
  261. WriteData(address,false);
  262. DeviceProcessLogShow($"转盘转动到位置{i}");
  263. }
  264. }
  265. /// <summary>
  266. /// 开启通道
  267. /// </summary>
  268. private void OpenPassway(int posion)
  269. {
  270. foreach(var item in polymer.OutPosionPLCs)
  271. {
  272. if((MaterialPosion)item.posion == (MaterialPosion)posion)
  273. {
  274. WriteData(item.SetPLCPosion,true);
  275. return ;
  276. }
  277. }
  278. }
  279. /// <summary>
  280. /// 开始校正
  281. /// </summary>
  282. /// <param name="passway"></param>
  283. /// <param name="time"></param>
  284. private void CheckPassway(int passway,int time)
  285. {
  286. WriteData(polymer.PasswayPosionList[(MaterialPosion)passway], Convert.ToInt32(time * expand));//写入出料时间
  287. Thread.Sleep(100);
  288. WriteData("M5.0", true);//开始校正
  289. }
  290. /// <summary>
  291. /// 确认校正重量
  292. /// </summary>
  293. private void CheckMaterailWeight(int passway,float weight)
  294. {
  295. WriteData(polymer.PasswayPosionList[(MaterialPosion)passway], weight*expand);
  296. }
  297. /// <summary>
  298. /// 奶茶制作进度
  299. /// </summary>
  300. private void MakeProcess(string goodName,int percent,int count)
  301. {
  302. int res = Convert.ToInt32(Math.Floor((double)percent / count)) * 100;
  303. ActionManage.GetInstance.Send("奶茶制作进度",new object[] {goodName, res });
  304. }
  305. #endregion
  306. /// <summary>
  307. /// 把每一个物料的用量写入plc
  308. /// </summary>
  309. /// <param name="materials"></param>
  310. private void SetMatertialWeight(Dictionary<int, float> materials)
  311. {
  312. foreach (var material in materials)
  313. {
  314. int value = Convert.ToInt32(material.Value*expand);
  315. WriteData(polymer.MaterialPosionList[(MaterialPosion)material.Key], value);
  316. DeviceProcessLogShow($"通道{material.Key}预设料{material.Value}g");
  317. Thread.Sleep(200);
  318. }
  319. }
  320. public override void ReadData()
  321. {
  322. //启用通道的地址1
  323. GetStatus("M0.0", new Action<object>((obj) =>
  324. {
  325. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 28)
  326. {
  327. }
  328. }));
  329. GetStatus("M10.0",new Action<object>((obj) =>
  330. {
  331. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 28)
  332. {
  333. for (int i = 0; i < 28; i++)
  334. {
  335. if (morkTM.outMaterialCompletes.ContainsKey(i+1))
  336. {
  337. morkTM.outMaterialCompletes[i+1] = bools[i];
  338. }
  339. else
  340. {
  341. morkTM.outMaterialCompletes.Add(i+1, bools[i]);
  342. }
  343. }
  344. }
  345. }));
  346. //转盘移动的地址
  347. GetStatus("M4.0", new Action<object>((obj) =>
  348. {
  349. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7)
  350. {
  351. }
  352. }));
  353. //装盘移动到位的地址
  354. GetStatus("M14.0", new Action<object>((obj) =>
  355. {
  356. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7)
  357. {
  358. morkTM.ReachPosion_1 = bools[0];
  359. morkTM.ReachPosion_2 = bools[1];
  360. morkTM.ReachPosion_3 = bools[2];
  361. morkTM.ReachPosion_4 = bools[3];
  362. morkTM.ReachPosion_5 = bools[4];
  363. morkTM.ReachPosion_6 = bools[5];
  364. morkTM.ReachOutPosion_0 = bools[6];
  365. for (int i = 0; i < 7; i++)
  366. {
  367. morkTM.ReachPosions[i] = bools[i];
  368. }
  369. }
  370. }));
  371. }
  372. public override void ResetProgram()
  373. {
  374. morkTM = null;
  375. morkTM = new GVL_MorkTM();
  376. }
  377. private void WriteData(string address, object value)
  378. {
  379. EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  380. }
  381. private void GetStatus(string key, Action<object> action)
  382. {
  383. if (peripheralStatus.ContainsKey(key))
  384. {
  385. if (peripheralStatus[key] != null)
  386. {
  387. action?.Invoke(peripheralStatus[key]);
  388. }
  389. }
  390. }
  391. public override void SimOrder()
  392. {
  393. ActionManage.GetInstance.Register(new Action<object>((o) =>
  394. {
  395. if (o is string goodName)
  396. {
  397. }
  398. }), "");
  399. }
  400. public override void Stop()
  401. {
  402. throw new NotImplementedException();
  403. }
  404. }
  405. }