终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Control_MorkCL.cs 70 KiB

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