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