终端一体化运控平台
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.
 
 
 

487 rivejä
21 KiB

  1. using BPA.Helper;
  2. using BPA.Message.Enum;
  3. using BPA.Models;
  4. using BPASmartClient.Device;
  5. using BPASmartClient.EventBus;
  6. using BPASmartClient.Modbus;
  7. using BPASmartClient.Model;
  8. using BPASmartClient.Model.PLC;
  9. using BPASmartClient.Model.订单;
  10. using BPASmartClient.Model.调酒机;
  11. using BPASmartClient.MorkMW.Model;
  12. using Newtonsoft.Json;
  13. using Org.BouncyCastle.Bcpg.OpenPgp;
  14. using System;
  15. using System.Collections.Concurrent;
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using System.Linq;
  19. using System.Net.Http.Json;
  20. using System.Reflection;
  21. using System.Threading;
  22. using System.Windows.Documents;
  23. using static BPASmartClient.EventBus.EventBus;
  24. namespace BPASmartClient.MorkMW
  25. {
  26. public class Control_MorkMW : BaseDevice
  27. {
  28. int id = 0;
  29. ModbusTcp modbus;
  30. public override DeviceClientType DeviceType => DeviceClientType.MORKMW;
  31. GVL_MorkMW morkMW = new GVL_MorkMW();
  32. public override void DoMain()
  33. {
  34. Json<KeepDataBase>.Read();
  35. VaribleMonitorDis();
  36. ConnectKlpRobot("192.168.0.100", 8001);
  37. ServerInit();
  38. DataParse();
  39. ThreadManage.GetInstance().StartLong(new Action(() => { VariableMonitor(); Thread.Sleep(5); }), "机器人变量状态监控线程", true);
  40. }
  41. private void VaribleMonitorDis()
  42. {
  43. PropertyInfo[] pros = morkMW.GetType().GetProperties();
  44. foreach (var item in pros)
  45. {
  46. var res = item.GetCustomAttribute<VariblesAttribute>();
  47. if (res != null)
  48. {
  49. GVL_MorkMW.varibleInfos.Add(new VaribleModel { Id = id + 1, VaribleName = res.VarName, RobotAddress = res.RobotAddress, ModbusAddress = res.ModbusTcpAddress, Notes = res.Notes });
  50. id++;
  51. }
  52. }
  53. }
  54. private void ServerInit()
  55. {
  56. //配方数据信息
  57. EventBus.EventBus.GetInstance().Subscribe<MorkMWGoodsEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  58. {
  59. if (@event == null) return;
  60. if (@event is MorkMWGoodsEvent recipe)
  61. {
  62. listMorkMWGoods = recipe.morkMWPushMessage?.MorkMWGoods;
  63. DeviceProcessLogShow($"接收到调酒机【{listMorkMWGoods?.Count}】个商品配方数据");
  64. }
  65. });
  66. }
  67. public override void MainTask()
  68. {
  69. if (Json<KeepDataBase>.Data.IsVerify)
  70. IsHealth = modbus.Connected;
  71. else
  72. IsHealth = true;//心跳上报
  73. ToGetWink();
  74. ToMixWink();
  75. ToPourWink();
  76. SignalDetect();
  77. }
  78. /// <summary>
  79. /// 接酒过程
  80. /// </summary>
  81. public void ToGetWink()
  82. {
  83. if (!GVL_MorkMW.AllowLocalSimOrder)
  84. {
  85. if (morkMW.RobotIdle && orderLocInfos.Count > 0 && !morkMW.TaskLock && !morkMW.PourWinkComplete && morkMW.CupSignal && modbus.Connected)
  86. {
  87. DeviceProcessLogShow("订单开始制作");
  88. morkMW.TaskLock = true;
  89. if (orderLocInfos.TryDequeue(out BPASmartClient.MorkMW.Model.OrderLocInfo res))
  90. {
  91. morkMW.CurrentSuborderId = res.SuborderId;
  92. OrderChange(res.SuborderId, ORDER_STATUS.COOKING);
  93. foreach (var item in res.mixWink)
  94. {
  95. switch (item.Loc)
  96. {
  97. // case 7: ToMixWink(); break;
  98. case 1: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  99. case 2: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  100. case 3: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  101. case 4: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  102. case 5: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  103. case 6: ToSpecifiedLocTakeWink(item.Loc, item.Qty); break;
  104. }
  105. switch (item.Loc)
  106. {
  107. //case 7: while (!morkMW.MixWinkComplte) { Thread.Sleep(5); } break;
  108. case 1: while (!morkMW.TakeWinkOneComplete) { Thread.Sleep(5); } break;
  109. case 2: while (!morkMW.TakeWinkTwoComplete) { Thread.Sleep(5); } break;
  110. case 3: while (!morkMW.TakeWinkThreeComplete) { Thread.Sleep(5); } break;
  111. case 4: while (!morkMW.TakeWinkFourComplete) { Thread.Sleep(5); } break;
  112. case 5: while (!morkMW.TakeWinkFiveComplete) { Thread.Sleep(5); } break;
  113. case 6: while (!morkMW.TakeWinkSixComplete) { Thread.Sleep(5); } break;
  114. }
  115. }
  116. morkMW.AllowMixWink = true;//接酒完成,允许调酒
  117. // morkMW.AllowPourWink = true;//调酒完成,允许倒酒
  118. }
  119. }
  120. }
  121. else
  122. {
  123. if (morkMW.RobotIdle && simOrderLocInfos.Count > 0 && !morkMW.TaskLock && !morkMW.PourWinkComplete && morkMW.CupSignal)
  124. {
  125. DeviceProcessLogShow("订单开始制作");
  126. morkMW.TaskLock = true;
  127. if (simOrderLocInfos.TryDequeue(out SimOrderLocInfo res))
  128. {
  129. foreach (var item in res.mixWink)
  130. {
  131. switch (item.Loc)
  132. {
  133. // case 7: ToMixWink(); break;
  134. case 1: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  135. case 2: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  136. case 3: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  137. case 4: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  138. case 5: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  139. case 6: ToSpecifiedLocTakeWink(item.Loc, item.Time); break;
  140. }
  141. switch (item.Loc)
  142. {
  143. //case 7: while (!morkMW.MixWinkComplte) { Thread.Sleep(5); } break;
  144. case 1: while (!morkMW.TakeWinkOneComplete) { Thread.Sleep(5); } break;
  145. case 2: while (!morkMW.TakeWinkTwoComplete) { Thread.Sleep(5); } break;
  146. case 3: while (!morkMW.TakeWinkThreeComplete) { Thread.Sleep(5); } break;
  147. case 4: while (!morkMW.TakeWinkFourComplete) { Thread.Sleep(5); } break;
  148. case 5: while (!morkMW.TakeWinkFiveComplete) { Thread.Sleep(5); } break;
  149. case 6: while (!morkMW.TakeWinkSixComplete) { Thread.Sleep(5); } break;
  150. }
  151. }
  152. DeviceProcessLogShow($"所有位置接酒完成");
  153. morkMW.AllowMixWink = true;//接酒完成,允许调酒
  154. // morkMW.AllowPourWink = true;//调酒完成,允许倒酒
  155. }
  156. }
  157. }
  158. }
  159. /// <summary>
  160. /// 调酒过程
  161. /// </summary>
  162. public void ToMixWink()
  163. {
  164. // modbus.WriteSingleRegister(0000, 7);//机器人调酒
  165. if (morkMW.AllowMixWink && modbus.Connected)
  166. {
  167. DeviceProcessLogShow("开始调酒");
  168. modbus.WriteSingleRegister(0000, 7);//机器人调酒
  169. morkMW.AllowMixWink = false;
  170. }
  171. }
  172. /// <summary>
  173. /// 去对应位置接酒
  174. /// </summary>
  175. /// <param name="loc"></param>
  176. /// <param name="time"></param>
  177. public void ToSpecifiedLocTakeWink(int loc, int time)
  178. {
  179. //发送接酒信号
  180. switch (loc)
  181. {
  182. case 1: modbus.WriteSingleRegister(0000, 1); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  183. case 2: modbus.WriteSingleRegister(0000, 2); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  184. case 3: modbus.WriteSingleRegister(0000, 3); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  185. case 4: modbus.WriteSingleRegister(0000, 4); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  186. case 5: modbus.WriteSingleRegister(0000, 5); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  187. case 6: modbus.WriteSingleRegister(0000, 6); DeviceProcessLogShow($"开始接【{loc}】号位置原酒"); break;
  188. }
  189. //等待机器人到达接酒位置
  190. switch (loc)
  191. {
  192. case 1: while (!morkMW.ArriveWinkOneLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  193. case 2: while (!morkMW.ArriveWinkTwoLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  194. case 3: while (!morkMW.ArriveWinkThreeLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  195. case 4: while (!morkMW.ArriveWinkFourLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  196. case 5: while (!morkMW.ArriveWinkFiveLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  197. case 6: while (!morkMW.ArriveWinkSixLoc) { Thread.Sleep(5); } DeviceProcessLogShow($"机械臂到达【{loc}】号接酒位置"); break;
  198. }
  199. Thread.Sleep(time * 1000);//接酒等待时间
  200. //发送接酒完成信号
  201. switch (loc)
  202. {
  203. case 1: modbus.WriteSingleCoil(4596, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  204. case 2: modbus.WriteSingleCoil(4597, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  205. case 3: modbus.WriteSingleCoil(4598, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  206. case 4: modbus.WriteSingleCoil(4599, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  207. case 5: modbus.WriteSingleCoil(4600, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  208. case 6: modbus.WriteSingleCoil(4601, true); DeviceProcessLogShow($"【{loc}】号位置接酒完成"); break;
  209. }
  210. }
  211. /// <summary>
  212. /// 倒酒过程
  213. /// </summary>
  214. public void ToPourWink()
  215. {
  216. //if (morkMW.AllowPourWink && morkMW.CupSignal)
  217. //{
  218. // morkMW.AllowPourWink = false;
  219. // modbus.WriteSingleRegister(0000, 8);//倒酒
  220. //}
  221. if (morkMW.CupSignal && RTrig.GetInstance("AllowOut").Start(morkMW.MixWinkComplte) && modbus.Connected)
  222. {
  223. DeviceProcessLogShow("开始倒酒");
  224. modbus.WriteSingleRegister(0000, 8);//倒酒
  225. }
  226. }
  227. /// <summary>
  228. /// 信号检测
  229. /// </summary>
  230. public void SignalDetect()
  231. {
  232. if (RTrig.GetInstance("AllComplete").Start(morkMW.ProcessComplete))
  233. {
  234. OrderChange(morkMW.CurrentSuborderId, ORDER_STATUS.COMPLETED_COOK);
  235. morkMW.PourWinkComplete = true;
  236. DeviceProcessLogShow("订单制作完成,请取走调好酒杯");
  237. }
  238. if (morkMW.PourWinkComplete)
  239. {
  240. if (TTrig.GetInstance("PoutWinkCom").Start(morkMW.CupSignal))
  241. {
  242. OrderChange(morkMW.CurrentSuborderId, ORDER_STATUS.COMPLETED_TAKE);
  243. DeviceProcessLogShow("客户取走调好酒杯,请放置空酒杯,以待下次订单制作");
  244. }
  245. if (RTrig.GetInstance("PoutWinkCom").Start(morkMW.CupSignal))
  246. {
  247. DeviceProcessLogShow("空酒杯就位,允许执行下一订单");
  248. morkMW.PourWinkComplete = false;
  249. morkMW.TaskLock = false;
  250. Thread.Sleep(2000);
  251. }
  252. }
  253. }
  254. /// <summary>
  255. /// 读卡乐普机器人状态
  256. /// </summary>
  257. public override void ReadData()
  258. {
  259. //GetStatus("M230.0", new Action<object>((obj) =>
  260. //{
  261. //}));
  262. if (modbus.Connected)
  263. {
  264. morkMW.ArriveWinkOneLoc = modbus.ReadCoils(4616);
  265. morkMW.ArriveWinkTwoLoc = modbus.ReadCoils(4617);
  266. morkMW.ArriveWinkThreeLoc = modbus.ReadCoils(4618);
  267. morkMW.ArriveWinkFourLoc = modbus.ReadCoils(4619);
  268. morkMW.ArriveWinkFiveLoc = modbus.ReadCoils(4620);
  269. morkMW.ArriveWinkSixLoc = modbus.ReadCoils(4621);
  270. morkMW.RobotIdle = modbus.ReadCoils(4201);
  271. morkMW.CupSignal = modbus.ReadInputs(0);
  272. morkMW.TakeWinkOneComplete = modbus.ReadCoils(4606);
  273. morkMW.TakeWinkTwoComplete = modbus.ReadCoils(4607);
  274. morkMW.TakeWinkThreeComplete = modbus.ReadCoils(4608);
  275. morkMW.TakeWinkFourComplete = modbus.ReadCoils(4609);
  276. morkMW.TakeWinkFiveComplete = modbus.ReadCoils(4610);
  277. morkMW.TakeWinkSixComplete = modbus.ReadCoils(4611);
  278. morkMW.MixWinkComplte = modbus.ReadCoils(4612);
  279. morkMW.ProcessComplete = modbus.ReadCoils(4613);
  280. }
  281. else
  282. {
  283. modbus.ModbusTcpConnect("192.168.0.100", 8001);
  284. }
  285. }
  286. public void VariableMonitor()
  287. {
  288. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkOneLoc").CurrentValue = morkMW.ArriveWinkOneLoc;
  289. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkTwoLoc").CurrentValue = morkMW.ArriveWinkTwoLoc;
  290. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkThreeLoc").CurrentValue = morkMW.ArriveWinkThreeLoc;
  291. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkFourLoc").CurrentValue = morkMW.ArriveWinkFourLoc;
  292. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkFiveLoc").CurrentValue = morkMW.ArriveWinkFiveLoc;
  293. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ArriveWinkSixLoc").CurrentValue = morkMW.ArriveWinkSixLoc;
  294. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "RobotIdle").CurrentValue = morkMW.RobotIdle;
  295. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "CupSignal").CurrentValue = morkMW.CupSignal;
  296. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkOneComplete").CurrentValue = morkMW.TakeWinkOneComplete;
  297. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkTwoComplete").CurrentValue = morkMW.TakeWinkTwoComplete;
  298. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkThreeComplete").CurrentValue = morkMW.TakeWinkThreeComplete;
  299. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkFourComplete").CurrentValue = morkMW.TakeWinkFourComplete;
  300. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkFiveComplete").CurrentValue = morkMW.TakeWinkFiveComplete;
  301. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "TakeWinkSixComplete").CurrentValue = morkMW.TakeWinkSixComplete;
  302. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "MixWinkComplte").CurrentValue = morkMW.MixWinkComplte;
  303. GVL_MorkMW.varibleInfos.FirstOrDefault(p => p.VaribleName == "ProcessComplete").CurrentValue = morkMW.ProcessComplete;
  304. }
  305. public override void ResetProgram()
  306. {
  307. morkMW = null;
  308. morkMW = new GVL_MorkMW();
  309. }
  310. public override void SimOrder()
  311. {
  312. EventBus.EventBus.GetInstance().Subscribe<MorkMWSimOrder>(0, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  313. {
  314. if (@event != null && @event is MorkMWSimOrder order)
  315. {
  316. if (order.mixWink.Count > 0)
  317. {
  318. string guid = Guid.NewGuid().ToString();
  319. simOrderLocInfos.Enqueue(new SimOrderLocInfo { mixWink = order.mixWink, SuborderId = guid });
  320. DeviceProcessLogShow("收到模拟订单");
  321. }
  322. }
  323. });
  324. }
  325. public override void Stop()
  326. {
  327. }
  328. private void GetStatus(string key, Action<object> action)
  329. {
  330. if (peripheralStatus.ContainsKey(key))
  331. {
  332. if (peripheralStatus[key] != null)
  333. {
  334. action?.Invoke(peripheralStatus[key]);
  335. }
  336. }
  337. }
  338. /// <summary>
  339. /// 卡乐普写数据
  340. /// </summary>
  341. /// <param name="address"></param>
  342. /// <param name="value"></param>
  343. private void WriteData(string address, object value)
  344. {
  345. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  346. }
  347. /// <summary>
  348. /// 数据解析
  349. /// </summary>
  350. public void DataParse()
  351. {
  352. EventBus.EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  353. {
  354. if (@event != null && @event is DoOrderEvent order)
  355. {
  356. morkMW.doOrderEvents.Add(order);
  357. if (listMorkMWGoods.Count == 0) return;
  358. if (morkMW.historySuborderId.FirstOrDefault(p => p == order.MorkOrder.SuborderId) != null) return;
  359. OrderCount++;
  360. var res = listMorkMWGoods?.FirstOrDefault(p => p.GoodsKey == order.MorkOrder.GoodsKey);
  361. if (res != null)
  362. {
  363. string guid = Guid.NewGuid().ToString();
  364. orderLocInfos.Enqueue(new BPASmartClient.MorkMW.Model.OrderLocInfo { mixWink = res.MorkMWBoms, SuborderId = order.MorkOrder.SuborderId });
  365. morkMW.historySuborderId.Add(order.MorkOrder.SuborderId);
  366. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  367. DeviceProcessLogShow($"收到【{OrderCount}】次小程序订单,当前订单【{order.MorkOrder.GoodsName}】,订单号【{order.MorkOrder.SuborderId}】");
  368. }
  369. else
  370. {
  371. DeviceProcessLogShow($"未找到订单对应商品,订单号【{order.MorkOrder.SuborderId}】");
  372. }
  373. }
  374. });
  375. }
  376. /// <summary>
  377. /// 订单状态上报
  378. /// </summary>
  379. /// <param name="subid"></param>
  380. /// <param name="oRDER_STATUS"></param>
  381. private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
  382. {
  383. try
  384. {
  385. var res = morkMW.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  386. string goodName = string.Empty;
  387. string SortNum = string.Empty;
  388. if (res != null)
  389. {
  390. goodName = res.MorkOrder.GoodsName;
  391. SortNum = res.MorkOrder.SortNum.ToString();
  392. }
  393. EventBus.EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType });
  394. }
  395. catch (Exception)
  396. {
  397. DeviceProcessLogShow($"订单状态上报失败,订单号【{morkMW.CurrentSuborderId}】");
  398. //throw;
  399. }
  400. }
  401. /// <summary>
  402. /// 连接卡乐普机器人
  403. /// </summary>
  404. /// <param name="ip"></param>
  405. /// <param name="port"></param>
  406. public void ConnectKlpRobot(string ip, int port)
  407. {
  408. modbus = new ModbusTcp();
  409. modbus.Show += new Action<string>((s) =>
  410. {
  411. if (s != null) DeviceProcessLogShow(s);
  412. });
  413. modbus.ShowEx += new Action<string>((s) =>
  414. {
  415. if ((s != null)) DeviceProcessLogShow(s);
  416. });
  417. modbus.ModbusTcpConnect(ip, port);
  418. }
  419. /// <summary>
  420. /// 调酒小程序订单队列
  421. /// </summary>
  422. public ConcurrentQueue<BPASmartClient.MorkMW.Model.OrderLocInfo> orderLocInfos = new ConcurrentQueue<BPASmartClient.MorkMW.Model.OrderLocInfo>();
  423. /// <summary>
  424. /// 调酒模拟订单队列
  425. /// </summary>
  426. public ConcurrentQueue<SimOrderLocInfo> simOrderLocInfos = new ConcurrentQueue<SimOrderLocInfo>();
  427. /// <summary>
  428. /// 调酒机配方集合
  429. /// </summary>
  430. public List<MORKMWGoods> listMorkMWGoods = new List<MORKMWGoods>();
  431. }
  432. }