终端一体化运控平台
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

1210 行
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. case EFunc.搅拌启动:
  392. device.StirStartOrStop = false;
  393. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入搅拌频率-{fm.funcPars.ElementAt(0).ParValue.ToString()}HZ。");
  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. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入开始搅拌。");
  398. device.StirStartOrStop = true;
  399. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入开始搅拌完成。");
  400. break;
  401. case EFunc.搅拌停止:
  402. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入停止搅拌。");
  403. device.StirStartOrStop = false;
  404. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-写入停止搅拌完成。");
  405. break;
  406. case EFunc.加热启动:
  407. device.HeatStartOrStop = false;
  408. await Task.Delay(400);
  409. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热挡位-【{fm.funcPars.ElementAt(0).ParValue.ToString()}】。");
  410. device.HeatingGearSet(fm.funcPars.ElementAt(0).ParValue.ToString());
  411. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热挡位-【{fm.funcPars.ElementAt(0).ParValue.ToString()}】完成,等待设置加热启动。");
  412. device.HeatStartOrStop = true;
  413. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热启动完成。");
  414. break;
  415. case EFunc.加热停止:
  416. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热停止。");
  417. device.HeatStartOrStop = false;
  418. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置加热停止完成。");
  419. break;
  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. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置。");
  428. device.FryingPanToSeasoningLoc = true;
  429. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置完成,等待炒锅到达调料投料位置。");
  430. //回到投料位置就复位。
  431. await Task.Delay(400);
  432. device.FeedingSeasoningLocFB.Wait(Cts: TaskList[et].Cts);
  433. device.FryingPanToSeasoningLoc = false;
  434. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅已到达调料投料位置。");
  435. device.CuttingControl(Seasoning.Loc.ToString(), fm.funcPars.ElementAt(1).ParValue.ToString(), TaskList[et].Cts);
  436. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-执行下料,下料位置:{Seasoning.Loc.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  437. }
  438. else
  439. {
  440. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找调料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】调料,任务即将取消。", DialogType.Warning);
  441. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找调料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】调料。任务取消。");
  442. TaskList[et].Cts.Cancel();
  443. }
  444. break;
  445. case EFunc.添加主料:
  446. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找主料【{fm.funcPars.ElementAt(0).Id}】。");
  447. if (float.TryParse(fm.funcPars.ElementAt(1).ParValue.ToString(), out float weight))
  448. {
  449. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  450. //查找主料库位符合条件的物料库位,主要根据物料ID和物料重量查找。
  451. var ingre_index = Array.FindIndex(Json<ItemStorageInfo>.Data.IngredientsStorage,
  452. item => item.MaterialID == fm.funcPars.ElementAt(0).Id/* && item.Weight == weight*/);
  453. if (ingre_index >= 0)
  454. {
  455. //device.CuttingControl(Seasoning.Loc.ToString(), fm.funcPars.ElementAt(1).ParValue.ToString());
  456. var ingredientes = Json<ItemStorageInfo>.Data.IngredientsStorage[ingre_index];
  457. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-执行下料,控制取{ingre_index + 1}库物料,下料名称:{ingredientes.Name.ToString()},下料重量:【{fm.funcPars.ElementAt(1).ParValue.ToString()}】。");
  458. device.FryingPanHome = false;
  459. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(ingre_index + 1).ToString()}】,子任务【{et}】。");
  460. robot.RobotTaskControl((ingre_index + 1).ToString(), et);
  461. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(ingre_index + 1).ToString()}】,子任务【{et}】完成。");
  462. await Task.Delay(400);
  463. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置。");
  464. device.FryingPanHome = true;
  465. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成,等待炒锅回到主料辅料投料位置");
  466. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置。");
  467. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  468. await Task.Delay(400);
  469. device.FryingPanHome = false;
  470. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成。");
  471. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置。");
  472. robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置也就是发出倒料请求。
  473. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置完成。");
  474. //目前程序在炒锅在投料位置时,会自动发出允许倒料信息。
  475. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料。");
  476. //robot.AllowPourVegetables(et);//允许机器人开始投料
  477. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料完成。");
  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. else
  486. {
  487. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】主料,任务即将取消。", DialogType.Warning);
  488. //TODO:暂定为直接取消任务,后期再说。
  489. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找主料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】主料。任务取消。");
  490. TaskList[et].Cts.Cancel();
  491. }
  492. }
  493. break;
  494. case EFunc.添加辅料:
  495. #region 根据配置文件选择每个炒锅的最大最小辅料位置,暂时没使用。
  496. var minloc = 1;
  497. var maxloc = 8;
  498. if (morkCL.IsUseSplitStorage)
  499. {
  500. if (et == EDeviceType.炒锅1)
  501. {
  502. minloc = Json<ConnectPar>.Data.FryPanAccessoriesMin_1;
  503. maxloc = Json<ConnectPar>.Data.FryPanAccessoriesMax_1;
  504. }
  505. else if (et == EDeviceType.炒锅2)
  506. {
  507. minloc = Json<ConnectPar>.Data.FryPanAccessoriesMin_2;
  508. maxloc = Json<ConnectPar>.Data.FryPanAccessoriesMax_2;
  509. }
  510. }
  511. else
  512. {
  513. minloc = 1;
  514. maxloc = 8;
  515. }
  516. #endregion
  517. MaterialBase mb = SqliteHelper.GetInstance.GetAccessories().FirstOrDefault(p => p.Loc >= minloc && p.Loc <= maxloc && p.Id == fm.funcPars.ElementAt(0).Id);
  518. if (mb != null)
  519. {
  520. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  521. //先复位变量。防止上一次是异常结束,设为True时,不会响应。
  522. device.FryingPanHome = false;
  523. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(mb.Loc + 12).ToString()}】,子任务【{et}】。");
  524. robot.RobotTaskControl((mb.Loc + 12).ToString(), et);
  525. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人任务【{(mb.Loc + 12).ToString()}】,子任务【{et}】完成。");
  526. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置。");
  527. await Task.Delay(400);
  528. device.FryingPanHome = true;
  529. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回投料位置完成,开始等待炒锅到投料位置。");
  530. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置。");
  531. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);//等待炒锅到投料位置
  532. await Task.Delay(400);
  533. device.FryingPanHome = false;
  534. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒锅到投料位置完成,等待机器人到投料位置。");
  535. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待机器人到投料位置。");
  536. robot.MaterialPouringRequest[index].Wait(Cts: TaskList[et].Cts); //等待机器人到投料位置
  537. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人到达投料位置完成,开始等待机器人投料完成。");
  538. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料。");
  539. //robot.AllowPourVegetables(et);//允许机器人开始投料
  540. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置允许机器人开始投料完成。");
  541. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-开始等待机器人投料完成。");
  542. robot.MaterialPouringComplete[index].Wait(Cts: TaskList[et].Cts); //等待机器人投料完成
  543. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人投料完成。");
  544. }
  545. else
  546. {
  547. MessageNotify.GetInstance.ShowDialog($"任务【{cd.Name}】查找辅料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】辅料,任务即将取消。", DialogType.Warning);
  548. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-查找辅料失败,未查找到【{fm.funcPars.ElementAt(0).Id}】辅料。任务取消。");
  549. TaskList[et].Cts.Cancel();
  550. }
  551. break;
  552. case EFunc.炒锅回原点位:
  553. device.FryingPanFeedingLoc = false;
  554. device.FryingPanHome = false;
  555. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回原点。");
  556. await Task.Delay(400);
  557. device.FryingPanHome = true;
  558. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅回原点完成,等待炒锅回原点。");
  559. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待回原点完成。");
  560. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  561. await Task.Delay(400);
  562. device.FryingPanHome = false;
  563. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅回原点完成。");
  564. break;
  565. case EFunc.出餐启动:
  566. device.DiningOutStart = false;
  567. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人取空盆。");
  568. robot.IsIdle.Wait(Cts: TaskList[et].Cts);
  569. //TODO:暂时修改,后期优化。
  570. while (!TaskList[et].Cts.IsCancellationRequested)
  571. {
  572. var emptyPanIndex = Array.FindIndex(otherDevice.BoxDetection, i => i == true);
  573. if (emptyPanIndex >= 0)
  574. {
  575. robot.RobotTaskControl((21 + emptyPanIndex).ToString(), et);//取空盆
  576. break;
  577. }
  578. await Task.Delay(3000);
  579. DeviceProcessLogShow("无空盆,请添加空盆!");
  580. }
  581. //robot.RobotTaskControl("21", et);//取空盆
  582. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置机器人取空盆完成,等待机器人到出菜位置。");
  583. robot.DiningOutRequest[index].Wait(Cts: TaskList[et].Cts);//等待机器人到出菜位置
  584. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-机器人已到出餐位置,出餐启动。");
  585. await Task.Delay(400);
  586. device.DiningOutStart = true;
  587. device.OutDinningSlowDownFlag.Wait(Cts: TaskList[et].Cts);
  588. robot.ModerateInPlace(et);
  589. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-到达出餐减速位。");
  590. device.OutDinningFinsh.Wait(Cts: TaskList[et].Cts);
  591. robot.DiningOutComplete(et);
  592. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-出餐完成。");
  593. //回到投料位置就复位。
  594. Thread.Sleep(50);
  595. device.FeedingLocFB.Wait(Cts: TaskList[et].Cts);
  596. await Task.Delay(400);
  597. device.DiningOutStart = false;
  598. break;
  599. case EFunc.炒锅清洗:
  600. device.FryingPanClear = false;
  601. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅清洗。");
  602. await Task.Delay(400);
  603. device.FryingPanClear = true;
  604. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅清洗已写入,等待炒锅清洗完成。");
  605. Thread.Sleep(500);
  606. device.CleanFinish.Wait(Cts: TaskList[et].Cts);
  607. await Task.Delay(400);
  608. device.FryingPanClear = false;
  609. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅清洗完成。");
  610. break;
  611. //该功能废弃,添加调料时,自动回到调料投料位置。
  612. //case EFunc.炒锅回调料投料位置:
  613. // device.FryingPanToSeasoningLoc = false;
  614. // //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置。");
  615. // await Task.Delay(400);
  616. // device.FryingPanToSeasoningLoc = true;
  617. // DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置炒锅到调料投料位置完成,等待回到调料投料位置。");
  618. // //回到投料位置就复位。
  619. // Thread.Sleep(50);
  620. // device.FeedingSeasoningLocFB.Wait(Cts: TaskList[et].Cts);
  621. // await Task.Delay(400);
  622. // device.FryingPanToSeasoningLoc = false;
  623. // DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅回到调料投料位置完成。");
  624. // break;
  625. case EFunc.去指定炒制位:
  626. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置去指定炒制位。");
  627. device.SetStirFryingLoc(fm.funcPars.ElementAt(0).ParValue.ToString(), TaskList[et].Cts);
  628. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-设置去指定炒制位【{fm.funcPars.ElementAt(0).ParValue.ToString()}】完成。");
  629. //TODO:根据情况看是否需要等待反馈变量。
  630. //device.StirFryingLocFB[int.Parse(fm.funcPars.ElementAt(0).ParValue.ToString())].Wait();
  631. //DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒锅到达炒制位【{fm.funcPars.ElementAt(0).ParValue.ToString()}】。");
  632. break;
  633. case EFunc.炒制:
  634. if (int.TryParse(fm.funcPars.ElementAt(0).ParValue.ToString(), out int time))
  635. {
  636. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-等待炒制【{time}】秒。");
  637. Task.Delay(time * 1000).Wait(TaskList[et].Cts.Token);
  638. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务执行-{fm.eFunc.ToString()}-炒制完成。");
  639. }
  640. break;
  641. default:
  642. break;
  643. }
  644. }
  645. catch (TaskCanceledException)
  646. {
  647. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务被取消。");
  648. }
  649. catch (OperationCanceledException)
  650. {
  651. DeviceProcessLogShow($"{cd.Name}-【{et}#】任务被手动取消。");
  652. }
  653. }
  654. }
  655. DeviceProcessLogShow($"【{et}】任务-{cd.Name} 执行完成");
  656. TaskList[et].IsComplete = true;
  657. }
  658. #endregion
  659. public override void ReadData()
  660. {
  661. if (propertyInfos is null || propertyInfos.Count==0)
  662. {
  663. propertyInfos = morkCL.GetType().GetProperties().ToList();
  664. }
  665. morkCL.RecipeQueueCount = morkCL.cds.Count;
  666. morkCL.FryingPanTaskCount_1 = morkCL.cds.Count(data => data.DeviceType == EDeviceType.炒锅1);
  667. morkCL.FryingPanTaskCount_2 = morkCL.cds.Count(data => data.DeviceType == EDeviceType.炒锅2);
  668. var fryingPan1 = (FryingPanServer)devices[EDeviceType.炒锅1];
  669. var fryingPan2 = (FryingPanServer)devices[EDeviceType.炒锅2];
  670. var robot = (RobotServer)devices[EDeviceType.机器人];
  671. var pressureCooker = (PressureCookerServer)devices[EDeviceType.压力锅];
  672. var otherDevice = (OtherServer)devices[EDeviceType.外部设备];
  673. alarm.EStop1 = fryingPan1.EStopAlarm;
  674. alarm.FryingPanFowardLimit1 = fryingPan1.FryingPanFowardLimit;
  675. alarm.FryingPanReverseLimit1 = fryingPan1.FryingPanReverseLimit;
  676. alarm.FryingPanEncoderCommError1 = fryingPan1.FryingPanEncoderCommError;
  677. alarm.StirMotorCommError1 = fryingPan1.StirMotorCommError;
  678. alarm.RollingMotorCommError1 = fryingPan1.RollingMotorCommError;
  679. alarm.StirMotorError1 = fryingPan1.StirMotorErrorCode != "无故障" ? true : false;
  680. alarm.TurnMotorError1 = fryingPan1.TurnMotorErrorCode != "无故障" ? true : false;
  681. alarm.EStop2 = fryingPan2.EStopAlarm;
  682. alarm.FryingPanFowardLimit2 = fryingPan2.FryingPanFowardLimit;
  683. alarm.FryingPanReverseLimit2 = fryingPan2.FryingPanReverseLimit;
  684. alarm.FryingPanEncoderCommError2 = fryingPan2.FryingPanEncoderCommError;
  685. alarm.StirMotorCommError2 = fryingPan2.StirMotorCommError;
  686. alarm.RollingMotorCommError2 = fryingPan2.RollingMotorCommError;
  687. alarm.StirMotorError2 = fryingPan2.StirMotorErrorCode != "无故障" ? true : false;
  688. alarm.TurnMotorError2 = fryingPan2.TurnMotorErrorCode != "无故障" ? true : false;
  689. //这是字段。直接赋值
  690. morkCL.FeedingSeasoningLocFB1 = fryingPan1.FeedingSeasoningLocFB;
  691. morkCL.FeedingSeasoningLocFB2 = fryingPan2.FeedingSeasoningLocFB;
  692. morkCL.FeedingLocFB1 = fryingPan1.FeedingLocFB;
  693. morkCL.FeedingLocFB2 = fryingPan2.FeedingLocFB;
  694. morkCL.CleanFinish1 = fryingPan1.CleanFinish;
  695. morkCL.CleanFinish2 = fryingPan2.CleanFinish;
  696. morkCL.OutDinningFinsh1 = fryingPan1.OutDinningFinsh;
  697. morkCL.OutDinningFinsh2 = fryingPan2.OutDinningFinsh;
  698. morkCL.OutDinningSlowDownFlag1 = fryingPan1.OutDinningSlowDownFlag;
  699. morkCL.OutDinningSlowDownFlag2 = fryingPan2.OutDinningSlowDownFlag;
  700. morkCL.BoxDetection = otherDevice.BoxDetection;
  701. morkCL.IsIdle = robot.IsIdle;
  702. #if !FORMAL
  703. if (fryingPan1.FeedingLocFB)
  704. {
  705. robot.AllowPourVegetables(EDeviceType.炒锅1);
  706. }
  707. else
  708. {
  709. robot.DisablePourVegetables(EDeviceType.炒锅1);
  710. }
  711. if (fryingPan2.FeedingLocFB)
  712. {
  713. robot.AllowPourVegetables(EDeviceType.炒锅2);
  714. }
  715. else
  716. {
  717. robot.DisablePourVegetables(EDeviceType.炒锅2);
  718. }
  719. foreach (var property in propertyInfos)
  720. {
  721. var att = property.GetCustomAttribute<VariableMonitorAttribute>();
  722. if (att != null)
  723. {
  724. if (att.Notes.Contains("1号炒锅"))
  725. {
  726. var p = fryingPan1.GetType().GetProperty(property.Name.TrimEnd('1'));
  727. if (p != null)
  728. {
  729. property.SetValue(morkCL, p.GetValue(fryingPan1));
  730. }
  731. }
  732. else if (att.Notes.Contains("2号炒锅"))
  733. {
  734. var p = fryingPan2.GetType().GetProperty(property.Name.TrimEnd('2'));
  735. if (p != null)
  736. {
  737. property.SetValue(morkCL, p.GetValue(fryingPan2));
  738. }
  739. }
  740. else if (att.Notes.Contains("机器人"))
  741. {
  742. var p = robot.GetType().GetProperty(property.Name);
  743. if (p != null)
  744. {
  745. property.SetValue(morkCL, p.GetValue(robot));
  746. }
  747. }
  748. else if (att.Notes.Contains("电子秤"))
  749. {
  750. var p = otherDevice.GetType().GetProperty(property.Name);
  751. if (p != null)
  752. {
  753. var res = p.GetValue(otherDevice);
  754. property.SetValue(morkCL, res);
  755. if (p.Name== "CurrentWeight")
  756. {
  757. ActionManage.GetInstance.Send("SendCurrentWeight", res);
  758. }
  759. }
  760. }
  761. else if (att.Notes.Contains("高压锅"))
  762. {
  763. var p = pressureCooker.GetType().GetProperty(property.Name);
  764. if (p != null)
  765. {
  766. property.SetValue(morkCL, p.GetValue(pressureCooker));
  767. }
  768. }
  769. }
  770. }
  771. #endif
  772. }
  773. public override void ResetProgram()
  774. {
  775. morkCL = null;
  776. morkCL = new GVL_MorkCL();
  777. }
  778. public override void SimOrder()
  779. {
  780. }
  781. public override void Stop()
  782. {
  783. }
  784. private bool GetFryPanAndRobotIsAuto(EDeviceType fryPan)
  785. {
  786. //目前拿不到机器人的远程状态,只能拿到炒锅的。
  787. var device = (FryingPanServer)devices[fryPan];
  788. var robot = (RobotServer)devices[EDeviceType.机器人];
  789. return device.InitComplete && device.StatusMode && device.EStop && robot.RemoteMode;
  790. }
  791. void ManualActionRegiester()
  792. {
  793. //主料入库委托。
  794. ActionManage.GetInstance.Register((object o) =>
  795. {
  796. if (!morkCL.CanItemStorage)
  797. {
  798. MessageNotify.GetInstance.ShowDialog("当前有炒菜任务正在排队,为避免影响菜品口味,不可入库,请稍后再试。", DialogType.Warning);
  799. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料入库失败,当前正在制作菜品。");
  800. return;
  801. }
  802. var robot = (RobotServer)devices[EDeviceType.机器人];
  803. if (robot.IsIdle==false)
  804. {
  805. MessageNotify.GetInstance.ShowDialog("当前机器人未在空闲状态,稍后再试。", DialogType.Warning);
  806. return;
  807. }
  808. TaskManage.GetInstance.Start(() =>
  809. {
  810. if (o != null && o is IngredientsTB ingredients)
  811. {
  812. var index = Array.FindIndex(Json<ItemStorageInfo>.Data.IngredientsStorage, i => i.IsEmploy == false);
  813. if (index >= 0)
  814. {
  815. if (!MessageNotify.GetInstance.ShowDialog($"请确认库位【{index+1}】上无物品,否则可能会造成碰撞事故!",DialogType.Warning))
  816. {
  817. DeviceProcessLogShow($"物料[{ingredients.Name}],ID:[{ingredients.Id}],库位[{index+1}]入库失败,未确认库位无异物。");
  818. Application.Current.Dispatcher.Invoke(() =>
  819. {
  820. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料{ingredients.Name}入库失败。");
  821. });
  822. return;
  823. }
  824. var item = Json<ItemStorageInfo>.Data.IngredientsStorage[index];
  825. item.MaterialID = ingredients.Id;
  826. item.Name = ingredients.Name;
  827. item.IsEmploy = true;
  828. item.Weight = ((OtherServer)devices[EDeviceType.外部设备]).CurrentWeight;
  829. var loc = (index + 1).ToString();
  830. #if !FORMAL
  831. robot.WarehousingControl(loc,null);
  832. DeviceProcessLogShow($"已下发机器人物料入{loc}号库任务,等待机器人入库操作完成");
  833. robot.WarehousingComplete[(Convert.ToInt32(loc) - 1)].Wait();
  834. #endif
  835. Json<ItemStorageInfo>.Save();
  836. ActionManage.GetInstance.Send("RefreshItemStorage");
  837. DeviceProcessLogShow($"物料[{ingredients.Name}],ID:[{ingredients.Id}],库位[{index + 1}]入库成功。");
  838. Application.Current.Dispatcher.Invoke(() =>
  839. {
  840. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "入库成功", $"物料{ingredients.Name}入库成功。");
  841. });
  842. return;
  843. }
  844. else
  845. {
  846. Application.Current.Dispatcher.Invoke(() =>
  847. {
  848. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料库已满。");
  849. });
  850. }
  851. }
  852. else
  853. {
  854. Application.Current.Dispatcher.Invoke(() =>
  855. {
  856. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "入库失败", $"物料入库失败。");
  857. });
  858. }
  859. }, "ItemStorageTask");
  860. }, NotifyTopic.ItemStorage, true);
  861. ActionManage.GetInstance.Register(() =>
  862. {
  863. if (ActionManage.GetInstance.SendResult("SystemIsBusy") is bool isBusy)
  864. {
  865. if (isBusy == true)
  866. {
  867. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "失败", $"当前还有配方任务在排队制作,请稍后后再试。");
  868. return;
  869. }
  870. Task.Run(() =>
  871. {
  872. var robot = (RobotServer)devices[EDeviceType.机器人];
  873. robot.GoCleanLoc();
  874. Application.Current.Dispatcher.Invoke(() =>
  875. {
  876. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "设置成功", $"设置机器人去清洗位置成功。");
  877. });
  878. });
  879. }
  880. }, "RobotGoCleanLoc", true);
  881. #region 暂时弃用
  882. ActionManage.GetInstance.Register((object location) =>
  883. {
  884. var loc = location.ToString();
  885. if (!String.IsNullOrEmpty(loc) && loc.Length >= 0)
  886. {
  887. var robot = (RobotServer)devices[EDeviceType.机器人];
  888. //Thread.Sleep(5000);
  889. robot.WarehousingControl(loc,null);
  890. //会卡死。
  891. robot.WarehousingComplete[(Convert.ToInt32(loc) - 1)].Wait();
  892. }
  893. }, "ItemStorage", true);
  894. #endregion
  895. ActionManage.GetInstance.Register((object[] o) =>
  896. {
  897. if (o is not null && o is object[] para)
  898. {
  899. var device =(EDeviceType)Enum.Parse(typeof(EDeviceType), para[0].ToString());
  900. var channelIndex = para[1].ToString();
  901. var demandValue = para[2].ToString();
  902. ((FryingPanServer)devices[device]).CuttingControl(channelIndex, demandValue,null);
  903. }
  904. },"DeviceCuttingControl",true);
  905. ActionManage.GetInstance.Register((object o) =>
  906. {
  907. if (o is not null)
  908. {
  909. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  910. if (TaskList.ContainsKey(device))
  911. {
  912. TaskList[device].Cts.Cancel();
  913. DeviceProcessLogShow($"取消{device}当前任务成功。");
  914. }
  915. else
  916. {
  917. DeviceProcessLogShow($"[{device}]当前无任务。");
  918. }
  919. }
  920. }, "CancelFryPanTask", true);
  921. ActionManage.GetInstance.Register((object o) =>
  922. {
  923. if (o is not null)
  924. {
  925. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  926. //TODO : 把所有属于该炒锅的任务全部删除。
  927. }
  928. }, "ClearFryPanTask", true);
  929. ActionManage.GetInstance.Register(() =>
  930. {
  931. //电子秤去皮
  932. var weghier = (OtherServer)devices[EDeviceType.外部设备];
  933. if (weghier.WeigherTare())
  934. {
  935. Application.Current.Dispatcher.Invoke(() =>
  936. {
  937. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "去皮成功", $"电子秤除皮操作成功。");
  938. });
  939. DeviceProcessLogShow($"电子秤除皮操作成功。");
  940. }
  941. else
  942. {
  943. Application.Current.Dispatcher.Invoke(() =>
  944. {
  945. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "去皮失败", $"电子秤除皮操作失败。");
  946. });
  947. DeviceProcessLogShow($"电子秤除皮操作失败。");
  948. }
  949. },"WeighrTare",true);
  950. ActionManage.GetInstance.Register(() =>
  951. {
  952. //电子秤置零
  953. var weghier = (OtherServer)devices[EDeviceType.外部设备];
  954. if (weghier.WeigherZero())
  955. {
  956. Application.Current.Dispatcher.Invoke(() =>
  957. {
  958. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "置零成功", $"电子秤置零操作成功。");
  959. });
  960. DeviceProcessLogShow($"电子秤置零操作成功。");
  961. }
  962. else
  963. {
  964. Application.Current.Dispatcher.Invoke(() =>
  965. {
  966. NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "置零失败", $"电子秤置零操作失败。");
  967. });
  968. DeviceProcessLogShow($"电子秤置零操作失败。");
  969. }
  970. }, "WeighrZero", true);
  971. ActionManage.GetInstance.Register((object o) =>
  972. {
  973. if (o != null && o is WriteModel<bool> write)
  974. {
  975. if (!TaskList.ContainsKey(write.DeviceType))
  976. {
  977. devices[write.DeviceType].WriteValue<bool>(write.Address, write.Value);
  978. DeviceProcessLogShow($"设备[{write.DeviceType}]--手动写入地址[{write.Address}],值[{write.Value}]");
  979. }
  980. //else
  981. //{
  982. // //MessageNotify.GetInstance.ShowDialog("当前有炒菜任务,不可手动操作,请稍后再试。", DialogType.Warning);
  983. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "操作失败", $"手动操作失败,当前正在制作菜品。");
  984. // return;
  985. //}
  986. }
  987. }, "WriteBool", true);
  988. ActionManage.GetInstance.Register((object o) =>
  989. {
  990. if (o != null && o is WriteModel<ushort> write)
  991. {
  992. if (!TaskList.ContainsKey(write.DeviceType))
  993. {
  994. devices[write.DeviceType].WriteValue<ushort>(write.Address, write.Value);
  995. DeviceProcessLogShow($"设备[{write.DeviceType}]--手动写入地址[{write.Address}],值[{write.Value}]");
  996. }
  997. //else
  998. //{
  999. // //MessageNotify.GetInstance.ShowDialog("当前有炒菜任务,不可手动操作,请稍后再试。", DialogType.Warning);
  1000. // NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "操作失败", $"手动操作失败,当前正在制作菜品。");
  1001. // return;
  1002. //}
  1003. }
  1004. }, "WriteUshort", true);
  1005. ActionManage.GetInstance.Register(frypanIsIdle, "GetDeviceIsIdle", true);
  1006. ActionManage.GetInstance.Register(() =>
  1007. {
  1008. var robot = (RobotServer)devices[EDeviceType.机器人];
  1009. if (robot.InitVariable())
  1010. {
  1011. Application.Current.Dispatcher.Invoke(() => { NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, Application.Current.MainWindow, "成功", $"复位所有由上位机下发至机器人的变量成功。"); });
  1012. DeviceProcessLogShow($"复位所有由上位机下发至机器人的变量成功。");
  1013. }
  1014. else
  1015. {
  1016. Application.Current.Dispatcher.Invoke(() => { NoticeDemoViewModel.OpenMsg(EnumPromptType.Error, Application.Current.MainWindow, "失败", $"复位所有由上位机下发至机器人的变量失败。"); });
  1017. DeviceProcessLogShow($"复位所有由上位机下发至机器人的变量失败。");
  1018. }
  1019. }, "InitRobotAllVar", true);
  1020. ActionManage.GetInstance.Register<Func<object>>(() =>
  1021. {
  1022. if (morkCL.RecipeQueueCount > 0 || morkCL.FryingPanTaskCount_1 > 0 || morkCL.FryingPanTaskCount_2 > 0)
  1023. {
  1024. return true;
  1025. }
  1026. return false;
  1027. },"SystemIsBusy",true);
  1028. }
  1029. Func<object, object> frypanIsIdle => (o) =>
  1030. {
  1031. if (o is not null)
  1032. {
  1033. var device = (EDeviceType)Enum.Parse(typeof(EDeviceType), o.ToString());
  1034. if (!TaskList.ContainsKey(device))
  1035. {
  1036. return true;
  1037. }
  1038. }
  1039. return false;
  1040. };
  1041. }
  1042. }