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