终端一体化运控平台
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

1290 righe
70 KiB

  1. using BPA.Message.Enum;
  2. using BPASmartClient.CustomResource.Pages.Model;
  3. using BPASmartClient.CustomResource.UserControls.MessageShow;
  4. using BPASmartClient.Device;
  5. using BPASmartClient.MorkCL.HelpClass;
  6. using BPASmartClient.MorkCL.Model.DB;
  7. using BPASmartClient.MorkCL.Model.Json;
  8. using BPASmartClient.MorkCL.Server;
  9. using Newtonsoft.Json.Linq;
  10. using Opc.Ua;
  11. using SqlSugar;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Net.WebSockets;
  16. using System.Reflection;
  17. using System.Text;
  18. using System.Threading.Tasks;
  19. namespace BPASmartClient.MorkCL
  20. {
  21. public class Control_MorkCL : BaseDevice
  22. {
  23. public override DeviceClientType DeviceType => DeviceClientType.MORKCL;
  24. GVL_MorkCL morkCL = new GVL_MorkCL();
  25. Alarm alarm = new Alarm();
  26. /// <summary>
  27. /// 设备信息集合
  28. /// </summary>
  29. ConcurrentDictionary<EDeviceType, IModbus> devices { get; set; } = new();
  30. /// <summary>
  31. /// 任务集合
  32. /// </summary>
  33. ConcurrentDictionary<EDeviceType, TaskServer> TaskList { get; set; } = new();
  34. List<PropertyInfo>? propertyInfos;
  35. public override void DoMain()
  36. {
  37. MonitorViewModel.DeviceId = DeviceId;
  38. SqliteHelper.GetInstance.Init();
  39. #region 读取本地文件数据
  40. Json<RecipesInfo>.Read();
  41. Json<ItemStorageInfo>.Read();
  42. Json<ConnectPar>.Read();
  43. #endregion
  44. //注册本地配方接收
  45. ActionManage.GetInstance.Register(new Action<object>(o =>
  46. {
  47. DeviceProcessLogShow($"接收到一个新配方任务。");
  48. if (o != null && o is ControlData cd)
  49. {
  50. morkCL.cds.Enqueue(cd);
  51. DeviceProcessLogShow($"新配方任务{cd.Id}解析完成,已加入配方队列。");
  52. }
  53. else
  54. {
  55. DeviceProcessLogShow($"新配方任务解析失败。");
  56. }
  57. }), NotifyTopic.FormulaDistribution);
  58. //初始化通讯对象
  59. devices.TryAdd(EDeviceType.炒锅1, new FryingPanServer());
  60. devices.TryAdd(EDeviceType.炒锅2, new FryingPanServer());
  61. devices.TryAdd(EDeviceType.机器人, new RobotServer());
  62. devices.TryAdd(EDeviceType.压力锅, new PressureCookerServer());
  63. devices.TryAdd(EDeviceType.外部设备, new OtherServer());
  64. morkCL.IsUseSplitStorage = Json<ConnectPar>.Data.IsUseSplitStorage;
  65. #if !FORMAL
  66. if (Json<ConnectPar>.Data.FryPanConnect_1)
  67. {
  68. devices[EDeviceType.炒锅1].Init(Json<ConnectPar>.Data.FryingPanIP1);
  69. }
  70. if (Json<ConnectPar>.Data.FryPanConnect_2)
  71. {
  72. devices[EDeviceType.炒锅2].Init(Json<ConnectPar>.Data.FryingPanIP2);
  73. }
  74. if (Json<ConnectPar>.Data.RobotConnet)
  75. {
  76. devices[EDeviceType.机器人].Init(Json<ConnectPar>.Data.RobotIP);
  77. }
  78. if (Json<ConnectPar>.Data.PressureCookerConnect)
  79. {
  80. devices[EDeviceType.压力锅].Init(Json<ConnectPar>.Data.PressureCookerIP);
  81. }
  82. if (Json<ConnectPar>.Data.OtherDeviceConnect)
  83. {
  84. devices[EDeviceType.外部设备].Init(PortName: Json<ConnectPar>.Data.ESPortName);
  85. }
  86. #endif
  87. ManualActionRegiester();
  88. }
  89. public override void MainTask()
  90. {
  91. //检查到有任务完成后将对已完成的任务进行清理
  92. var res = TaskList.FirstOrDefault(p => p.Value.IsComplete).Key;
  93. if (TaskList.ContainsKey(res))
  94. TaskList.TryRemove(res, out _);
  95. if (TaskList.IsEmpty)
  96. {
  97. morkCL.CanItemStorage = true;
  98. }
  99. else
  100. {
  101. morkCL.CanItemStorage = false;
  102. }
  103. //分配任务,这段程序必须写最后。
  104. if (morkCL.cds.Count > 0)
  105. {
  106. #region 修改为在下配方时选择使用哪个锅,这段程序不需要使用了。
  107. //var dishType = morkCL.cds.ElementAt(0).DishType;
  108. //var devieceType = EDeviceType.无;
  109. //if (dishType == Model.Recipe.EDishType.炒菜)
  110. //{
  111. // //如果任务队列里,炒锅1已经有任务了,就看炒锅2是否有任务,没任务就设置为炒锅2执行,如果两个锅都有任务则返回该次任务。
  112. // if (TaskList.ContainsKey(EDeviceType.炒锅1))
  113. // {
  114. // if (TaskList.ContainsKey(EDeviceType.炒锅2))
  115. // {
  116. // return;
  117. // }
  118. // else
  119. // { devieceType = EDeviceType.炒锅2; }
  120. // }
  121. // else
  122. // {
  123. // devieceType = EDeviceType.炒锅1;
  124. // }
  125. //}
  126. //else
  127. //{
  128. // devieceType = EDeviceType.压力锅;
  129. //}
  130. #endregion
  131. //这里判定主要是针对压力锅。
  132. //修改为炒锅和机器人不允许下单情况下,就不下单。
  133. if (!TaskList.ContainsKey(morkCL.cds.ElementAt(0).DeviceType) && GetFryPanAndRobotIsAuto(morkCL.cds.ElementAt(0).DeviceType))
  134. {
  135. if (morkCL.cds.TryDequeue(out ControlData cd))
  136. {
  137. //cd.DeviceType = devieceType;
  138. //cd.DeviceType = EDeviceType.炒锅1;
  139. TaskList.TryAdd(cd.DeviceType, new TaskServer());
  140. TaskList[cd.DeviceType].TaskName = $"{cd.DeviceType.ToString()}-{cd.Name}";
  141. TaskList[cd.DeviceType].RunTask = new Task(new Action(() => { FryingPanControl(cd.DeviceType, cd); }));
  142. TaskList[cd.DeviceType].RunTask.Start();
  143. }
  144. }
  145. }
  146. }
  147. #region 日志修改前
  148. //private async void FryingPanControl(EDeviceType et, ControlData cd)
  149. //{
  150. // DeviceProcessLogShow($"【{et}】开始执行-{cd.Name} 任务");
  151. // if (TaskList.ContainsKey(et) && TaskList[et].Cts.IsCancellationRequested)
  152. // return;
  153. // while (cd.ControlFuncs.Count > 0)
  154. // {
  155. // if (cd.ControlFuncs.TryDequeue(out FuncModel fm))
  156. // {
  157. // var device = (FryingPanServer)devices[et];
  158. // var robot = (RobotServer)devices[EDeviceType.机器人];
  159. // var otherDevice = (OtherServer)devices[EDeviceType.外部设备];
  160. // int index = (ushort)et - 1;
  161. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}。");
  162. // switch (fm.eFunc)
  163. // {
  164. // case EFunc.搅拌启动:
  165. // device.StirStartOrStop = false;
  166. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入搅拌频率-{fm.funcPars.ElementAt(0).ParValue.ToString()}HZ。");
  167. // device.MixingFrequencySet(fm.funcPars.ElementAt(0).ParValue.ToString());
  168. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入搅拌频率-{fm.funcPars.ElementAt(0).ParValue.ToString()}HZ完成。");
  169. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入开始搅拌。");
  170. // device.StirStartOrStop = true;
  171. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入开始搅拌完成。");
  172. // break;
  173. // case EFunc.搅拌停止:
  174. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入停止搅拌。");
  175. // device.StirStartOrStop = false;
  176. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-写入停止搅拌完成。");
  177. // break;
  178. // case EFunc.加热启动:
  179. // device.HeatStartOrStop = false;
  180. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置加热挡位-【{fm.funcPars.ElementAt(0).ParValue.ToString()}】。");
  181. // device.HeatingGearSet(fm.funcPars.ElementAt(0).ParValue.ToString());
  182. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置加热挡位完成,设置加热启动。");
  183. // device.HeatStartOrStop = true;
  184. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置加热启动完成。");
  185. // break;
  186. // case EFunc.加热停止:
  187. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置加热停止。");
  188. // device.HeatStartOrStop = false;
  189. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置加热停止完成。");
  190. // break;
  191. // case EFunc.添加调料:
  192. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-查找调料【{fm.funcPars.ElementAt(0).Id}】。");
  193. // var Seasoning = SqliteHelper.GetInstance.GetSeasoning().FirstOrDefault(p => p.Id == fm.funcPars.ElementAt(0).Id);
  194. // if (Seasoning != null)
  195. // {
  196. // device.FryingPanToSeasoningLoc = false;
  197. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置。");
  198. // device.FryingPanToSeasoningLoc = true;
  199. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置完成。");
  200. // //回到投料位置就复位。
  201. // Thread.Sleep(50);
  202. // device.FeedingSeasoningLocFB.Wait(Cts: TaskList[et].Cts);
  203. // device.FryingPanToSeasoningLoc = false;
  204. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-炒锅已到达调料投料位置。");
  205. // device.CuttingControl(Seasoning.Loc.ToString(), fm.funcPars.ElementAt(1).ParValue.ToString());
  206. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-执行下料,下料位置:{Seasoning.Loc.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  207. // }
  208. // else
  209. // {
  210. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-查找调料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】调料。任务取消。");
  211. // TaskList[et].Cts.Cancel();
  212. // }
  213. // break;
  214. // case EFunc.添加主料:
  215. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-查找主料【{fm.funcPars.ElementAt(0).Id}】。");
  216. // if (float.TryParse(fm.funcPars.ElementAt(1).ParValue.ToString(), out float weight))
  217. // {
  218. // //查找主料库位符合条件的物料库位,主要根据物料ID和物料重量查找。
  219. // var ingre_index = Array.FindIndex(Json<ItemStorageInfo>.Data.IngredientsStorage,
  220. // item => item.MaterialID == fm.funcPars.ElementAt(0).Id/* && item.Weight == weight*/);
  221. // if (ingre_index >= 0)
  222. // {
  223. // //device.CuttingControl(Seasoning.Loc.ToString(), fm.funcPars.ElementAt(1).ParValue.ToString());
  224. // var ingredientes = Json<ItemStorageInfo>.Data.IngredientsStorage[ingre_index];
  225. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-执行下料,控制取{ingre_index + 1}库物料,下料名称:{ingredientes.Name.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  226. // device.FryingPanHome = false;
  227. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(ingre_index + 1).ToString()}】,子任务【{et}】。");
  228. // robot.RobotTaskControl((ingre_index + 1).ToString(), et);
  229. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(ingre_index + 1).ToString()}】,子任务【{et}】完成。");
  230. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置。");
  231. // device.FryingPanHome = true;
  232. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成。");
  233. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置。");
  234. // device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  235. // device.FryingPanHome = false;
  236. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成。");
  237. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置。");
  238. // robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置也就是发出倒料请求。
  239. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置完成。");
  240. // //目前程序在炒锅在投料位置时,会自动发出允许倒料信息。
  241. // //DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料。");
  242. // //robot.AllowPourVegetables(et);//允许机器人开始投料
  243. // //DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料完成。");
  244. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-开始等待机器人投料完成。");
  245. // robot.MaterialPouringComplete[index].Wait(Cts: TaskList[et].Cts); //等待机器人投料完成
  246. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-机器人投料完成。");
  247. // Json<ItemStorageInfo>.Data.IngredientsStorage[ingre_index] = new ItemStorage();
  248. // Json<ItemStorageInfo>.Save();
  249. // ActionManage.GetInstance.Send("RefreshItemStorage");
  250. // }
  251. // else
  252. // {
  253. // //TODO:暂定为直接取消任务,后期再说。
  254. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】主料。任务取消。");
  255. // TaskList[et].Cts.Cancel();
  256. // }
  257. // }
  258. // break;
  259. // case EFunc.添加辅料:
  260. // MaterialBase mb = SqliteHelper.GetInstance.GetAccessories().FirstOrDefault(p => p.Id == fm.funcPars.ElementAt(0).Id);
  261. // if (mb != null)
  262. // {
  263. // //先复位变量。防止上一次是异常结束,设为True时,不会响应。
  264. // device.FryingPanHome = false;
  265. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(mb.Loc + 12).ToString()}】,子任务【{et}】。");
  266. // robot.RobotTaskControl((mb.Loc + 12).ToString(), et);
  267. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(mb.Loc + 12).ToString()}】,子任务【{et}】完成。");
  268. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置。");
  269. // device.FryingPanHome = true;
  270. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成。");
  271. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置。");
  272. // device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  273. // device.FryingPanHome = false;
  274. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成。");
  275. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置。");
  276. // robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置
  277. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置完成。");
  278. // //DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料。");
  279. // //robot.AllowPourVegetables(et);//允许机器人开始投料
  280. // //DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料完成。");
  281. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-开始等待机器人投料完成。");
  282. // robot.MaterialPouringComplete[index].Wait(Cts: TaskList[et].Cts); //等待机器人投料完成
  283. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-机器人投料完成。");
  284. // }
  285. // else
  286. // {
  287. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】辅料。任务取消。");
  288. // TaskList[et].Cts.Cancel();
  289. // }
  290. // break;
  291. // case EFunc.炒锅回原点位:
  292. // device.FryingPanFeedingLoc = false;
  293. // device.FryingPanHome = false;
  294. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回原点。");
  295. // device.FryingPanHome = true;
  296. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅回原点完成。");
  297. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待回原点完成。");
  298. // device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  299. // device.FryingPanHome = false;
  300. // break;
  301. // case EFunc.出餐启动:
  302. // device.DiningOutStart = false;
  303. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人取空盆。");
  304. // //TODO:暂时修改,后期优化。
  305. // while (true)
  306. // {
  307. // var emptyPanIndex = Array.FindIndex(otherDevice.BoxDetection, i => i == true);
  308. // if (emptyPanIndex >= 0)
  309. // {
  310. // robot.RobotTaskControl((21 + emptyPanIndex).ToString(), et);//取空盆
  311. // break;
  312. // }
  313. // await Task.Delay(3000);
  314. // DeviceProcessLogShow("无空盆,请添加空盆!");
  315. // }
  316. // //robot.RobotTaskControl("21", et);//取空盆
  317. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置机器人取空盆完成,等待机器人到出菜位置。");
  318. // robot.DiningOutRequest[index].Wait(Cts: TaskList[et].Cts);//等待机器人到出菜位置
  319. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-机器人已到出餐位置,出餐启动。");
  320. // device.DiningOutStart = true;
  321. // device.OutDinningSlowDownFlag.Wait(Cts: TaskList[et].Cts);
  322. // robot.ModerateInPlace(et);
  323. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-到达出餐减速位。");
  324. // device.OutDinningFinsh.Wait(Cts: TaskList[et].Cts);
  325. // robot.DiningOutComplete(et);
  326. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-出餐完成。");
  327. // //回到投料位置就复位。
  328. // Thread.Sleep(50);
  329. // device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  330. // device.DiningOutStart = false;
  331. // break;
  332. // case EFunc.炒锅清洗:
  333. // device.FryingPanClear = false;
  334. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅清洗。");
  335. // device.FryingPanClear = true;
  336. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-炒锅清洗已写入。");
  337. // Thread.Sleep(500);
  338. // device.CleanFinish.Wait(Cts: TaskList[et].Cts);
  339. // device.FryingPanClear = false;
  340. // break;
  341. // case EFunc.炒锅回调料投料位置:
  342. // device.FryingPanToSeasoningLoc = false;
  343. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置。");
  344. // device.FryingPanToSeasoningLoc = true;
  345. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置完成。");
  346. // //回到投料位置就复位。
  347. // Thread.Sleep(50);
  348. // device.FeedingSeasoningLocFB.Wait(Cts: TaskList[et].Cts);
  349. // device.FryingPanToSeasoningLoc = false;
  350. // break;
  351. // case EFunc.去指定炒制位:
  352. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置去指定炒制位。");
  353. // device.SetStirFryingLoc(fm.funcPars.ElementAt(0).ParValue.ToString());
  354. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-设置去指定炒制位【{fm.funcPars.ElementAt(0).ParValue.ToString()}】完成。");
  355. // break;
  356. // case EFunc.炒制:
  357. // if (int.TryParse(fm.funcPars.ElementAt(0).ParValue.ToString(), out int time))
  358. // {
  359. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-等待炒制【{time}】秒。");
  360. // Task.Delay(time * 1000).Wait(TaskList[et].Cts.Token);
  361. // }
  362. // DeviceProcessLogShow($"{cd.Name}-任务执行-{fm.eFunc.ToString()}-炒制完成。");
  363. // break;
  364. // default:
  365. // break;
  366. // }
  367. // }
  368. // }
  369. // DeviceProcessLogShow($"【{et}】任务-{cd.Name} 执行完成");
  370. //}
  371. #endregion
  372. #region 炒锅流程控制日志修改后
  373. private async void FryingPanControl(EDeviceType et, ControlData cd)
  374. {
  375. DeviceProcessLogShow($"【{et}】开始执行-{cd.Name} 任务");
  376. if (TaskList.ContainsKey(et) && TaskList[et].Cts.IsCancellationRequested)
  377. return;
  378. while (cd.ControlFuncs.Count > 0 && !TaskList[et].Cts.IsCancellationRequested)
  379. {
  380. if (cd.ControlFuncs.TryDequeue(out FuncModel fm))
  381. {
  382. var device = (FryingPanServer)devices[et];
  383. var robot = (RobotServer)devices[EDeviceType.机器人];
  384. var otherDevice = (OtherServer)devices[EDeviceType.外部设备];
  385. int index = (ushort)et - 1;
  386. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}。");
  387. try
  388. {
  389. switch (fm.eFunc)
  390. {
  391. #region 搅拌启动与停止
  392. case EFunc.搅拌启动:
  393. device.StirStartOrStop = false;
  394. device.MixingFrequencySet(fm.funcPars.ElementAt(0).ParValue.ToString());
  395. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入搅拌频率-{fm.funcPars.ElementAt(0).ParValue.ToString()}HZ完成。");
  396. await Task.Delay(400);
  397. device.StirStartOrStop = true;
  398. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入开始搅拌完成。");
  399. break;
  400. case EFunc.搅拌停止:
  401. device.StirStartOrStop = false;
  402. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入停止搅拌完成。");
  403. break;
  404. #endregion
  405. #region 加热启动与停止
  406. case EFunc.加热启动:
  407. device.HeatStartOrStop = false;
  408. await Task.Delay(400);
  409. device.HeatingGearSet(fm.funcPars.ElementAt(0).ParValue.ToString());
  410. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热挡位-【{fm.funcPars.ElementAt(0).ParValue.ToString()}】完成,等待设置加热启动。");
  411. device.HeatStartOrStop = true;
  412. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热启动完成。");
  413. break;
  414. case EFunc.加热停止:
  415. device.HeatStartOrStop = false;
  416. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热停止完成。");
  417. break;
  418. #endregion
  419. #region 添加调料
  420. case EFunc.添加调料:
  421. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找调料【{fm.funcPars.ElementAt(0).Id}】。");
  422. var Seasoning = SqliteHelper.GetInstance.GetSeasoning().FirstOrDefault(p => p.Id == fm.funcPars.ElementAt(0).Id);
  423. if (Seasoning != null)
  424. {
  425. device.FryingPanToSeasoningLoc = false;
  426. await Task.Delay(400);
  427. device.FryingPanToSeasoningLoc = true;
  428. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置完成,等待炒锅到达调料投料位置。");
  429. //回到投料位置就复位。
  430. await Task.Delay(400);
  431. device.FeedingSeasoningLocFB.Wait(Cts: TaskList[et].Cts);
  432. device.FryingPanToSeasoningLoc = false;
  433. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅已到达调料投料位置。");
  434. device.CuttingControl(Seasoning.Loc.ToString(), fm.funcPars.ElementAt(1).ParValue.ToString(), TaskList[et].Cts);
  435. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-执行下料,下料位置:{Seasoning.Loc.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  436. //去炒制位
  437. string stirFryLoc = fm.funcPars.ElementAt(2).ParValue.ToString();
  438. GoStirFryLoc(stirFryLoc);
  439. //炒制
  440. if (int.TryParse(fm.funcPars.ElementAt(3).ParValue.ToString(), out int time1))
  441. {
  442. StirFry(time1);
  443. }
  444. }
  445. else
  446. {
  447. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找调料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】调料,任务即将取消。", DialogType.Warning);
  448. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找调料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】调料。任务取消。");
  449. TaskList[et].Cts.Cancel();
  450. }
  451. break;
  452. #endregion
  453. #region 添加主料
  454. case EFunc.添加主料:
  455. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找主料【{fm.funcPars.ElementAt(0).Id}】。");
  456. if (float.TryParse(fm.funcPars.ElementAt(1).ParValue.ToString(), out float weight))
  457. {
  458. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  459. //查找主料库位符合条件的物料库位,主要根据物料ID和物料重量查找。
  460. var ingre_index = Array.FindIndex(Json<ItemStorageInfo>.Data.IngredientsStorage,
  461. item => item.MaterialID == fm.funcPars.ElementAt(0).Id/* && item.Weight == weight*/);
  462. if (ingre_index >= 0)
  463. {
  464. var ingredientes = Json<ItemStorageInfo>.Data.IngredientsStorage[ingre_index];
  465. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-执行下料,控制取{ingre_index + 1}库物料,下料名称:{ingredientes.Name.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  466. device.FryingPanHome = false;
  467. robot.RobotTaskControl((ingre_index + 1).ToString(), et);
  468. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(ingre_index + 1).ToString()}】,子任务【{et}】完成。");
  469. await Task.Delay(400);
  470. device.FryingPanHome = true;
  471. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成,等待炒锅回到主料辅料投料位置");
  472. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  473. await Task.Delay(400);
  474. device.FryingPanHome = false;
  475. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成。");
  476. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置。");
  477. robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置也就是发出倒料请求。
  478. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人已到达投料位置,等待机器人投料完成。");
  479. robot.MaterialPouringComplete[index].Wait(Cts: TaskList[et].Cts); //等待机器人投料完成
  480. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人投料完成。");
  481. Json<ItemStorageInfo>.Data.IngredientsStorage[ingre_index] = new ItemStorage();
  482. Json<ItemStorageInfo>.Save();
  483. ActionManage.GetInstance.Send("RefreshItemStorage");
  484. //去炒制位
  485. string stirFryLoc = fm.funcPars.ElementAt(2).ParValue.ToString();
  486. GoStirFryLoc(stirFryLoc);
  487. //炒制
  488. if (int.TryParse(fm.funcPars.ElementAt(3).ParValue.ToString(), out int time2))
  489. {
  490. StirFry(time2);
  491. }
  492. }
  493. else
  494. {
  495. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】主料,任务即将取消。", DialogType.Warning);
  496. //TODO:暂定为直接取消任务,后期再说。
  497. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】主料。任务取消。");
  498. TaskList[et].Cts.Cancel();
  499. }
  500. }
  501. break;
  502. #endregion
  503. #region 添加辅料
  504. case EFunc.添加辅料:
  505. #region 根据配置文件选择每个炒锅的最大最小辅料位置,暂时没使用。
  506. var minloc = 1;
  507. var maxloc = 8;
  508. if (morkCL.IsUseSplitStorage)
  509. {
  510. if (et == EDeviceType.炒锅1)
  511. {
  512. minloc = Json<ConnectPar>.Data.FryPanAccessoriesMin_1;
  513. maxloc = Json<ConnectPar>.Data.FryPanAccessoriesMax_1;
  514. }
  515. else if (et == EDeviceType.炒锅2)
  516. {
  517. minloc = Json<ConnectPar>.Data.FryPanAccessoriesMin_2;
  518. maxloc = Json<ConnectPar>.Data.FryPanAccessoriesMax_2;
  519. }
  520. }
  521. else
  522. {
  523. minloc = 1;
  524. maxloc = 8;
  525. }
  526. #endregion
  527. MaterialBase mb = SqliteHelper.GetInstance.GetAccessories().FirstOrDefault(p => p.Loc >= minloc && p.Loc <= maxloc && p.Id == fm.funcPars.ElementAt(0).Id);
  528. if (mb != null)
  529. {
  530. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  531. //先复位变量。防止上一次是异常结束,设为True时,不会响应。
  532. device.FryingPanHome = false;
  533. robot.RobotTaskControl((mb.Loc + 12).ToString(), et);
  534. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(mb.Loc + 12).ToString()}】,子任务【{et}】完成。");
  535. await Task.Delay(400);
  536. device.FryingPanHome = true;
  537. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成,开始等待炒锅到投料位置。");
  538. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  539. await Task.Delay(400);
  540. device.FryingPanHome = false;
  541. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成,等待机器人到投料位置。");
  542. robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置
  543. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人到达投料位置完成,开始等待机器人投料完成。");
  544. robot.MaterialPouringComplete[index].Wait(Cts: TaskList[et].Cts); //等待机器人投料完成
  545. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人投料完成。");
  546. //去炒制位
  547. string stirFryLoc = fm.funcPars.ElementAt(1).ParValue.ToString();
  548. GoStirFryLoc(stirFryLoc);
  549. //炒制
  550. if (int.TryParse(fm.funcPars.ElementAt(2).ParValue.ToString(), out int time3))
  551. {
  552. StirFry(time3);
  553. }
  554. }
  555. else
  556. {
  557. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找辅料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】辅料,任务即将取消。", DialogType.Warning);
  558. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找辅料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】辅料。任务取消。");
  559. TaskList[et].Cts.Cancel();
  560. }
  561. break;
  562. #endregion
  563. case EFunc.炒锅回原点位:
  564. GoHome();
  565. break;
  566. #region 出餐启动
  567. case EFunc.出餐启动:
  568. device.DiningOutStart = false;
  569. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人取空盆。");
  570. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  571. //TODO:暂时修改,后期优化。
  572. while (!TaskList[et].Cts.IsCancellationRequested)
  573. {
  574. var emptyPanIndex = Array.FindIndex(otherDevice.BoxDetection, i => i == true);
  575. if (emptyPanIndex >= 0)
  576. {
  577. robot.RobotTaskControl((21 + emptyPanIndex).ToString(), et);//取空盆
  578. break;
  579. }
  580. await Task.Delay(3000);
  581. DeviceProcessLogShow("无空盆,请添加空盆!");
  582. }
  583. //robot.RobotTaskControl("21", et);//取空盆
  584. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人取空盆完成,等待机器人到出菜位置。");
  585. robot.DiningOutRequest[index].Wait(Cts: TaskList[et].Cts);//等待机器人到出菜位置
  586. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人已到出餐位置,出餐启动。");
  587. await Task.Delay(400);
  588. device.DiningOutStart = true;
  589. device.OutDinningSlowDownFlag.Wait(Cts: TaskList[et].Cts);
  590. robot.ModerateInPlace(et);
  591. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-到达出餐减速位。");
  592. device.OutDinningFinsh.Wait(Cts: TaskList[et].Cts);
  593. robot.DiningOutComplete(et);
  594. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-出餐完成。");
  595. //回到投料位置就复位。
  596. Thread.Sleep(50);
  597. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  598. await Task.Delay(400);
  599. device.DiningOutStart = false;
  600. break;
  601. #endregion
  602. #region 炒锅清洗--基本没用
  603. case EFunc.炒锅清洗:
  604. device.FryingPanClear = false;
  605. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅清洗。");
  606. await Task.Delay(400);
  607. device.FryingPanClear = true;
  608. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅清洗已写入,等待炒锅清洗完成。");
  609. Thread.Sleep(500);
  610. device.CleanFinish.Wait(Cts: TaskList[et].Cts);
  611. await Task.Delay(400);
  612. device.FryingPanClear = false;
  613. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅清洗完成。");
  614. break;
  615. #endregion
  616. #region
  617. case EFunc.去指定炒制位:
  618. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置去指定炒制位。");
  619. string loc = fm.funcPars.ElementAt(0).ParValue.ToString();
  620. GoStirFryLoc(loc);
  621. break;
  622. case EFunc.炒制:
  623. if (int.TryParse(fm.funcPars.ElementAt(0).ParValue.ToString(), out int time))
  624. {
  625. StirFry(time);
  626. }
  627. break;
  628. #endregion
  629. default:
  630. break;
  631. }
  632. #region 回原点
  633. void GoHome()
  634. {
  635. device.FryingPanFeedingLoc = false;
  636. device.FryingPanHome = false;
  637. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回原点。");
  638. Task.Delay(400).Wait();
  639. device.FryingPanHome = true;
  640. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回原点完成,等待炒锅回原点。");
  641. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待回原点完成。");
  642. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  643. Task.Delay(400).Wait();
  644. device.FryingPanHome = false;
  645. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅回原点完成。");
  646. }
  647. #endregion
  648. #region 去指定炒制位
  649. //去指定炒制位
  650. void GoStirFryLoc(string loc)
  651. {
  652. device.SetStirFryingLoc(loc, TaskList[et].Cts);
  653. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置去指定炒制位【{fm.funcPars.ElementAt(0).ParValue.ToString()}】完成。");
  654. //TODO:根据情况看是否需要等待反馈变量。
  655. //device.StirFryingLocFB[int.Parse(fm.funcPars.ElementAt(0).ParValue.ToString())].Wait();
  656. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅到达炒制位【{fm.funcPars.ElementAt(0).ParValue.ToString()}】。");
  657. }
  658. #endregion
  659. #region 炒制延时
  660. //炒制延时。
  661. void StirFry(int time)
  662. {
  663. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒制【{time}】秒。");
  664. Task.Delay(time * 1000).Wait(TaskList[et].Cts.Token);
  665. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒制完成。");
  666. }
  667. #endregion
  668. }
  669. catch (TaskCanceledException)
  670. {
  671. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务被取消。");
  672. }
  673. catch (OperationCanceledException)
  674. {
  675. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务被手动取消。");
  676. }
  677. }
  678. }
  679. DeviceProcessLogShow($"【{et}】任务-{cd.Name} 执行完成");
  680. TaskList[et].IsComplete = true;
  681. }
  682. #endregion
  683. public override void ReadData()
  684. {
  685. if (propertyInfos is null || propertyInfos.Count == 0)
  686. {
  687. propertyInfos = morkCL.GetType().GetProperties().ToList();
  688. }
  689. morkCL.RecipeQueueCount = morkCL.cds.Count;
  690. morkCL.FryingPanTaskCount_1 = morkCL.cds.Count(data => data.DeviceType == EDeviceType.炒锅1);
  691. morkCL.FryingPanTaskCount_2 = morkCL.cds.Count(data => data.DeviceType == EDeviceType.炒锅2);
  692. var fryingPan1 = (FryingPanServer)devices[EDeviceType.炒锅1];
  693. var fryingPan2 = (FryingPanServer)devices[EDeviceType.炒锅2];
  694. var robot = (RobotServer)devices[EDeviceType.机器人];
  695. var pressureCooker = (PressureCookerServer)devices[EDeviceType.压力锅];
  696. var otherDevice = (OtherServer)devices[EDeviceType.外部设备];
  697. alarm.EStop1 = fryingPan1.EStopAlarm;
  698. alarm.FryingPanFowardLimit1 = fryingPan1.FryingPanFowardLimit;
  699. alarm.FryingPanReverseLimit1 = fryingPan1.FryingPanReverseLimit;
  700. alarm.FryingPanEncoderCommError1 = fryingPan1.FryingPanEncoderCommError;
  701. alarm.StirMotorCommError1 = fryingPan1.StirMotorCommError;
  702. alarm.RollingMotorCommError1 = fryingPan1.RollingMotorCommError;
  703. alarm.StirMotorError1 = fryingPan1.StirMotorErrorCode != "无故障" ? true : false;
  704. alarm.TurnMotorError1 = fryingPan1.TurnMotorErrorCode != "无故障" ? true : false;
  705. alarm.EStop2 = fryingPan2.EStopAlarm;
  706. alarm.FryingPanFowardLimit2 = fryingPan2.FryingPanFowardLimit;
  707. alarm.FryingPanReverseLimit2 = fryingPan2.FryingPanReverseLimit;
  708. alarm.FryingPanEncoderCommError2 = fryingPan2.FryingPanEncoderCommError;
  709. alarm.StirMotorCommError2 = fryingPan2.StirMotorCommError;
  710. alarm.RollingMotorCommError2 = fryingPan2.RollingMotorCommError;
  711. alarm.StirMotorError2 = fryingPan2.StirMotorErrorCode != "无故障" ? true : false;
  712. alarm.TurnMotorError2 = fryingPan2.TurnMotorErrorCode != "无故障" ? true : false;
  713. //这是字段。直接赋值
  714. morkCL.FeedingSeasoningLocFB1 = fryingPan1.FeedingSeasoningLocFB;
  715. morkCL.FeedingSeasoningLocFB2 = fryingPan2.FeedingSeasoningLocFB;
  716. morkCL.FeedingLocFB1 = fryingPan1.FeedingLocFB;
  717. morkCL.FeedingLocFB2 = fryingPan2.FeedingLocFB;
  718. morkCL.CleanFinish1 = fryingPan1.CleanFinish;
  719. morkCL.CleanFinish2 = fryingPan2.CleanFinish;
  720. morkCL.OutDinningFinsh1 = fryingPan1.OutDinningFinsh;
  721. morkCL.OutDinningFinsh2 = fryingPan2.OutDinningFinsh;
  722. morkCL.OutDinningSlowDownFlag1 = fryingPan1.OutDinningSlowDownFlag;
  723. morkCL.OutDinningSlowDownFlag2 = fryingPan2.OutDinningSlowDownFlag;
  724. morkCL.BoxDetection = otherDevice.BoxDetection;
  725. morkCL.IsIdle = robot.IsIdle;
  726. #if !FORMAL
  727. if (fryingPan1.FeedingLocFB)
  728. {
  729. robot.AllowPourVegetables(EDeviceType.炒锅1);
  730. }
  731. else
  732. {
  733. robot.DisablePourVegetables(EDeviceType.炒锅1);
  734. }
  735. if (fryingPan2.FeedingLocFB)
  736. {
  737. robot.AllowPourVegetables(EDeviceType.炒锅2);
  738. }
  739. else
  740. {
  741. robot.DisablePourVegetables(EDeviceType.炒锅2);
  742. }
  743. foreach (var property in propertyInfos)
  744. {
  745. var att = property.GetCustomAttribute<VariableMonitorAttribute>();
  746. if (att != null)
  747. {
  748. if (att.Notes.Contains("1号炒锅"))
  749. {
  750. var p = fryingPan1.GetType().GetProperty(property.Name.TrimEnd('1'));
  751. if (p != null)
  752. {
  753. property.SetValue(morkCL, p.GetValue(fryingPan1));
  754. }
  755. }
  756. else if (att.Notes.Contains("2号炒锅"))
  757. {
  758. var p = fryingPan2.GetType().GetProperty(property.Name.TrimEnd('2'));
  759. if (p != null)
  760. {
  761. property.SetValue(morkCL, p.GetValue(fryingPan2));
  762. }
  763. }
  764. else if (att.Notes.Contains("机器人"))
  765. {
  766. var p = robot.GetType().GetProperty(property.Name);
  767. if (p != null)
  768. {
  769. property.SetValue(morkCL, p.GetValue(robot));
  770. }
  771. }
  772. else if (att.Notes.Contains("电子秤"))
  773. {
  774. var p = otherDevice.GetType().GetProperty(property.Name);
  775. if (p != null)
  776. {
  777. var res = p.GetValue(otherDevice);
  778. property.SetValue(morkCL, res);
  779. if (p.Name == "CurrentWeight")
  780. {
  781. ActionManage.GetInstance.Send(res, "SendCurrentWeight");
  782. }
  783. }
  784. }
  785. else if (att.Notes.Contains("高压锅"))
  786. {
  787. var p = pressureCooker.GetType().GetProperty(property.Name);
  788. if (p != null)
  789. {
  790. property.SetValue(morkCL, p.GetValue(pressureCooker));
  791. }
  792. }
  793. }
  794. }
  795. #endif
  796. }
  797. public override void ResetProgram()
  798. {
  799. morkCL = null;
  800. morkCL = new GVL_MorkCL();
  801. }
  802. public override void SimOrder()
  803. {
  804. }
  805. public override void Stop()
  806. {
  807. }
  808. private bool GetFryPanAndRobotIsAuto(EDeviceType fryPan)
  809. {
  810. //目前拿不到机器人的远程状态,只能拿到炒锅的。
  811. var device = (FryingPanServer)devices[fryPan];
  812. var robot = (RobotServer)devices[EDeviceType.机器人];
  813. return device.InitComplete && device.StatusMode && device.EStop && robot.RemoteMode;
  814. }
  815. void ManualActionRegiester()
  816. {
  817. //主料入库委托。
  818. ActionManage.GetInstance.Register((object o) =>
  819. {
  820. if (!morkCL.CanItemStorage)
  821. {
  822. MessageNotify.GetInstance.ShowDialog("当前有炒菜任务正在排队,为避免影响菜品口味,不可入库,请稍后再试。", DialogType.Warning);
  823. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料入库失败,当前正在制作菜品。");
  824. return;
  825. }
  826. var robot = (RobotServer)devices[EDeviceType.机器人];
  827. if (robot.IsIdle == false)
  828. {
  829. MessageNotify.GetInstance.ShowDialog("当前机器人未在空闲状态,稍后再试。", DialogType.Warning);
  830. return;
  831. }
  832. TaskManage.GetInstance.Start(() =>
  833. {
  834. if (o != null && o is IngredientsTB ingredients)
  835. {
  836. var index = Array.FindIndex(Json<ItemStorageInfo>.Data.IngredientsStorage, i => i.IsEmploy == false);
  837. if (index >= 0)
  838. {
  839. if (!MessageNotify.GetInstance.ShowDialog($"请确认库位【{index + 1}】上无物品,否则可能会造成碰撞事故!", DialogType.Warning))
  840. {
  841. DeviceProcessLogShow($"物料[{ingredients.Name}],ID:[{ingredients.Id}],库位[{index + 1}]入库失败,未确认库位无异物。");
  842. Application.Current.Dispatcher.Invoke(() =>
  843. {
  844. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料{ingredients.Name}入库失败。");
  845. });
  846. return;
  847. }
  848. var item = Json<ItemStorageInfo>.Data.IngredientsStorage[index];
  849. item.MaterialID = ingredients.Id;
  850. item.Name = ingredients.Name;
  851. item.IsEmploy = true;
  852. item.Weight = ((OtherServer)devices[EDeviceType.外部设备]).CurrentWeight;
  853. var loc = (index + 1).ToString();
  854. #if !FORMAL
  855. robot.WarehousingControl(loc, null);
  856. DeviceProcessLogShow($"已下发机器人物料入{loc}号库任务,等待机器人入库操作完成");
  857. robot.WarehousingComplete[(Convert.ToInt32(loc) - 1)].Wait();
  858. #endif
  859. Json<ItemStorageInfo>.Save();
  860. ActionManage.GetInstance.Send("RefreshItemStorage");
  861. DeviceProcessLogShow($"物料[{ingredients.Name}],ID:[{ingredients.Id}],库位[{index + 1}]入库成功。");
  862. Application.Current.Dispatcher.Invoke(() =>
  863. {
  864. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "入库成功", $"物料{ingredients.Name}入库成功。");
  865. });
  866. return;
  867. }
  868. else
  869. {
  870. Application.Current.Dispatcher.Invoke(() =>
  871. {
  872. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料库已满。");
  873. });
  874. }
  875. }
  876. else
  877. {
  878. Application.Current.Dispatcher.Invoke(() =>
  879. {
  880. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料入库失败。");
  881. });
  882. }
  883. }, "ItemStorageTask");
  884. }, NotifyTopic.ItemStorage, true);
  885. ActionManage.GetInstance.Register(() =>
  886. {
  887. ActionManage.GetInstance.Send("SystemIsBusy").OnFinally(isBusy =>
  888. {
  889. if (isBusy.IsSuccess == true)
  890. {
  891. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "失败", $"当前还有配方任务在排队制作,请稍后后再试。");
  892. return;
  893. }
  894. Task.Run(() =>
  895. {
  896. var robot = (RobotServer)devices[EDeviceType.机器人];
  897. robot.GoCleanLoc();
  898. Application.Current.Dispatcher.Invoke(() =>
  899. {
  900. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "设置成功", $"设置机器人去清洗位置成功。");
  901. });
  902. robot.AtCleanLoc.Wait();
  903. Application.Current.Dispatcher.Invoke(() =>
  904. {
  905. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "成功", $"机器人已到达清洗位置。");
  906. });
  907. });
  908. });
  909. //if (ActionManage.GetInstance.SendResult("SystemIsBusy") is bool isBusy)
  910. //{
  911. // if (isBusy == true)
  912. // {
  913. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "失败", $"当前还有配方任务在排队制作,请稍后后再试。");
  914. // return;
  915. // }
  916. // Task.Run(() =>
  917. // {
  918. // var robot = (RobotServer)devices[EDeviceType.机器人];
  919. // robot.GoCleanLoc();
  920. // Application.Current.Dispatcher.Invoke(() =>
  921. // {
  922. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "设置成功", $"设置机器人去清洗位置成功。");
  923. // });
  924. // robot.AtCleanLoc.Wait();
  925. // Application.Current.Dispatcher.Invoke(() =>
  926. // {
  927. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "成功", $"机器人已到达清洗位置。");
  928. // });
  929. // });
  930. //}
  931. }, "RobotGoCleanLoc", true);
  932. ActionManage.GetInstance.Register(() =>
  933. {
  934. Task.Run(() =>
  935. {
  936. var robot = (RobotServer)devices[EDeviceType.机器人];
  937. bool isSuccuess = robot.SendCleanFinish();
  938. if (isSuccuess)
  939. {
  940. Application.Current.Dispatcher.Invoke(() =>
  941. {
  942. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "通知成功", $"通知机器人清洗完成成功。");
  943. });
  944. }
  945. });
  946. }, "RobotCleanFinish", true);
  947. #region 暂时弃用
  948. ActionManage.GetInstance.Register((object location) =>
  949. {
  950. var loc = location.ToString();
  951. if (!String.IsNullOrEmpty(loc) && loc.Length >= 0)
  952. {
  953. var robot = (RobotServer)devices[EDeviceType.机器人];
  954. //Thread.Sleep(5000);
  955. robot.WarehousingControl(loc, null);
  956. //会卡死。
  957. robot.WarehousingComplete[(Convert.ToInt32(loc) - 1)].Wait();
  958. }
  959. }, "ItemStorage", true);
  960. #endregion
  961. ActionManage.GetInstance.Register((object[] o) =>
  962. {
  963. if (o is not null && o is object[] para)
  964. {
  965. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), para[0].ToString());
  966. var channelIndex = para[1].ToString();
  967. var demandValue = para[2].ToString();
  968. ((FryingPanServer)devices[device]).CuttingControl(channelIndex, demandValue, null);
  969. }
  970. }, "DeviceCuttingControl", true);
  971. ActionManage.GetInstance.Register((object o) =>
  972. {
  973. if (o is not null)
  974. {
  975. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  976. if (TaskList.ContainsKey(device))
  977. {
  978. TaskList[device].Cts.Cancel();
  979. DeviceProcessLogShow($"取消{device}当前任务成功。");
  980. }
  981. else
  982. {
  983. DeviceProcessLogShow($"[{device}]当前无任务。");
  984. }
  985. }
  986. }, "CancelFryPanTask", true);
  987. ActionManage.GetInstance.Register((object o) =>
  988. {
  989. if (o is not null)
  990. {
  991. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  992. //TODO : 把所有属于该炒锅的任务全部删除。
  993. }
  994. }, "ClearFryPanTask", true);
  995. ActionManage.GetInstance.Register(() =>
  996. {
  997. //电子秤去皮
  998. var weghier = (OtherServer)devices[EDeviceType.外部设备];
  999. if (weghier.WeigherTare())
  1000. {
  1001. Application.Current.Dispatcher.Invoke(() =>
  1002. {
  1003. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "去皮成功", $"电子秤除皮操作成功。");
  1004. });
  1005. DeviceProcessLogShow($"电子秤除皮操作成功。");
  1006. }
  1007. else
  1008. {
  1009. Application.Current.Dispatcher.Invoke(() =>
  1010. {
  1011. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "去皮失败", $"电子秤除皮操作失败。");
  1012. });
  1013. DeviceProcessLogShow($"电子秤除皮操作失败。");
  1014. }
  1015. }, "WeighrTare", true);
  1016. ActionManage.GetInstance.Register(() =>
  1017. {
  1018. //电子秤置零
  1019. var weghier = (OtherServer)devices[EDeviceType.外部设备];
  1020. if (weghier.WeigherZero())
  1021. {
  1022. Application.Current.Dispatcher.Invoke(() =>
  1023. {
  1024. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "置零成功", $"电子秤置零操作成功。");
  1025. });
  1026. DeviceProcessLogShow($"电子秤置零操作成功。");
  1027. }
  1028. else
  1029. {
  1030. Application.Current.Dispatcher.Invoke(() =>
  1031. {
  1032. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "置零失败", $"电子秤置零操作失败。");
  1033. });
  1034. DeviceProcessLogShow($"电子秤置零操作失败。");
  1035. }
  1036. }, "WeighrZero", true);
  1037. ActionManage.GetInstance.Register((object o) =>
  1038. {
  1039. if (o != null && o is WriteModel<bool> write)
  1040. {
  1041. if (!TaskList.ContainsKey(write.DeviceType))
  1042. {
  1043. devices[write.DeviceType].WriteValue<bool>(write.Address, write.Value);
  1044. DeviceProcessLogShow($"设备[{write.DeviceType}]--手动写入地址[{write.Address}],值[{write.Value}]");
  1045. }
  1046. }
  1047. }, "WriteBool", true);
  1048. ActionManage.GetInstance.Register((object o) =>
  1049. {
  1050. if (o != null && o is WriteModel<ushort> write)
  1051. {
  1052. if (!TaskList.ContainsKey(write.DeviceType))
  1053. {
  1054. devices[write.DeviceType].WriteValue<ushort>(write.Address, write.Value);
  1055. DeviceProcessLogShow($"设备[{write.DeviceType}]--手动写入地址[{write.Address}],值[{write.Value}]");
  1056. }
  1057. //else
  1058. //{
  1059. // //MessageNotify.GetInstance.ShowDialog("当前有炒菜任务,不可手动操作,请稍后再试。", DialogType.Warning);
  1060. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "操作失败", $"手动操作失败,当前正在制作菜品。");
  1061. // return;
  1062. //}
  1063. }
  1064. }, "WriteUshort", true);
  1065. ActionManage.GetInstance.Register(frypanIsIdle, "GetDeviceIsIdle", true);
  1066. ActionManage.GetInstance.Register(() =>
  1067. {
  1068. var robot = (RobotServer)devices[EDeviceType.机器人];
  1069. if (robot.InitVariable())
  1070. {
  1071. Application.Current.Dispatcher.Invoke(() => { NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "成功", $"复位所有由上位机下发至机器人的变量成功。"); });
  1072. DeviceProcessLogShow($"复位所有由上位机下发至机器人的变量成功。");
  1073. }
  1074. else
  1075. {
  1076. Application.Current.Dispatcher.Invoke(() => { NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "失败", $"复位所有由上位机下发至机器人的变量失败。"); });
  1077. DeviceProcessLogShow($"复位所有由上位机下发至机器人的变量失败。");
  1078. }
  1079. }, "InitRobotAllVar", true);
  1080. ActionManage.GetInstance.Register<bool>(() =>
  1081. {
  1082. if (morkCL.RecipeQueueCount > 0 || morkCL.FryingPanTaskCount_1 > 0 || morkCL.FryingPanTaskCount_2 > 0)
  1083. {
  1084. return true;
  1085. }
  1086. return false;
  1087. }, "SystemIsBusy", true);
  1088. }
  1089. Func<object, object> frypanIsIdle => (o) =>
  1090. {
  1091. if (o is not null)
  1092. {
  1093. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  1094. if (!TaskList.ContainsKey(device))
  1095. {
  1096. return true;
  1097. }
  1098. }
  1099. return false;
  1100. };
  1101. }
  1102. }