终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Control_MorkCL.cs 70 KiB

1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
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. }