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

Control_MorkF.cs 117 KiB

1年前
1年前
1年前
1年前
2年前
2年前
1年前
1年前
2年前
1年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
1年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
1年前
2年前
2年前
2年前
1年前
1年前
2年前
2年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
1年前
1年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
1年前
2年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
2年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
1年前
2年前
1年前
1年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
1年前
2年前
2年前
1年前
2年前
1年前
1年前
1年前
2年前
1年前
2年前
1年前
1年前
1年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
1年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
2年前
1年前
1年前
2年前
1年前
2年前
2年前
1年前
2年前
1年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033
  1. using BPA.Message;
  2. using System;
  3. using BPA.Message.Enum;
  4. using BPASmartClient.Device;
  5. using BPA.Helper;
  6. using BPASmartClient.Model;
  7. using BPASmartClient.Model.PLC;
  8. using BPA.Models;
  9. using BPASmartClient.Model.小炒机;
  10. using BPASmartClient.MorkF.Model;
  11. using System.Text;
  12. using System.Collections.Concurrent;
  13. using System.Windows.Documents;
  14. using BPASmartClient.Business;
  15. using Microsoft.CodeAnalysis;
  16. using BPASmartClient.MorkF.ViewModel;
  17. using BPASmartClient.ViewModel;
  18. using System.Windows;
  19. using static BPA.Helper.EventBus;
  20. namespace BPASmartClient.MorkF
  21. {
  22. public class Control_MorkF : BaseDevice
  23. {
  24. #region 常数定义
  25. /// <summary>
  26. /// while循环最大sleep次数
  27. /// </summary>
  28. private const int sleepCount = 20;
  29. /// <summary>
  30. /// while循环每次sleep时间
  31. /// </summary>
  32. private const int sleepTime = 500;
  33. /// <summary>
  34. /// 菜品库while循环最大sleep次数
  35. /// </summary>
  36. private const int materialSleepCount = 600;
  37. /// <summary>
  38. /// 菜品库while循环每次sleep时间
  39. /// </summary>
  40. private const int materialSleepTime = 100;
  41. /// <summary>
  42. /// 初始化炒锅数量
  43. /// </summary>
  44. private int count = 2;
  45. /// <summary>
  46. /// 菜品盒下移高度,相对于坐标系
  47. /// </summary>
  48. //private const int materialBoxHigh = 4080;
  49. ////菜品库出餐高度
  50. //private const int materialHigh = 33000;
  51. ////传感器到菜品库的高度(坐标系)
  52. //private const int materialLaserHigh = 34500;
  53. /// <summary>
  54. /// 菜品盒坐标系高度
  55. /// </summary>
  56. private const int materialBoxHeight = 9700;
  57. //传感器1到菜品库的高度(厘米)
  58. //private const int materialLaserHighCM_1 = 22;
  59. ////传感器2到菜品库的高度(厘米)
  60. //private const int materialLaserHighCM_2 = 27;
  61. ////传感器3到菜品库的高度(厘米)
  62. //private const int materialLaserHighCM_3 = 31;
  63. /// <summary>
  64. /// 传感器到隔板的距离(坐标系)
  65. /// </summary>
  66. private const int clapboardLaserHigh = 10000;
  67. ////炒锅1倒菜的xy坐标
  68. //private const int materialPutPositionXFry1 = 70000;
  69. //private const int materialPutPositionYFry1 = 40000;
  70. ////炒锅2倒菜的xy坐标
  71. //private const int materialPutPositionXFry2 = 70000;
  72. //private const int materialPutPositionYFry2 = 40000;
  73. //菜品库机械爪放置菜品距离
  74. private const int materialToFryDistance = 10000;
  75. //当前炒锅,默认为1号炒锅
  76. private int fryIndex = 0;
  77. #endregion
  78. public override DeviceClientType DeviceType => DeviceClientType.MORKCS;
  79. public AutoResetEvent minorReset = new AutoResetEvent(false);
  80. public AutoResetEvent mainReset = new AutoResetEvent(false);
  81. /// <summary>
  82. /// 等待炒制数量
  83. /// </summary>
  84. private int StagingFryCount { get; set; }
  85. /// <summary>
  86. /// 正在炒制数量
  87. /// </summary>
  88. private int FryingCount { get; set; }
  89. /// <summary>
  90. /// 炒锅编号与炒锅实例
  91. /// </summary>
  92. Dictionary<int, GVL_MorkF> morkFs = new Dictionary<int, GVL_MorkF>();//全局对象声明
  93. /// <summary>
  94. /// 菜品库对象
  95. /// </summary>
  96. ML_MorkF ml_morkf = new ML_MorkF();
  97. /// <summary>
  98. /// 小炒菜单集合
  99. /// </summary>f
  100. public static List<StirFryGoods> LocalstirFryGoods = new List<StirFryGoods>();
  101. /// <summary>
  102. /// 待炒小炒队列
  103. /// </summary>
  104. private ConcurrentQueue<OrderLocInfo> StirFryGoodsQuenes = new ConcurrentQueue<OrderLocInfo>();
  105. /// <summary>
  106. /// 炒锅炒制线程名称
  107. /// </summary>
  108. private const String striConst = "炒锅{0}炒制{1}线程";
  109. /// <summary>
  110. /// 当前炒制菜品
  111. /// </summary>
  112. private OrderLocInfo[] nowStirFryGood = new OrderLocInfo[2];
  113. /// <summary>
  114. /// 待取菜队列
  115. /// </summary>
  116. private ConcurrentQueue<MaterialOperation> materialOperationQuenes = new ConcurrentQueue<MaterialOperation>();
  117. List<int> resultorder = new List<int>();//调试变量
  118. /// <summary>
  119. /// 告警列表
  120. /// </summary>
  121. private List<BPA.Message.AlarmModel> alarmModel = new List<BPA.Message.AlarmModel>();
  122. /// <summary>
  123. ///
  124. /// </summary>
  125. private List<StatsModel> statsModels = new List<StatsModel>();
  126. /// <summary>
  127. /// 暂存使用菜品量
  128. /// </summary>
  129. private List<GoodBatchings> stagingGoodBatchings = new List<GoodBatchings>();
  130. /// <summary>
  131. /// 是否为本地炒菜模式,默认为联网的
  132. /// </summary>
  133. private bool isLocalFryingMode { get; set; } = true;
  134. /// <summary>
  135. /// 入口
  136. /// </summary>
  137. public override void DoMain()
  138. {
  139. IsHealth = true;
  140. for (int i = 0; i < count; i++)
  141. {
  142. morkFs.Add(i, new GVL_MorkF());
  143. }
  144. DataParse();//数据解析
  145. CommandRegist();//调试
  146. ServerInit();
  147. DeviceProcessLogShow("MORKF 设备初始化完成");
  148. ///初始化菜品库
  149. //FoodLibInit();
  150. Task2ReadMaterialData();
  151. ScreenDataServer();
  152. Json<MaterialAndFryingTime>.Read();
  153. //更新菜品余量
  154. UpdateMaterialSurplus();
  155. //读取坐标系
  156. MaterialCoordinate materialCoordinate = ReadMaterialCoordinate();
  157. if (materialCoordinate != null)
  158. {
  159. MaterialCoordinate.GetInstance.dicNoMaterialCoordinate = materialCoordinate.dicNoMaterialCoordinate;
  160. MaterialCoordinate.GetInstance.MLCoordinateList = materialCoordinate.MLCoordinateList;
  161. MaterialCoordinate.GetInstance.distance_1 = materialCoordinate.distance_1;
  162. MaterialCoordinate.GetInstance.distance_2 = materialCoordinate.distance_2;
  163. MaterialCoordinate.GetInstance.distance_3 = materialCoordinate.distance_3;
  164. MaterialCoordinate.GetInstance.frying1 = materialCoordinate.frying1;
  165. MaterialCoordinate.GetInstance.frying2 = materialCoordinate.frying2;
  166. MaterialCoordinate.GetInstance.materialHeight = materialCoordinate.materialHeight;
  167. MaterialCoordinate.GetInstance.MaterialOneX = materialCoordinate.MaterialOneX;
  168. MaterialCoordinate.GetInstance.MaterialTwoX = materialCoordinate.MaterialTwoX;
  169. MaterialCoordinate.GetInstance.MaterialThreeX = materialCoordinate.MaterialThreeX;
  170. }
  171. ////菜品库编号与坐标系对象存储
  172. //SaveMaterialCoordinate();
  173. }
  174. /// <summary>
  175. /// 主任务
  176. /// </summary>
  177. public override void MainTask()
  178. {
  179. //炒锅炒制线程
  180. MainProcessExcute();
  181. //菜品库操作线程
  182. MainProcessMaterial();
  183. //MinorProcessExcute();
  184. //SingleProcess();
  185. }
  186. private static object saveMaterialLock = new object();
  187. private void SaveMaterialData()
  188. {
  189. lock (saveMaterialLock)
  190. {
  191. Json<MaterialSurplus>.Data = MaterialSurplusOperation.GetInstance.materialSurplus;
  192. Json<MaterialSurplus>.Save();
  193. }
  194. }
  195. private static object saveMaterialCoordinateLock = new object();
  196. /// <summary>
  197. /// 保存当前的坐标系
  198. /// </summary>
  199. public void SaveMaterialCoordinate()
  200. {
  201. lock (saveMaterialLock)
  202. {
  203. Json<MaterialCoordinate>.Data = MaterialCoordinate.GetInstance;
  204. Json<MaterialCoordinate>.Save();
  205. }
  206. }
  207. /// <summary>
  208. /// 读取坐标系
  209. /// </summary>
  210. /// <returns></returns>
  211. private MaterialCoordinate ReadMaterialCoordinate()
  212. {
  213. try
  214. {
  215. lock (saveMaterialLock)
  216. {
  217. Json<MaterialCoordinate>.Read();
  218. MaterialCoordinate materialCoordinate = Json<MaterialCoordinate>.Data;
  219. return materialCoordinate;
  220. }
  221. }
  222. catch (Exception ex)
  223. {
  224. return null;
  225. }
  226. }
  227. private void Task2ReadMaterialData()
  228. {
  229. TaskManage.GetInstance.StartLong(new Action(() =>
  230. {
  231. //获取定位到达状态
  232. GetStatus("M10.0", new Action<object>((objects) =>
  233. {
  234. if (objects is bool[] bools)
  235. {
  236. //ml_morkf.ArriveComplete = bools[i];
  237. //小炒定点到达上升沿信号捕获
  238. if (RTrig.GetInstance("SmartArriveComplete").Start(bools[0]))
  239. {
  240. if (isInitialArrive == false)
  241. {
  242. //MessageLog.GetInstance.Show("到达上升沿为true,isInitialArrive is false");
  243. isInitialArrive = true;
  244. }
  245. else
  246. {
  247. //MessageLog.GetInstance.Show("到达上升沿为true");
  248. ml_morkf.ArriveComplete = true;
  249. isInitialArrive = true;
  250. }
  251. }
  252. }
  253. }), 2);
  254. }), "ReadMaterialSmartArriveCompleteData", true);
  255. TaskManage.GetInstance.StartLong(new Action(() =>
  256. {
  257. ReadMaterialData();
  258. Thread.Sleep(10);
  259. }), "ReadMaterialData", true);
  260. }
  261. private void ReadMaterialData()
  262. {
  263. //获取激光距离
  264. GetStatus("VW270", new Action<object>((objects) =>
  265. {
  266. if (objects is ushort[] bools)
  267. {
  268. for (int i = 0; i < 1; i++)
  269. {
  270. ml_morkf.LaserDistance = bools[i];
  271. }
  272. }
  273. }), 2);
  274. //获取坐标X
  275. GetStatus("VD828", new Action<object>((objects) =>
  276. {
  277. if (objects is int bools)
  278. {
  279. ml_morkf.ArmPositionX = bools;
  280. }
  281. }), 2);
  282. //获取坐标Y
  283. GetStatus("VD832", new Action<object>((objects) =>
  284. {
  285. if (objects is int bools)
  286. {
  287. ml_morkf.ArmPositionY = bools;
  288. }
  289. }), 2);
  290. //获取爪子到达位置
  291. GetStatus("M11.0", new Action<object>((objects) =>
  292. {
  293. if (objects is bool[] bools && bools.Length > 3)
  294. {
  295. ml_morkf.PawArrivePortOne = bools[0];
  296. ml_morkf.PawArrivePortTwo = bools[1];
  297. ml_morkf.PawArrivePortThree = bools[2];
  298. }
  299. }), 2);
  300. //获取爪子伸出退回到位
  301. GetStatus("M10.6", new Action<object>((objects) =>
  302. {
  303. if (objects is bool[] bools && bools.Length == 2)
  304. {
  305. ml_morkf.PawOutComplete = bools[0];
  306. ml_morkf.PawInComplete = bools[1];
  307. }
  308. }), 2);
  309. //获取总初始化完成
  310. GetStatus("M10.2", new Action<object>((objects) =>
  311. {
  312. if (objects is bool[] bools)
  313. {
  314. for (int i = 0; i < 1; i++)
  315. {
  316. ml_morkf.InitialComplete = bools[i];
  317. }
  318. }
  319. }), 2);
  320. //抓手初始化完成
  321. GetStatus("M10.3", new Action<object>((objects) =>
  322. {
  323. if (objects is bool[] bools)
  324. {
  325. for (int i = 0; i < 1; i++)
  326. {
  327. ml_morkf.PawInitialComplete = bools[i];
  328. }
  329. }
  330. }), 2);
  331. //抓手初始化完成
  332. GetStatus("I0.1", new Action<object>((objects) =>
  333. {
  334. if (objects is bool[] bools && bools.Length > 2)
  335. {
  336. ml_morkf.PawPositon_1 = bools[0];
  337. ml_morkf.PawPositon_2 = bools[1];
  338. ml_morkf.PawPositon_3 = bools[2];
  339. }
  340. }), 2);
  341. }
  342. public override void Stop()
  343. {
  344. IsHealth = false;
  345. }
  346. #region 调试代码
  347. public void CommandRegist()
  348. {
  349. #region 设备控制
  350. ActionManage.GetInstance.Register(PLCInite, "InitCommand");
  351. ActionManage.GetInstance.Register<object>(StartOrder, "StartOrder");
  352. ActionManage.GetInstance.Register<object>(StartOrderMain, "开始下单");
  353. ActionManage.GetInstance.Register<int>(StopLocalOrder, "StopLocalOrder");
  354. ActionManage.GetInstance.Register(new Action<object>((o) =>
  355. {
  356. if (o is string materialName)
  357. {
  358. NewStartLocalOrder(materialName);
  359. }
  360. }), "NewStartLocalOrder");
  361. #endregion
  362. #region 菜品库
  363. ActionManage.GetInstance.Register(new Action(() =>
  364. {
  365. TaskManage.GetInstance.Start(new Action(() =>
  366. {
  367. FoodLibInit();
  368. }), "FoodLibInit");
  369. }), "FoodLibInit");
  370. ActionManage.GetInstance.Register(new Action(() =>
  371. {
  372. isLocalFryingMode = !isLocalFryingMode;
  373. }), "ModeChange");
  374. ActionManage.GetInstance.Register(new Action(() =>
  375. {
  376. TaskManage.GetInstance.Start(new Action(() =>
  377. {
  378. if (!UpdateMaterialLibraryStock())
  379. {
  380. MessageLog.GetInstance.ShowEx("菜品库检测余量失败");
  381. }
  382. }), "SurplusCheck");
  383. }), "SurplusCheck");
  384. ActionManage.GetInstance.Register(new Action<object>((o) =>
  385. {
  386. TaskManage.GetInstance.Start(new Action(() =>
  387. {
  388. Electromagnetism(o);
  389. }), "Electromagnetism");
  390. }), "Electromagnetism");
  391. ActionManage.GetInstance.Register(new Action(() =>
  392. {
  393. TaskManage.GetInstance.Start(new Action(() =>
  394. {
  395. PawToPoint1();
  396. }), "PawToPoint1");
  397. }), "PawToPoint1");
  398. ActionManage.GetInstance.Register(new Action(() =>
  399. {
  400. TaskManage.GetInstance.Start(new Action(() =>
  401. {
  402. PawToPoint2();
  403. }), "PawToPoint2");
  404. }), "PawToPoint2");
  405. ActionManage.GetInstance.Register(new Action(() =>
  406. {
  407. TaskManage.GetInstance.Start(new Action(() =>
  408. {
  409. PawToPoint3();
  410. }), "PawToPoint3");
  411. }), "PawToPoint3");
  412. ActionManage.GetInstance.Register(new Action(() =>
  413. {
  414. TaskManage.GetInstance.Start(new Action(() =>
  415. {
  416. GetDistance_1();
  417. }), "GetDistance_1");
  418. }), "GetDistance_1");
  419. ActionManage.GetInstance.Register(new Action(() =>
  420. {
  421. TaskManage.GetInstance.Start(new Action(() =>
  422. {
  423. GetDistance_2();
  424. }), "GetDistance_2");
  425. }), "GetDistance_2");
  426. ActionManage.GetInstance.Register(new Action(() =>
  427. {
  428. TaskManage.GetInstance.Start(new Action(() =>
  429. {
  430. GetDistance_3();
  431. }), "GetDistance_3");
  432. }), "GetDistance_3");
  433. ActionManage.GetInstance.Register(new Action(() =>
  434. {
  435. TaskManage.GetInstance.Start(new Action(() =>
  436. {
  437. PawExtend();
  438. }), "PawTurnFront");
  439. }), "PawTurnFront");
  440. ActionManage.GetInstance.Register(new Action(() =>
  441. {
  442. TaskManage.GetInstance.Start(new Action(() =>
  443. {
  444. PawShrink();
  445. }), "PawTurnBack");
  446. }), "PawTurnBack");
  447. ActionManage.GetInstance.Register(new Action<object>((list) =>
  448. {
  449. TaskManage.GetInstance.Start(new Action(() =>
  450. {
  451. if (list is List<int> list_int)
  452. {
  453. if (list_int.Count == 2)
  454. {
  455. SetArmPosition(list_int[0], list_int[1]);
  456. }
  457. }
  458. }), "SetArmPosition");
  459. }), "SetArmPosition");
  460. ActionManage.GetInstance.Register(new Action<object>((list) =>
  461. {
  462. if (list is bool startOrStop)
  463. {
  464. ArmRunUp(startOrStop);
  465. }
  466. }), "ArmRunUp");
  467. ActionManage.GetInstance.Register(new Action<object>((list) =>
  468. {
  469. if (list is bool startOrStop)
  470. {
  471. ArmRunDown(startOrStop);
  472. }
  473. }), "ArmRunDown");
  474. ActionManage.GetInstance.Register(new Action<object>((list) =>
  475. {
  476. if (list is bool startOrStop)
  477. {
  478. ArmRunLeft(startOrStop);
  479. }
  480. }), "ArmRunLeft");
  481. ActionManage.GetInstance.Register(new Action<object>((list) =>
  482. {
  483. if (list is bool startOrStop)
  484. {
  485. ArmRunRight(startOrStop);
  486. }
  487. }), "ArmRunRight");
  488. ActionManage.GetInstance.Register(new Action<object>((list) =>
  489. {
  490. TaskManage.GetInstance.Start(new Action(() =>
  491. {
  492. if (list is List<int> list_int)
  493. {
  494. if (list_int.Count == 2)
  495. {
  496. SetArmPosition(list_int[0], list_int[1]);
  497. }
  498. }
  499. }), "SetNowPosition");
  500. }), "SetNowPosition");
  501. ActionManage.GetInstance.Register(new Action<object>((list) =>
  502. {
  503. TaskManage.GetInstance.Start(new Action(() =>
  504. {
  505. if (list is List<object> list_object)
  506. {
  507. if (list_object.Count != 3)
  508. {
  509. return;
  510. }
  511. if (list_object[0] is string No && list_object[1] is int x && list_object[2] is int y)
  512. {
  513. if (SetArmPosition(x, y))
  514. {
  515. ActionManage.GetInstance.Send(new List<string> { No }, "CalibrationCallBack");//设定机械臂当前位置
  516. }
  517. }
  518. }
  519. }), "CalibrationCoordination");
  520. }), "CalibrationCoordination");
  521. #endregion
  522. //ActionManage.GetInstance.Register(PLCInite, "InitCommand");
  523. #region 配料控制
  524. ActionManage.GetInstance.Register(new Action<object>((o) =>
  525. {
  526. TaskManage.GetInstance.Start(new Action(() =>
  527. {
  528. OutSeasoning(o, fryIndex);
  529. }), "OutMaterials");
  530. }), "OutMaterials");
  531. //ActionManage.GetInstance.Register(OutSeasoning, "OutMaterials");
  532. #endregion
  533. #region 炒锅
  534. ActionManage.GetInstance.Register(new Action(() =>
  535. {
  536. TaskManage.GetInstance.Start(new Action(() =>
  537. {
  538. Plc1Reset(fryIndex);
  539. }), "Plc1Reset");
  540. }), "Plc1Reset");
  541. ActionManage.GetInstance.Register(new Action(() =>
  542. {
  543. TaskManage.GetInstance.Start(new Action(() =>
  544. {
  545. AddOil();
  546. }), "AddOil");
  547. }), "AddOil");
  548. ActionManage.GetInstance.Register(new Action(() =>
  549. {
  550. TaskManage.GetInstance.Start(new Action(() =>
  551. {
  552. StartFire(fryIndex);
  553. }), "StartFire");
  554. }), "StartFire");
  555. ActionManage.GetInstance.Register(new Action(() =>
  556. {
  557. TaskManage.GetInstance.Start(new Action(() =>
  558. {
  559. StopFire(fryIndex);
  560. }), "StopFire");
  561. }), "StopFire");
  562. ActionManage.GetInstance.Register(new Action(() =>
  563. {
  564. TaskManage.GetInstance.Start(new Action(() =>
  565. {
  566. StartStir(fryIndex);
  567. }), "StartStir");
  568. }), "StartStir");
  569. ActionManage.GetInstance.Register(new Action(() =>
  570. {
  571. TaskManage.GetInstance.Start(new Action(() =>
  572. {
  573. StopStir(fryIndex);
  574. }), "StopStir");
  575. }), "StopStir");
  576. ActionManage.GetInstance.Register(new Action(() =>
  577. {
  578. TaskManage.GetInstance.Start(new Action(() =>
  579. {
  580. MagnetOn(fryIndex);
  581. }), "MagnetOn");
  582. }), "MagnetOn");
  583. ActionManage.GetInstance.Register(new Action(() =>
  584. {
  585. TaskManage.GetInstance.Start(new Action(() =>
  586. {
  587. MagnetOff(fryIndex);
  588. }), "MagnetOff");
  589. }), "MagnetOff");
  590. ActionManage.GetInstance.Register(new Action(() =>
  591. {
  592. TaskManage.GetInstance.Start(new Action(() =>
  593. {
  594. string error;
  595. OutFood(fryIndex, out error);
  596. }), "OutFood");
  597. }), "OutFood");
  598. ActionManage.GetInstance.Register(new Action(() =>
  599. {
  600. TaskManage.GetInstance.Start(new Action(() =>
  601. {
  602. StirArmGoOrigin(fryIndex);
  603. }), "StirArmGoOrigin");
  604. }), "StirArmGoOrigin");
  605. ActionManage.GetInstance.Register(new Action(() =>
  606. {
  607. TaskManage.GetInstance.Start(new Action(() =>
  608. {
  609. string error;
  610. StirArmGoWork(fryIndex, out error);
  611. }), "StirArmGoWork");
  612. }), "StirArmGoWork");
  613. ActionManage.GetInstance.Register(new Action(() =>
  614. {
  615. TaskManage.GetInstance.Start(new Action(() =>
  616. {
  617. HBOTGoWork(fryIndex);
  618. }), "HBOTGoWork");
  619. }), "HBOTGoWork");
  620. ActionManage.GetInstance.Register(new Action(() =>
  621. {
  622. TaskManage.GetInstance.Start(new Action(() =>
  623. {
  624. OutMeal(fryIndex);
  625. }), "OutMeal");
  626. }), "OutMeal");
  627. ActionManage.GetInstance.Register(new Action<object>((o) =>
  628. {
  629. TaskManage.GetInstance.Start(new Action(() =>
  630. {
  631. SetFire(o, fryIndex);
  632. }), "SetFire");
  633. }), "SetFire");
  634. ActionManage.GetInstance.Register(new Action<object>((o) =>
  635. {
  636. TaskManage.GetInstance.Start(new Action(() =>
  637. {
  638. SetFry(o);
  639. }), "SetFry");
  640. }), "SetFry");
  641. ActionManage.GetInstance.Register(new Action<object>((o) =>
  642. {
  643. TaskManage.GetInstance.Start(new Action(() =>
  644. {
  645. SetStir(o, fryIndex);
  646. }), "SetStir");
  647. }), "SetStir");
  648. #endregion
  649. }
  650. /// <summary>
  651. /// 根据菜品ID下单
  652. /// </summary>
  653. private void StartOrder(object o)
  654. {
  655. if (o == null) return;
  656. if (o is int goodId)
  657. {
  658. var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey == goodId);//匹配订单对应制作流程
  659. if (res != null)
  660. {
  661. /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  662. if (StirFryGoodsQuenes.Count > 0) return;
  663. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  664. {
  665. SuborderId = Guid.NewGuid().ToString(),
  666. StirPotActions = res.StirPotActions,
  667. GoodName = "本地菜品"
  668. });
  669. MessageLog.GetInstance.Show($"添加本地订单{res.GoodsKey}");
  670. }
  671. }
  672. }
  673. /// <summary>
  674. /// 主界面本地菜单下单
  675. /// </summary>
  676. private void StartOrderMain(object o)
  677. {
  678. if (o == null) return;
  679. //if (o is FoodMenuModel good)
  680. //{
  681. // NewStartLocalOrder(good.GoodName);
  682. //}
  683. //if (o == null) return;
  684. //if (o is string goodId)
  685. //{
  686. // var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey.ToString() == goodId);//匹配订单对应制作流程
  687. // if (res != null)
  688. // {
  689. // /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  690. // if (StirFryGoodsQuenes.Count > 0) return;
  691. // StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  692. // {
  693. // SuborderId = Guid.NewGuid().ToString(),
  694. // StirPotActions = res.StirPotActions,
  695. // GoodName = "本地菜品"
  696. // });
  697. // MessageLog.GetInstance.Show($"添加本地订单{res.GoodsKey}");
  698. // }
  699. //}
  700. }
  701. /// <summary>
  702. /// 本地配置的订单
  703. /// </summary>
  704. /// <param name="materialName"></param>
  705. private void NewStartLocalOrder(string materialName)
  706. {
  707. //if (StirFryGoodsQuenes.Count > 0) return;//只能一个一个做
  708. //if (Json<LocalPotStep>.Data.LocalstirFryGoods.StirPotActions.Count > 0)
  709. //{
  710. // StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  711. // {
  712. // SuborderId = Guid.NewGuid().ToString(),
  713. // StirPotActions = Json<LocalPotStep>.Data.LocalstirFryGoods.StirPotActions,
  714. // GoodName = "本地菜品"
  715. // });
  716. // MessageLog.GetInstance.Show($"添加本地模拟的订单{Json<LocalPotStep>.Data.LocalstirFryGoods.GoodsKey}");
  717. //}
  718. if (Json<MaterialAndFryingTime>.Data.materials.Count > 0)
  719. {
  720. if (!Json<MaterialAndFryingTime>.Data.materials.ContainsKey(materialName))
  721. {
  722. return;
  723. }
  724. List<PotActions> potActions = new List<PotActions>();
  725. foreach (var item in Json<MaterialAndFryingTime>.Data.materials[materialName])
  726. {
  727. potActions.Add(item);
  728. }
  729. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  730. {
  731. SuborderId = Guid.NewGuid().ToString(),
  732. StirPotActions = potActions,
  733. GoodName = materialName
  734. });
  735. MessageLog.GetInstance.Show($"添加本地模拟的订单{Json<LocalPotStep>.Data.LocalstirFryGoods.GoodsKey}");
  736. MessageBox.Show("下单成功");
  737. }
  738. }
  739. /// <summary>
  740. /// 停止本地菜单炒制
  741. /// </summary>
  742. private void StopLocalOrder(int num = -1)
  743. {
  744. //判断当前是否有炒制菜品
  745. if (nowStirFryGood == null) return;
  746. //根据morkFs中是否有num执行不同的停止操作
  747. if (!morkFs.ContainsKey(num))
  748. {
  749. //根据调试界面的当前炒锅编号停止炒制线程
  750. TaskManage.GetInstance.StopTask(String.Format(striConst, fryIndex.ToString(), nowStirFryGood[fryIndex].GoodName), new Action(() => { Plc1Reset(fryIndex); }));
  751. }
  752. else
  753. {
  754. //根据炒锅编号停止炒制线程
  755. TaskManage.GetInstance.StopTask(String.Format(striConst, fryIndex.ToString(), nowStirFryGood[num].GoodName), new Action(() => { Plc1Reset(num); }));
  756. }
  757. }
  758. /// <summary>
  759. /// 重置程序
  760. /// </summary>
  761. public override void ResetProgram()
  762. {
  763. IsHealth = true;
  764. morkFs.Clear();
  765. morkFs = new Dictionary<int, GVL_MorkF>();
  766. ml_morkf = new ML_MorkF();
  767. //根据编号new炒锅实例对象
  768. for (int i = 0; i < count; i++)
  769. {
  770. morkFs.Add(i, new GVL_MorkF());
  771. }
  772. }
  773. #endregion
  774. #region 公用PLC方法
  775. /// <summary>
  776. /// 获取设备PLC的所有状态
  777. /// </summary>
  778. /// <param name="key"></param>
  779. /// <param name="action"></param>
  780. /// <param name="num">炒锅编号</param>
  781. private void GetStatus(string key, Action<object> action, int num)
  782. {
  783. if (dicPort2peripheralStatus.ContainsKey(num))
  784. {
  785. if (dicPort2peripheralStatus[num].ContainsKey(key))
  786. {
  787. action((object)dicPort2peripheralStatus[num][key]);//获取PLC指定地址的状态值
  788. }
  789. }
  790. }
  791. /// <summary>
  792. /// PLC数据读取
  793. /// </summary>
  794. public override void ReadData()
  795. {
  796. for (int i = 0; i < morkFs.Count; i++)
  797. {
  798. GetStatus("LB50", new Action<object>((objects) =>
  799. {
  800. if (!morkFs.ContainsKey(i))
  801. {
  802. return;
  803. }
  804. if (objects is bool[] bools)
  805. {
  806. morkFs[i].FryPot1_InitialComplete = bools[0];
  807. morkFs[i].FryPot1_HOBTPut = bools[1];
  808. morkFs[i].FryPot1_HOBTGet = bools[2];
  809. morkFs[i].FryPot1_MaterialIntoPot = bools[3];
  810. morkFs[i].OutFoodCompelete = bools[4];
  811. morkFs[i].CanOutFood = bools[5];
  812. morkFs[i].GetFoodCompelete = bools[6];
  813. morkFs[i].CanOutPotWashingWater = bools[7];
  814. morkFs[i].ArmOnOrigin = bools[8];
  815. morkFs[i].ArmOnWorking = bools[9];
  816. morkFs[i].PotOnOrigin = bools[10];
  817. }
  818. }), i);
  819. }
  820. for (int j = 0; j < morkFs.Count; j++)
  821. {
  822. GetStatus("LB74", new Action<object>((objects) =>
  823. {
  824. if (!morkFs.ContainsKey(j))
  825. {
  826. return;
  827. }
  828. if (objects is bool[] bools)
  829. {
  830. for (int i = 0; i < 14; i++)
  831. {
  832. morkFs[j].PassWay1_Compelete[i] = bools[i];
  833. }
  834. }
  835. }), j);
  836. }
  837. for (int i = 0; i < morkFs.Count; i++)
  838. {
  839. if (!morkFs.ContainsKey(i))
  840. {
  841. return;
  842. }
  843. GetStatus("LB90", new Action<object>((objects) =>
  844. {
  845. if (objects is bool[] bools)
  846. {
  847. morkFs[i].AutoMode = bools[0];
  848. }
  849. }), i);
  850. }
  851. }
  852. #endregion
  853. #region 菜品库方法
  854. #region PLC操作
  855. /// <summary>
  856. /// 菜品库数据写入
  857. /// </summary>
  858. /// <param name="address"></param>
  859. /// <param name="value"></param>
  860. private void MaterailLibrary_Write(string address, object value, int num = 2)
  861. {
  862. WriteControlExact(address, value, num);
  863. }
  864. /// <summary>
  865. /// 菜品库初始化
  866. /// </summary>
  867. public bool FoodLibInit()
  868. {
  869. MaterailLibrary_Write("M0.2", true);
  870. Thread.Sleep(500);
  871. for (int i = 0; i < materialSleepCount && !ml_morkf.InitialComplete; i++)
  872. {
  873. Thread.Sleep(materialSleepTime);
  874. if (i >= materialSleepCount - 1)
  875. {
  876. MessageLog.GetInstance.ShowEx("菜品库初始化超时");
  877. return false;
  878. }
  879. }
  880. return true;
  881. }
  882. /// <summary>
  883. /// 爪子伸出
  884. /// </summary>
  885. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  886. public bool PawExtend()
  887. {
  888. if (!ml_morkf.InitialComplete)
  889. {
  890. MessageLog.GetInstance.ShowEx("爪子伸出错误,菜品库未初始化");
  891. return false;
  892. }
  893. Thread.Sleep(500);
  894. MaterailLibrary_Write("M0.6", true);
  895. for (int i = 0; i < materialSleepCount && !ml_morkf.PawOutComplete; i++)//潘华小炒没有夹爪到位功能
  896. {
  897. Thread.Sleep(materialSleepTime);
  898. if (i >= materialSleepCount - 1)
  899. {
  900. MessageLog.GetInstance.ShowEx("爪子伸出超时");
  901. return false;
  902. }
  903. }
  904. return true;
  905. ////等待爪子伸出延时4s
  906. //Thread.Sleep(6000);
  907. }
  908. /// <summary>
  909. /// 爪子收缩
  910. /// </summary>
  911. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  912. public bool PawShrink()
  913. {
  914. if (!ml_morkf.InitialComplete)
  915. {
  916. MessageLog.GetInstance.ShowEx("爪子伸出错误,菜品库未初始化");
  917. return false;
  918. }
  919. MaterailLibrary_Write("M0.7", true);
  920. Thread.Sleep(500);
  921. for (int i = 0; i < materialSleepCount && !ml_morkf.PawInComplete; i++)//潘华小炒没有夹爪到位功能
  922. {
  923. Thread.Sleep(materialSleepTime);
  924. if (i >= materialSleepCount - 1)
  925. {
  926. MessageLog.GetInstance.ShowEx("爪子伸出超时");
  927. return false;
  928. }
  929. }
  930. return true;
  931. //等待爪子收缩延时4s
  932. //Thread.Sleep(6000);
  933. }
  934. /// <summary>
  935. /// 电磁阀启停
  936. /// </summary>
  937. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  938. public void Electromagnetism(object o)
  939. {
  940. if (!ml_morkf.InitialComplete)
  941. {
  942. MessageLog.GetInstance.ShowEx("电磁阀启停出错,菜品库未初始化");
  943. return;
  944. }
  945. if (o == null) return;
  946. if (o is List<bool> bs && bs.Count == 1)
  947. {
  948. MaterailLibrary_Write("M1.3", bs[0]);
  949. }
  950. }
  951. public bool PawToPoint1()
  952. {
  953. if (!ml_morkf.InitialComplete)
  954. {
  955. MessageLog.GetInstance.ShowEx("爪子去到1号位出错,菜品库未初始化");
  956. return false;
  957. }
  958. //MessageLog.GetInstance.Show("爪子去到1号位");
  959. MaterailLibrary_Write("M1.0", true);
  960. Thread.Sleep(500);
  961. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortOne; i++)
  962. {
  963. Thread.Sleep(materialSleepTime);
  964. if (i >= materialSleepCount - 1)
  965. {
  966. if (i == 10)
  967. {
  968. MaterailLibrary_Write("M1.0", true);
  969. }
  970. MessageLog.GetInstance.ShowEx("爪子去到1号位超时");
  971. return false;
  972. }
  973. }
  974. Thread.Sleep(300);
  975. //MessageLog.GetInstance.Show("爪子去到1号位完成");
  976. return true;
  977. }
  978. public bool PawToPoint2()
  979. {
  980. if (!ml_morkf.InitialComplete)
  981. {
  982. MessageLog.GetInstance.ShowEx("爪子去到2号位出错,菜品库未初始化");
  983. return false;
  984. }
  985. MaterailLibrary_Write("M1.1", true);
  986. //MessageLog.GetInstance.Show("爪子去到2号位");
  987. Thread.Sleep(500);
  988. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortTwo; i++)
  989. {
  990. Thread.Sleep(materialSleepTime);
  991. if (i >= materialSleepCount - 1)
  992. {
  993. if (i == 10)
  994. {
  995. MaterailLibrary_Write("M1.1", true);
  996. }
  997. MessageLog.GetInstance.ShowEx("爪子去到2号位超时");
  998. return false;
  999. }
  1000. }
  1001. Thread.Sleep(300);
  1002. //MessageLog.GetInstance.Show("爪子去到2号位完成");
  1003. return true;
  1004. }
  1005. public bool PawToPoint3()
  1006. {
  1007. if (!ml_morkf.InitialComplete)
  1008. {
  1009. MessageLog.GetInstance.ShowEx("爪子去到3号位出错,菜品库未初始化");
  1010. return false;
  1011. }
  1012. //MessageLog.GetInstance.Show("爪子去到3号位");
  1013. MaterailLibrary_Write("M1.2", true);
  1014. Thread.Sleep(500);
  1015. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortThree; i++)
  1016. {
  1017. Thread.Sleep(materialSleepTime);
  1018. if (i == 30)
  1019. {
  1020. MaterailLibrary_Write("M1.2", true);
  1021. }
  1022. if (i >= materialSleepCount - 1)
  1023. {
  1024. MessageLog.GetInstance.ShowEx("爪子去到3号位超时");
  1025. }
  1026. }
  1027. if (!ml_morkf.PawPositon_3)
  1028. {
  1029. MaterailLibrary_Write("M1.2", true);
  1030. Thread.Sleep(3000);
  1031. }
  1032. Thread.Sleep(300);
  1033. //MessageLog.GetInstance.Show("爪子去到3号位完成");
  1034. return true;
  1035. }
  1036. public bool GetDistance_1()
  1037. {
  1038. if (!ml_morkf.InitialComplete)
  1039. {
  1040. MessageLog.GetInstance.ShowEx("1号测距出错,菜品库未初始化");
  1041. return false;
  1042. }
  1043. MaterailLibrary_Write("M0.3", true);
  1044. MaterailLibrary_Write("M0.3", false);
  1045. Thread.Sleep(3000);
  1046. //MessageLog.GetInstance.Show("1号测距开启完成");
  1047. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1048. ActionManage.GetInstance.Send(new List<string> { "1", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1049. return true;
  1050. }
  1051. public bool GetDistance_2()
  1052. {
  1053. if (!ml_morkf.InitialComplete)
  1054. {
  1055. MessageLog.GetInstance.ShowEx("2号测距出错,菜品库未初始化");
  1056. return false;
  1057. }
  1058. MaterailLibrary_Write("M0.4", true);
  1059. MaterailLibrary_Write("M0.4", false);
  1060. Thread.Sleep(3000);
  1061. //MessageLog.GetInstance.Show("2号测距开启完成");
  1062. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1063. ActionManage.GetInstance.Send(new List<string> { "2", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1064. return true;
  1065. }
  1066. public bool GetDistance_3()
  1067. {
  1068. if (!ml_morkf.InitialComplete)
  1069. {
  1070. MessageLog.GetInstance.ShowEx("3号测距出错,菜品库未初始化");
  1071. return false;
  1072. }
  1073. MaterailLibrary_Write("M0.5", true);
  1074. MaterailLibrary_Write("M0.5", false);
  1075. Thread.Sleep(3000);
  1076. //MessageLog.GetInstance.Show("3号测距开启完成");
  1077. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1078. ActionManage.GetInstance.Send(new List<string> { "3", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1079. return true;
  1080. }
  1081. /// <summary>
  1082. /// 写入传感器距离
  1083. /// </summary>
  1084. /// <param name="speed"></param>
  1085. public void WriteSpeed(int speed)
  1086. {
  1087. MaterailLibrary_Write("VD808", speed);
  1088. Thread.Sleep(400);
  1089. }
  1090. /// <summary>
  1091. /// 写入传感器距离
  1092. /// </summary>
  1093. /// <param name="distance"></param>
  1094. public void WriteDistance(int distance)
  1095. {
  1096. MaterailLibrary_Write("VW270", distance);
  1097. }
  1098. /// <summary>
  1099. /// 根据x坐标获取传感器距离
  1100. /// </summary>
  1101. /// <param name="x"></param>
  1102. /// <returns></returns>
  1103. public bool GetDistance(int x)
  1104. {
  1105. bool ret = true;
  1106. //是否在第一层菜品库
  1107. if (x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1108. {
  1109. //获取传感器1的距离
  1110. ret &= GetDistance_1();
  1111. Thread.Sleep(400);
  1112. ////获取传感器1的距离
  1113. ret &= GetDistance_1();
  1114. }
  1115. //是否在第二层菜品库
  1116. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X)
  1117. {
  1118. //获取传感器2的距离
  1119. ret &= GetDistance_2();
  1120. Thread.Sleep(400);
  1121. ret &= GetDistance_2();
  1122. }
  1123. //是否在第三层菜品库
  1124. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["19"].X)
  1125. {
  1126. //获取传感器3的距离
  1127. ret &= GetDistance_3();
  1128. Thread.Sleep(400);
  1129. ret &= GetDistance_3();
  1130. }
  1131. if (!ret)
  1132. {
  1133. MessageLog.GetInstance.ShowEx($"错误:X轴:{x}获取传感器数据出错");
  1134. }
  1135. return ret;
  1136. }
  1137. /// <summary>
  1138. /// 设定机械臂的位置
  1139. /// </summary>
  1140. /// <param name="x"></param>
  1141. /// <param name="y"></param>
  1142. public bool SetArmPosition(int x, int y)
  1143. {
  1144. if (!ml_morkf.InitialComplete)
  1145. {
  1146. MessageLog.GetInstance.ShowEx($"机械臂移动出错,菜品库未初始化");
  1147. return false;
  1148. }
  1149. if (x > 212000 || y > 240000)
  1150. {
  1151. MessageLog.GetInstance.ShowEx("机械臂移动超出范围");
  1152. return false;
  1153. }
  1154. //取反
  1155. x = 0 - Math.Abs(x);
  1156. y = 0 - Math.Abs(y);
  1157. if (x > 0 || y > 0)
  1158. {
  1159. MessageLog.GetInstance.ShowEx($"机械臂移动到[{x},{y}]非法");
  1160. return false;
  1161. }
  1162. MaterailLibrary_Write("VD836", x);
  1163. Thread.Sleep(100);
  1164. MaterailLibrary_Write("VD840", y);
  1165. Thread.Sleep(200);
  1166. //MessageLog.GetInstance.Show($"机械臂移动到[{x},{y}]");
  1167. //到达置为false
  1168. ml_morkf.ArriveComplete = false;
  1169. //定位启动
  1170. MaterailLibrary_Write("M0.0", true);
  1171. Thread.Sleep(400);
  1172. for (int i = 0; i < materialSleepCount && (!ml_morkf.ArriveComplete); i++)
  1173. {
  1174. Thread.Sleep(materialSleepTime);
  1175. //若是目标点与当前坐标一致,跳出循环
  1176. if ((ml_morkf.ArmPositionX == x && ml_morkf.ArmPositionY == y))
  1177. {
  1178. MessageLog.GetInstance.Show($"机械臂已移动到[{ml_morkf.ArmPositionX},{ml_morkf.ArmPositionY}]");
  1179. break;
  1180. }
  1181. if (i >= materialSleepCount - 1)
  1182. {
  1183. MessageLog.GetInstance.ShowEx("机械臂移动操作超时");
  1184. return false;
  1185. }
  1186. }
  1187. //MessageLog.GetInstance.Show("机械臂移动操作完成");
  1188. Thread.Sleep(300);
  1189. return true;
  1190. }
  1191. /// <summary>
  1192. /// 设定机械臂的当前坐标
  1193. /// </summary>
  1194. /// <param name="x"></param>
  1195. /// <param name="y"></param>
  1196. public void SetNowPosition(int x, int y)
  1197. {
  1198. //取反
  1199. x -= 2 * x;
  1200. y -= 2 * y;
  1201. //MessageLog.GetInstance.Show($"设置机械臂当前坐标为[{x},{y}]");
  1202. MaterailLibrary_Write("VD828", x);
  1203. Thread.Sleep(200);
  1204. MaterailLibrary_Write("VD832", y);
  1205. Thread.Sleep(200);
  1206. }
  1207. /// <summary>
  1208. /// 机械臂向上移动开关
  1209. /// </summary>
  1210. /// <param name="startOrStop">true:开启,false:关闭</param>
  1211. public void ArmRunUp(bool startOrStop)
  1212. {
  1213. MaterailLibrary_Write("M5.3", startOrStop);
  1214. Thread.Sleep(200);
  1215. }
  1216. /// <summary>
  1217. /// 机械臂向下移动开关
  1218. /// </summary>
  1219. /// <param name="startOrStop">true:开启,false:关闭</param>
  1220. public void ArmRunDown(bool startOrStop)
  1221. {
  1222. MaterailLibrary_Write("M5.4", startOrStop);
  1223. Thread.Sleep(200);
  1224. }
  1225. /// <summary>
  1226. /// 机械臂向左移动开关
  1227. /// </summary>
  1228. /// <param name="startOrStop">true:开启,false:关闭</param>
  1229. public void ArmRunLeft(bool startOrStop)
  1230. {
  1231. MaterailLibrary_Write("M5.5", startOrStop);
  1232. Thread.Sleep(200);
  1233. }
  1234. /// <summary>
  1235. /// 机械臂向右移动开关
  1236. /// </summary>
  1237. /// <param name="startOrStop">true:开启,false:关闭</param>
  1238. public void ArmRunRight(bool startOrStop)
  1239. {
  1240. MaterailLibrary_Write("M5.6", startOrStop);
  1241. Thread.Sleep(200);
  1242. }
  1243. #endregion
  1244. //菜品库锁
  1245. object lock_Materail = new object();
  1246. /// <summary>
  1247. /// 取菜操作
  1248. /// </summary>
  1249. /// <param name="x">取菜x轴坐标</param>
  1250. /// <param name="y">取菜y轴坐标</param>
  1251. /// <param name="fryNum">炒锅编号</param>
  1252. public bool GetMaterail(int x, int y, int fryNum)
  1253. {
  1254. //设置到抓菜处
  1255. if (!SetArmPosition(x, y))
  1256. {
  1257. return false;
  1258. }
  1259. if (!GetDistance(x))
  1260. {
  1261. MessageLog.GetInstance.Show("错误:获取传感器数据出错");
  1262. return false;
  1263. }
  1264. Thread.Sleep(1000);
  1265. //获取传感器的距离,转换成坐标系的点
  1266. int laserHigh = ml_morkf.LaserDistance;
  1267. //秦工要求读取后置0
  1268. WriteDistance(0);
  1269. MessageLog.GetInstance.Show($"传感器的距离{laserHigh}");
  1270. int moveX = 0;
  1271. if (LaserDistance2Coordinate(laserHigh, x, out moveX) != Laser2CoordinateState.MaterialNormal)
  1272. {
  1273. MessageLog.GetInstance.ShowEx("错误:传感器距离转坐标值失败");
  1274. return false;
  1275. }
  1276. if (x < moveX)
  1277. {
  1278. MessageLog.GetInstance.ShowEx("错误:传感器距离转坐标值大于当前x轴坐标");
  1279. return false;
  1280. }
  1281. //设置到传感器感应的距离处
  1282. if (!SetArmPosition(x - moveX, y))
  1283. {
  1284. return false;
  1285. }
  1286. WriteSpeed(10000);
  1287. //关闭电磁阀
  1288. Electromagnetism(new List<bool> { true });
  1289. Thread.Sleep(500);
  1290. //爪子去1号位抓菜
  1291. if (!PawToPoint1())
  1292. {
  1293. return false;
  1294. }
  1295. //伸出爪子
  1296. if (!PawExtend())
  1297. {
  1298. return false;
  1299. }
  1300. //移动前开启电磁阀
  1301. Electromagnetism(new List<bool> { false });
  1302. Thread.Sleep(500);
  1303. //根据x轴所在坐标系,计算高度差。
  1304. if ((x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X) &&
  1305. (MaterialCoordinate.GetInstance.MaterialOneX > 0 && MaterialCoordinate.GetInstance.MaterialOneX < x))
  1306. {
  1307. //菜品盒子出菜品库,往上移动一个盒子的距离
  1308. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialOneX, y))
  1309. {
  1310. return false;
  1311. }
  1312. }
  1313. else if ((x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X) &&
  1314. (MaterialCoordinate.GetInstance.MaterialTwoX > 0 && MaterialCoordinate.GetInstance.MaterialTwoX < x))
  1315. {
  1316. //菜品盒子出菜品库,往上移动一个盒子的距离
  1317. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialTwoX, y))
  1318. {
  1319. return false;
  1320. }
  1321. }
  1322. else if ((x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["20"].X) &&
  1323. (MaterialCoordinate.GetInstance.MaterialThreeX > 0 && MaterialCoordinate.GetInstance.MaterialThreeX < x))
  1324. {
  1325. //菜品盒子出菜品库,往上移动一个盒子的距离
  1326. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialThreeX, y))
  1327. {
  1328. return false;
  1329. }
  1330. }
  1331. else
  1332. {
  1333. MessageLog.GetInstance.ShowEx("错误:未设置当前菜品库出菜位置");
  1334. return false;
  1335. }
  1336. //爪子去2号位放菜
  1337. if (!PawToPoint2())
  1338. {
  1339. return false;
  1340. }
  1341. WriteSpeed(50000);//移动速度
  1342. //TaskManage.GetInstance.Start(new Action(() =>
  1343. //{
  1344. // //收缩爪子
  1345. // PawShrink();
  1346. //}), "GetMaterialPawShrink");
  1347. //收缩爪子
  1348. if (!PawShrink()) return false;
  1349. //判断炒锅是否可以放盒
  1350. for (int i = 0; materialSleepCount > i && !morkFs[fryNum].FryPot1_HOBTPut; i++)
  1351. {
  1352. Thread.Sleep(materialSleepTime);
  1353. if (i >= materialSleepCount - 1)
  1354. {
  1355. MessageLog.GetInstance.ShowEx("等待炒锅允许放盒超时");
  1356. return false;
  1357. }
  1358. }
  1359. //关闭启磁吸
  1360. MagnetOff(fryNum);
  1361. //Thread.Sleep(2000);
  1362. //根据炒锅不同设置不同的出菜处
  1363. if (fryNum % 2 == 0)
  1364. {
  1365. x = MaterialCoordinate.GetInstance.frying1.X;
  1366. y = MaterialCoordinate.GetInstance.frying1.Y;
  1367. }
  1368. else
  1369. {
  1370. x = MaterialCoordinate.GetInstance.frying2.X;
  1371. y = MaterialCoordinate.GetInstance.frying2.Y;
  1372. }
  1373. //先设置到炒锅i出菜处上10000点
  1374. if (!SetArmPosition(x - materialToFryDistance, y))
  1375. {
  1376. return false;
  1377. }
  1378. //爪子去3号位放菜
  1379. if (!PawToPoint3())
  1380. {
  1381. return false;
  1382. }
  1383. //开启磁吸
  1384. MagnetOn(fryNum);
  1385. Thread.Sleep(500);
  1386. //设置到炒锅1出菜处
  1387. if (!SetArmPosition(x, y))
  1388. {
  1389. return false;
  1390. }
  1391. //伸出爪子
  1392. if (!PawExtend())
  1393. {
  1394. return false;
  1395. }
  1396. Thread.Sleep(300);
  1397. //关闭电磁阀
  1398. Electromagnetism(new List<bool> { true });
  1399. Thread.Sleep(300);
  1400. //收缩爪子
  1401. if (!PawShrink()) return false;
  1402. //设置到炒锅i出菜处
  1403. if (!SetArmPosition(x + materialToFryDistance, y))
  1404. {
  1405. return false;
  1406. }
  1407. //爪子回到2号位
  1408. if (!PawToPoint2())
  1409. {
  1410. return false;
  1411. }
  1412. //开启电磁阀
  1413. Electromagnetism(new List<bool> { false });
  1414. if (morkFs.ContainsKey(fryNum))
  1415. {
  1416. morkFs[fryNum].GetMaterialComplete = true;
  1417. }
  1418. return true;
  1419. }
  1420. /// <summary>
  1421. /// 更新菜品库存量
  1422. /// </summary>
  1423. /// <returns></returns>
  1424. public bool UpdateMaterialLibraryStock()
  1425. {
  1426. try
  1427. {
  1428. //判断是否初始化
  1429. if (!ml_morkf.InitialComplete)
  1430. {
  1431. MessageLog.GetInstance.Show("更新菜品库存量出错,菜品库未初始化");
  1432. return false;
  1433. }
  1434. if (MaterialCoordinate.GetInstance.dicNoMaterialCoordinate == null || MaterialCoordinate.GetInstance.dicNoMaterialCoordinate.Count != 27)
  1435. {
  1436. MessageLog.GetInstance.ShowEx("更新菜品库存量出错,菜品库坐标系数据未建立");
  1437. return false;
  1438. }
  1439. //关闭电磁阀
  1440. Electromagnetism(new List<bool> { true });
  1441. //爪子收回
  1442. if (!PawShrink())
  1443. {
  1444. return false;
  1445. }
  1446. //爪子去2号点位
  1447. if (!PawToPoint2())
  1448. {
  1449. return false;
  1450. }
  1451. //开启电磁阀
  1452. Electromagnetism(new List<bool> { false });
  1453. //遍历坐标系与位置,并根据位置更新菜品余量
  1454. foreach (var item in MaterialCoordinate.GetInstance.dicNoMaterialCoordinate)
  1455. {
  1456. bool ret = true;
  1457. switch (item.Key)
  1458. {
  1459. //遇到1 9 10 18 19 27号位置跳过不检测,因为这6个位置不放菜品
  1460. case "1":
  1461. case "9":
  1462. case "10":
  1463. case "18":
  1464. case "19":
  1465. case "27":
  1466. ret = false;
  1467. break;
  1468. }
  1469. if (!ret)
  1470. {
  1471. continue;
  1472. }
  1473. //设置到抓菜处
  1474. if (!SetArmPosition(item.Value.X, item.Value.Y))
  1475. {
  1476. return false;
  1477. }
  1478. //获取该处的距离
  1479. if (!GetDistance(item.Value.X))
  1480. {
  1481. MessageLog.GetInstance.ShowEx("错误:获取传感器数据出错");
  1482. return false;
  1483. }
  1484. Thread.Sleep(1000);
  1485. //获取传感器的距离
  1486. int laserHigh = ml_morkf.LaserDistance;
  1487. //秦工要求读取后置0
  1488. WriteDistance(0);
  1489. int surplus = 0;
  1490. //根据距离算出菜品余量
  1491. Laser2CoordinateState state = LaserDistance2MaterialCount(laserHigh, item.Value.X, out surplus);
  1492. if (state != Laser2CoordinateState.MaterialNormal && state != Laser2CoordinateState.MaterialEmpty)
  1493. {
  1494. return false;
  1495. }
  1496. //更新菜品余量
  1497. if (!MaterialSurplusOperation.GetInstance.UpdateSurplus(item.Key, surplus))
  1498. {
  1499. //return false;
  1500. }
  1501. }
  1502. return true;
  1503. }
  1504. catch (Exception ex)
  1505. {
  1506. return false;
  1507. }
  1508. }
  1509. /// <summary>
  1510. /// 传感器距离转为x轴坐标系
  1511. /// </summary>
  1512. /// <param name="distance"></param>
  1513. /// <param name="x_high"></param>
  1514. /// <returns></returns>
  1515. public Laser2CoordinateState LaserDistance2Coordinate(int distance, int x, out int x_high)
  1516. {
  1517. x_high = 0;
  1518. int boxCount = 0;
  1519. try
  1520. {
  1521. Laser2CoordinateState laser2CoordinateState = LaserDistance2MaterialCount(distance, x, out boxCount);
  1522. if (laser2CoordinateState == Laser2CoordinateState.MaterialNormal)
  1523. {
  1524. int compensateHeight = boxCount > 1 ? 500 : 0;//补偿高度,超过1层盒子增加补偿
  1525. //盒子高度计算除去起始位置的那个盒子
  1526. x_high = (boxCount - 1) * materialBoxHeight + compensateHeight;
  1527. }
  1528. return laser2CoordinateState;
  1529. }
  1530. catch (Exception ex)
  1531. {
  1532. return Laser2CoordinateState.MaterialUnkown;
  1533. }
  1534. }
  1535. /// <summary>
  1536. /// 传感器距离转为菜品数量
  1537. /// </summary>
  1538. /// <param name="distance"></param>
  1539. /// <param name="x"></param>
  1540. /// <returns></returns>
  1541. public Laser2CoordinateState LaserDistance2MaterialCount(int distance, int x, out int count)
  1542. {
  1543. count = 0;
  1544. try
  1545. {
  1546. //传感器高度小于80mm,无法移出,菜品库满
  1547. if (distance < 80)
  1548. {
  1549. MessageLog.GetInstance.ShowEx("错误:传感器距离不满足出菜高度");
  1550. return Laser2CoordinateState.MaterialOverdo;
  1551. }
  1552. int heightDifferent = 0;
  1553. //根据x轴所在坐标系,计算高度差。
  1554. if (x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1555. {
  1556. heightDifferent = MaterialCoordinate.GetInstance.distance_1 - distance;
  1557. }
  1558. else if (x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1559. {
  1560. heightDifferent = MaterialCoordinate.GetInstance.distance_2 - distance;
  1561. }
  1562. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["20"].X)
  1563. {
  1564. heightDifferent = MaterialCoordinate.GetInstance.distance_3 - distance;
  1565. }
  1566. else
  1567. {
  1568. return Laser2CoordinateState.MaterialOverdo;
  1569. }
  1570. if (heightDifferent < 0)
  1571. {
  1572. MessageLog.GetInstance.ShowEx($"菜品库检测{x}处的菜品量时,传感器获取的高度差为负数,请校准该层高度");
  1573. return Laser2CoordinateState.MaterialEmpty; ;
  1574. }
  1575. //盒子高度为45,但是需要考虑到误差,不足35,则认为为空
  1576. int boxCount = (heightDifferent + 5) / 35;
  1577. count = boxCount;
  1578. if (count == 0)
  1579. {
  1580. MessageLog.GetInstance.ShowEx("菜品库为空");
  1581. return Laser2CoordinateState.MaterialEmpty;
  1582. }
  1583. else if (count > 6)
  1584. {
  1585. MessageLog.GetInstance.ShowEx("菜品库数量超量");
  1586. return Laser2CoordinateState.MaterialOverdo;
  1587. }
  1588. else
  1589. {
  1590. return Laser2CoordinateState.MaterialNormal;
  1591. }
  1592. }
  1593. catch (Exception ex)
  1594. {
  1595. return Laser2CoordinateState.MaterialUnkown;
  1596. }
  1597. }
  1598. /// <summary>
  1599. /// 获取菜品测试
  1600. /// </summary>
  1601. /// <param name="isGet"></param>
  1602. private void GetMaterailTest(MaterialOperation materialOperation)
  1603. {
  1604. TaskManage.GetInstance.Start(new Action(() =>
  1605. {
  1606. bool ret = false;
  1607. try
  1608. {
  1609. Coordinate myCoordinate = new Coordinate();
  1610. //获取坐标,根据菜品的位置信息
  1611. if (!NoMaterial2Coordinate(materialOperation.materialInfo.Loc, out myCoordinate))
  1612. {
  1613. MessageLog.GetInstance.ShowEx($"炒锅{materialOperation.fryNum}获取菜品[{materialOperation.materialInfo.Name}]失败,找不到对应位置");
  1614. return;
  1615. }
  1616. //取菜操作
  1617. ret = GetMaterail(myCoordinate.X, myCoordinate.Y, materialOperation.fryNum);
  1618. }
  1619. catch (Exception ex)
  1620. {
  1621. ret = false;
  1622. }
  1623. finally
  1624. {
  1625. //本地炒制不进行菜品数量检查
  1626. if (!isLocalFryingMode)
  1627. {
  1628. GoodBatchings goodBatchings = stagingGoodBatchings.Find(o => o.BatchingId == materialOperation.materialInfo.Key);
  1629. if (ret == true)
  1630. {
  1631. if (true)
  1632. {
  1633. if (goodBatchings != null)
  1634. {
  1635. //指定位置菜品减一
  1636. MaterialSurplusOperation.GetInstance.ReduceSurplus(materialOperation.materialInfo.Loc, goodBatchings.BatchingCount);
  1637. }
  1638. }
  1639. else
  1640. {
  1641. //指定位置菜品减一
  1642. MaterialSurplusOperation.GetInstance.ReduceSurplus(materialOperation.materialInfo.Loc);
  1643. }
  1644. SaveMaterialData();
  1645. }
  1646. //移出占用菜品
  1647. stagingGoodBatchings.Remove(goodBatchings);
  1648. }
  1649. ml_morkf.MaterailIsWorking = false;
  1650. }
  1651. }), $"菜品库操作");
  1652. }
  1653. #endregion
  1654. #region 炒锅PLC基本操作方法
  1655. /// <summary>
  1656. /// 炒锅写寄存器方法,num为炒锅对应编号,从0开始
  1657. /// </summary>
  1658. /// <param name="address">寄存器地址</param>
  1659. /// <param name="value">值</param>
  1660. /// <param name="num">炒锅编号</param>
  1661. private void FirePot_Write(string address, object value, int num)
  1662. {
  1663. WriteControlExact(address, value, num);
  1664. }
  1665. /// <summary>
  1666. /// 出调料
  1667. /// </summary>
  1668. /// <param name="o"></param>
  1669. public void OutSeasoning(object o, int num)
  1670. {
  1671. if (o == null) return;
  1672. if (o is List<int> ints && ints.Count == 2 && morkFs.ContainsKey(num))
  1673. {
  1674. FirePot_Write(morkFs[num].PassWayValue[ints[0]], (ushort)ints[1], num);//写入通道值
  1675. Thread.Sleep(400);
  1676. FirePot_Write(morkFs[num].StartPassWay[ints[0]], true, num);//开启通道
  1677. Thread.Sleep(400);
  1678. FirePot_Write(morkFs[num].StartPassWay[ints[0]], false, num);//开启通道
  1679. }
  1680. }
  1681. /// <summary>
  1682. /// 出多个调料
  1683. /// </summary>
  1684. public void OutSeasonings(List<SeasoningList> seasoningLists, int num)
  1685. {
  1686. //防止越界
  1687. if (!morkFs.ContainsKey(num))
  1688. {
  1689. return;
  1690. }
  1691. foreach (SeasoningList seasoning in seasoningLists)
  1692. {
  1693. FirePot_Write(morkFs[num].PassWayValue[seasoning.Loc], (ushort)seasoning.Qty, num);
  1694. Thread.Sleep(300);
  1695. }
  1696. foreach (SeasoningList seasoning in seasoningLists)
  1697. {
  1698. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], true, num);
  1699. Thread.Sleep(300);
  1700. }
  1701. foreach (SeasoningList seasoning in seasoningLists)
  1702. {
  1703. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1704. Thread.Sleep(300);
  1705. }
  1706. foreach (SeasoningList seasoning in seasoningLists)
  1707. {
  1708. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1709. Thread.Sleep(300);
  1710. }
  1711. }
  1712. /// <summary>
  1713. /// 复位
  1714. /// </summary>
  1715. public void Plc1Reset(int num)
  1716. {
  1717. TaskManage.GetInstance.Start(new Action(() =>
  1718. {
  1719. StopFire(num);
  1720. Thread.Sleep(200);
  1721. StopStir(num);
  1722. Thread.Sleep(200);
  1723. FirePot_Write("LB5", false, num);
  1724. Thread.Sleep(200);
  1725. FirePot_Write("LB3", false, num);
  1726. Thread.Sleep(200);
  1727. FirePot_Write("LB6", false, num);
  1728. Thread.Sleep(200);
  1729. FirePot_Write("LB7", false, num);
  1730. Thread.Sleep(200);
  1731. FirePot_Write("LB4", false, num);
  1732. Thread.Sleep(200);
  1733. FirePot_Write("LB53", false, num);
  1734. if (morkFs.ContainsKey(num))
  1735. {
  1736. foreach (var item in morkFs[num].StartPassWay.Values)
  1737. {
  1738. Thread.Sleep(200);
  1739. FirePot_Write(item, false, num);
  1740. }
  1741. }
  1742. }), $"炒锅{num}初始化");
  1743. }
  1744. /// <summary>
  1745. /// 炒锅初始化
  1746. /// </summary>
  1747. public void PLCInite()
  1748. {
  1749. for (int i = 0; i < morkFs.Count; i++)
  1750. {
  1751. FirePot_Write("LB0", true, i);
  1752. for (int j = 0; j < sleepCount && !morkFs[i].FryPot1_InitialComplete; j++)
  1753. {
  1754. Thread.Sleep(sleepTime);
  1755. if (j >= sleepCount - 1)
  1756. {
  1757. MessageLog.GetInstance.ShowEx($"炒锅{j}初始化超时");
  1758. }
  1759. }
  1760. FirePot_Write("LB0", false, i);
  1761. }
  1762. }
  1763. //加油
  1764. public void AddOil()
  1765. {
  1766. }
  1767. //加热启动
  1768. public void StartFire(int num)
  1769. {
  1770. FirePot_Write("LB1", true, num);
  1771. Thread.Sleep(200);
  1772. }
  1773. //加热停止
  1774. public void StopFire(int num)
  1775. {
  1776. FirePot_Write("LB1", false, num);
  1777. Thread.Sleep(200);
  1778. }
  1779. //搅拌启动
  1780. public void StartStir(int num)
  1781. {
  1782. FirePot_Write("LB2", true, num);
  1783. Thread.Sleep(200);
  1784. }
  1785. //搅拌启停止
  1786. public void StopStir(int num)
  1787. {
  1788. FirePot_Write("LB2", false, num);
  1789. Thread.Sleep(200);
  1790. }
  1791. //倒菜
  1792. public bool OutFood(int num, out string error, bool isMaterial = false)
  1793. {
  1794. bool ret = true;
  1795. error = string.Empty;
  1796. if (!morkFs.ContainsKey(num))
  1797. {
  1798. error = $"编号为{num}的炒锅无法找到";
  1799. return false;
  1800. }
  1801. int i = 0;
  1802. MessageLog.GetInstance.Show("倒菜启动开始");
  1803. if (isMaterial)
  1804. {
  1805. //判断是否完成取菜
  1806. for (i = 0; i < materialSleepCount * 2 && !morkFs[num].GetMaterialComplete; i++)
  1807. {
  1808. if (i == 10)
  1809. {
  1810. //停止搅拌
  1811. //StopStir(num);
  1812. //搅拌设置为1档
  1813. SetStir(new List<int> { 1 }, i);
  1814. //火力设置为2档
  1815. SetFire(new List<int> { 3 }, num);
  1816. }
  1817. Thread.Sleep(materialSleepTime);
  1818. if (i >= materialSleepCount * 2 - 1)
  1819. {
  1820. error = $"炒锅{num}倒菜超时:未能等到取菜完成,请检查菜品库是否正常运行";
  1821. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时:未能等到取菜完成");
  1822. ret &= false;
  1823. }
  1824. }
  1825. if (i > 9)
  1826. {
  1827. //开启搅拌
  1828. //StartStir(num);
  1829. //搅拌设置为原本搅拌档位
  1830. SetStir(new List<int> { morkFs[num].Stir }, i);
  1831. //火力设置回原本火力
  1832. SetFire(new List<int> { morkFs[num].Fire }, num);
  1833. }
  1834. }
  1835. if (!ret)
  1836. {
  1837. return ret;
  1838. }
  1839. FirePot_Write("LB3", true, num);
  1840. //MessageLog.GetInstance.Show("倒菜启动");
  1841. Thread.Sleep(500);
  1842. for (i = 0; i < materialSleepCount && !morkFs[num].FryPot1_MaterialIntoPot; i++)
  1843. {
  1844. Thread.Sleep(materialSleepTime);
  1845. if (i >= materialSleepCount - 1)
  1846. {
  1847. error = $"炒锅{num}倒菜超时,请联系相关工作人员";
  1848. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时");
  1849. ret &= false;
  1850. }
  1851. }
  1852. FirePot_Write("LB3", false, num);
  1853. Thread.Sleep(200);
  1854. //MessageLog.GetInstance.Show("倒菜完成");
  1855. morkFs[num].GetMaterialComplete = false;
  1856. return ret;
  1857. }
  1858. //搅拌臂去原点位
  1859. public void StirArmGoOrigin(int num)
  1860. {
  1861. if (!morkFs.ContainsKey(num))
  1862. {
  1863. return;
  1864. }
  1865. FirePot_Write("LB5", true, num);
  1866. //MessageLog.GetInstance.Show("搅拌臂去原点位");
  1867. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnOrigin; i++)
  1868. {
  1869. Thread.Sleep(sleepTime);
  1870. if (i >= sleepCount - 1)
  1871. {
  1872. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去原点位超时");
  1873. }
  1874. }
  1875. FirePot_Write("LB5", false, num);
  1876. Thread.Sleep(200);
  1877. //MessageLog.GetInstance.Show("搅拌臂到达原点位");
  1878. }
  1879. //搅拌臂去炒制位
  1880. public bool StirArmGoWork(int num, out string error)
  1881. {
  1882. error = string.Empty;
  1883. bool ret = true;
  1884. if (!morkFs.ContainsKey(num))
  1885. {
  1886. error = $"编号为{num}的炒锅无法找到";
  1887. return false;
  1888. }
  1889. if (!morkFs[num].ArmOnWorking/* && morkFs[num].PotOnOrigin*/)
  1890. {
  1891. FirePot_Write("LB6", true, num);
  1892. //MessageLog.GetInstance.Show("搅拌臂去工作位");
  1893. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnWorking; i++)
  1894. {
  1895. Thread.Sleep(sleepTime);
  1896. if (i >= sleepCount - 1)
  1897. {
  1898. error = $"炒锅{num}搅拌臂去炒制位超时";
  1899. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去炒制位超时");
  1900. ret &= false;
  1901. }
  1902. }
  1903. //while (!morkFs[num].ArmOnWorking)
  1904. //{
  1905. // Thread.Sleep(200);
  1906. //}
  1907. FirePot_Write("LB6", false, num);
  1908. Thread.Sleep(200);
  1909. //MessageLog.GetInstance.Show("搅拌臂到达工作位");
  1910. return ret;
  1911. }
  1912. return true;
  1913. }
  1914. //HBOT放盒子到位
  1915. public void HBOTGoWork(int num)
  1916. {
  1917. FirePot_Write("LB7", true, num);
  1918. Thread.Sleep(400);
  1919. FirePot_Write("LB7", false, num);
  1920. }
  1921. //出餐启动
  1922. public void OutMeal(int num)
  1923. {
  1924. if (!morkFs[num].ArmOnOrigin /*&& morkFs[num].PotOnOrigin*/)
  1925. {
  1926. MessageLog.GetInstance.ShowEx("搅拌臂不在原点位,无法完成出餐");
  1927. return;
  1928. }
  1929. FirePot_Write("LB4", true, num);
  1930. Thread.Sleep(500);
  1931. FirePot_Write("LB4", false, num);
  1932. }
  1933. //加热挡位设定
  1934. public void SetFire(object o, int num)
  1935. {
  1936. if (o == null) return;
  1937. if (o is List<int> ints && ints.Count == 1)
  1938. {
  1939. FirePot_Write("LW14", (ushort)ints[0], num);
  1940. Thread.Sleep(200);
  1941. }
  1942. }
  1943. public void SetFry(object o)
  1944. {
  1945. if (o == null) return;
  1946. if (o is List<int> ints && ints.Count == 1)
  1947. {
  1948. fryIndex = ints[0] - 1;
  1949. }
  1950. }
  1951. /// <summary>
  1952. /// 搅拌挡位设定
  1953. /// </summary>
  1954. /// <param name="o"></param>
  1955. public void SetStir(object o, int num)
  1956. {
  1957. if (o == null) return;
  1958. if (o is List<int> ints && ints.Count == 1)
  1959. {
  1960. FirePot_Write("LW15", (ushort)ints[0], num);
  1961. Thread.Sleep(200);
  1962. }
  1963. }
  1964. /// <summary>
  1965. /// 开启磁吸
  1966. /// </summary>
  1967. /// <param name="num"></param>
  1968. public void MagnetOn(int num)
  1969. {
  1970. FirePot_Write("LB8", false, num);
  1971. Thread.Sleep(200);
  1972. }
  1973. /// <summary>
  1974. /// 关闭磁吸
  1975. /// </summary>
  1976. /// <param name="num"></param>
  1977. public void MagnetOff(int num)
  1978. {
  1979. FirePot_Write("LB8", true, num);
  1980. Thread.Sleep(200);
  1981. }
  1982. #endregion
  1983. bool isInitialArrive = false;
  1984. bool isInitialPaw = false;
  1985. #region 联网交互
  1986. private void ServerInit()
  1987. {
  1988. //物料信息
  1989. EventBus.GetInstance.Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1990. {
  1991. if (@event == null) return;
  1992. if (@event is MaterialDeliveryEvent material)
  1993. {
  1994. orderMaterialDelivery = material.orderMaterialDelivery;
  1995. }
  1996. });
  1997. //配方数据信息
  1998. EventBus.GetInstance.Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1999. {
  2000. if (@event == null) return;
  2001. if (@event is RecipeBomEvent recipe)
  2002. {
  2003. recipeBoms = recipe.recipeBoms;
  2004. }
  2005. });
  2006. //小炒流程信息
  2007. EventBus.GetInstance.Subscribe<StirFryGoodsEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callback)
  2008. {
  2009. if (@event == null) return;
  2010. if (@event is StirFryGoodsEvent stirFry)
  2011. {
  2012. if (stirFry.stirFrymessage != null)
  2013. {
  2014. if (stirFry.stirFrymessage.stirFryGoods.Count > 0)
  2015. {
  2016. foreach (var item in stirFry.stirFrymessage.stirFryGoods)
  2017. {
  2018. LocalstirFryGoods.Add(new StirFryGoods
  2019. {
  2020. GoodsKey = item.GoodsKey,
  2021. StirPotActions = OrderSort(item.StirPotActions),
  2022. });
  2023. }
  2024. }
  2025. MessageLog.GetInstance.Show("接收到小炒流程信息");
  2026. //流程解析
  2027. foreach (var item in LocalstirFryGoods)
  2028. {
  2029. MessageLog.GetInstance.Show($"添加菜谱{item.GoodsKey}");
  2030. // morkF.listStirBom.Add(item.StirFryBomInfo);//添加订单制作流程
  2031. string MenuStep = "菜单步骤:";
  2032. foreach (var items in item.StirPotActions)
  2033. {
  2034. switch (items.Actions)
  2035. {
  2036. case nameof(StirFryPotActionEnum.加热开启):
  2037. MenuStep += items.Actions + ",";
  2038. break;
  2039. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2040. MenuStep += items.Actions + ",";
  2041. break;
  2042. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2043. MenuStep += items.Actions + ",";
  2044. break;
  2045. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2046. MenuStep += items.Actions + ",";
  2047. break;
  2048. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2049. MenuStep += items.Actions + ",";
  2050. break;
  2051. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2052. MenuStep += items.Actions + ",";
  2053. break;
  2054. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2055. MenuStep += items.Actions + ",";
  2056. break;
  2057. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2058. MenuStep += items.Actions + ",";
  2059. break;
  2060. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2061. MenuStep += items.Actions + ",";
  2062. break;
  2063. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2064. MenuStep += items.Actions + ",";
  2065. break;
  2066. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2067. MenuStep += items.Actions + ",";
  2068. break;
  2069. case nameof(StirFryPotActionEnum.停止加热):
  2070. MenuStep += items.Actions + ",";
  2071. break;
  2072. case nameof(StirFryPotActionEnum.加调料):
  2073. MenuStep += items.Actions + ",";
  2074. break;
  2075. case nameof(StirFryPotActionEnum.取原料):
  2076. MenuStep += items.Actions + ",";
  2077. break;
  2078. case nameof(StirFryPotActionEnum.开启搅拌):
  2079. MenuStep += items.Actions + ",";
  2080. break;
  2081. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2082. MenuStep += items.Actions + ",";
  2083. break;
  2084. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2085. MenuStep += items.Actions + ",";
  2086. break;
  2087. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2088. MenuStep += items.Actions + ",";
  2089. break;
  2090. case nameof(StirFryPotActionEnum.关闭搅拌):
  2091. MenuStep += items.Actions + ",";
  2092. break;
  2093. case nameof(StirFryPotActionEnum.出餐启动):
  2094. MenuStep += items.Actions + ",";
  2095. break;
  2096. case nameof(StirFryPotActionEnum.道菜启动):
  2097. MenuStep += items.Actions + ",";
  2098. break;
  2099. case nameof(StirFryPotActionEnum.炒制菜品):
  2100. MenuStep += items.Actions + ",";
  2101. break;
  2102. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2103. MenuStep += items.Actions + ",";
  2104. break;
  2105. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2106. MenuStep += items.Actions + ",";
  2107. break;
  2108. case nameof(StirFryPotActionEnum.洗锅):
  2109. MenuStep += items.Actions + ",";
  2110. break;
  2111. default:
  2112. break;
  2113. }
  2114. }
  2115. MessageLog.GetInstance.Show(MenuStep);
  2116. }
  2117. if (stirFry.stirFrymessage.materials.Count > 0)
  2118. {
  2119. MaterialSurplusOperation.GetInstance.UpdateSurplusAll(stirFry.stirFrymessage.materials);
  2120. SaveMaterialData();
  2121. }
  2122. }
  2123. }
  2124. });
  2125. }
  2126. /// <summary>
  2127. /// 订单排序
  2128. /// </summary>
  2129. /// <param name="potActions"></param>
  2130. /// <returns></returns>
  2131. private List<PotActions> OrderSort(List<PotActions> potActions)
  2132. {
  2133. if (potActions.Count > 1)
  2134. {
  2135. potActions.Sort(
  2136. delegate (PotActions st1, PotActions st2)
  2137. {
  2138. //降序排列
  2139. //return st2.FryTime.CompareTo(st1.FryTime);
  2140. //升序版(颠倒 st1 和 st2 即可)
  2141. return st1.FryTime.CompareTo(st2.FryTime);
  2142. });
  2143. }
  2144. return potActions;
  2145. }
  2146. /// <summary>
  2147. /// 订单状态发布
  2148. /// </summary>
  2149. /// <param name="subid"></param>
  2150. /// <param name="oRDER_STATUS"></param>
  2151. private void OrderChange(string Id, string goodName, ORDER_STATUS oRDER_STATUS, int deviceId)
  2152. {
  2153. EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { Status = oRDER_STATUS, GoodName = goodName, DeviceId = deviceId, SubOrderId = Id });
  2154. }
  2155. /// <summary>
  2156. /// 订单数据解析
  2157. /// </summary>
  2158. private void DataParse()
  2159. {
  2160. //if (!morkFs.ContainsKey(num))
  2161. //{
  2162. // return;
  2163. //}
  2164. EventBus.GetInstance.Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  2165. {
  2166. if (@event == null) return;
  2167. if (@event is DoOrderEvent order)
  2168. {
  2169. if (order.MorkOrder.GoodBatchings == null) return;
  2170. OrderCount++;
  2171. DeviceProcessLogShow($"接收到{OrderCount}次订单");
  2172. Enum.GetNames(typeof(StirFryPotActionEnum));
  2173. if (true)
  2174. {
  2175. var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey == order.MorkOrder.GoodsKey);//匹配订单对应制作流程
  2176. if (order.MorkOrder.GoodBatchings.Count <= 0)
  2177. {
  2178. return;
  2179. }
  2180. MaterialSurplus materialSurplus = MaterialSurplusOperation.GetInstance.materialSurplus;
  2181. if (order.MorkOrder.DeviceId != DeviceId)
  2182. {
  2183. return;
  2184. }
  2185. ///遍历并增加到待用菜品库
  2186. foreach (var goodBatching in order.MorkOrder.GoodBatchings)
  2187. {
  2188. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance.materialSurplus.dicSurplus.Find(o => o.Key == goodBatching.BatchingId);
  2189. if (materialInfo != null)
  2190. {
  2191. //if
  2192. if (System.Convert.ToInt32(materialInfo.Qty) - goodBatching.BatchingCount < 0)
  2193. {
  2194. MessageLog.GetInstance.ShowEx($"{materialInfo.Name}不够,请更新菜品库,并点击检测");
  2195. return;
  2196. }
  2197. else
  2198. {
  2199. //查找是否有该菜品
  2200. GoodBatchings existingGoodBatchings = stagingGoodBatchings.Find(o => o.BatchingId == goodBatching.BatchingId);
  2201. //判断是否存在
  2202. if (existingGoodBatchings != null)
  2203. {
  2204. existingGoodBatchings.BatchingCount += goodBatching.BatchingCount;
  2205. }
  2206. else
  2207. {
  2208. stagingGoodBatchings.Add(goodBatching);
  2209. }
  2210. }
  2211. }
  2212. else
  2213. {
  2214. MessageLog.GetInstance.ShowEx($"ID为{goodBatching.BatchingId}的菜品无法找到,请联系售后人员");
  2215. return;
  2216. }
  2217. }
  2218. //var res = LocalstirFryGoods[0];
  2219. if (res != null)
  2220. {
  2221. /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  2222. //添加到带炒小炒队列
  2223. if (StirFryGoodsQuenes.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  2224. {
  2225. //待炒数量+1
  2226. StagingFryCount++;
  2227. lock (lock_MainProcessExcute)
  2228. {
  2229. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  2230. {
  2231. SuborderId = order.MorkOrder.SuborderId,
  2232. StirPotActions = res.StirPotActions,
  2233. GoodName = order.MorkOrder.GoodsName
  2234. });
  2235. }
  2236. }
  2237. }
  2238. }
  2239. else
  2240. {
  2241. NewStartLocalOrder("莲白回锅");
  2242. }
  2243. ////暂时使用本地菜单
  2244. //StartLocalOrder();
  2245. }
  2246. });
  2247. }
  2248. #endregion
  2249. private object lock_MainProcessExcute = new object();
  2250. /// <summary>
  2251. /// 倒菜锁
  2252. /// </summary>
  2253. private object lock_OutMeal = new object();
  2254. /// <summary>
  2255. /// 炒锅主流程
  2256. /// </summary>
  2257. private void MainProcessExcute()
  2258. {
  2259. //判断是否有订单信息
  2260. if (StirFryGoodsQuenes.Count > 0)
  2261. {
  2262. //遍历炒锅,找到合适、空闲的炒锅
  2263. for (int i = 0; i < morkFs.Count; i++)
  2264. {
  2265. if (morkFs[i].AutoMode && morkFs[i].FryPot1_InitialComplete && ml_morkf.InitialComplete &&
  2266. !morkFs[i].FryWorking)//炒锅在自动状态&&初始化完成&&菜品库初始化&&是否在炒菜中
  2267. {
  2268. Thread.Sleep(4000);
  2269. lock (lock_MainProcessExcute)
  2270. {
  2271. //待炒小炒队列出队列
  2272. if (StirFryGoodsQuenes.TryDequeue(out var res))
  2273. {
  2274. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.WAIT, DeviceId = i);
  2275. //设置当前炒制菜品
  2276. nowStirFryGood[i] = res;
  2277. //炒锅工作状态置为正在工作中
  2278. morkFs[i].FryWorking = true;
  2279. //空闲炒锅入队列
  2280. morkFs[i].StirFryGoodsQuenes.Enqueue(res);
  2281. //炒锅取菜状态置为未取到
  2282. morkFs[i].GetMaterialComplete = false;
  2283. //开启线程进行炒制
  2284. TaskManage.GetInstance.Start(new Action(() =>
  2285. {
  2286. try
  2287. {
  2288. //待炒数量-1
  2289. StagingFryCount--;
  2290. //正在炒制数量+1
  2291. FryingCount++;
  2292. int testi = 0;
  2293. string error = string.Empty;
  2294. //初始化大屏
  2295. morkFs[i].ScreenInit();
  2296. bool ret = true;
  2297. MessageLog.GetInstance.Show($"炒锅{i}开始炒制菜品{res.GoodName}");
  2298. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COOKING, DeviceId = i);
  2299. morkFs[i].GoodName = res.GoodName;
  2300. Coordinate myCoordinate = new Coordinate();
  2301. foreach (var potActions in res.StirPotActions)
  2302. {
  2303. if (TaskManage.GetInstance.IsComplete(String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)))
  2304. {
  2305. return;
  2306. }
  2307. if (ret == false)
  2308. {
  2309. MessageLog.GetInstance.ShowEx("上一步操作未成功");
  2310. break;
  2311. }
  2312. ////调试大屏用代码
  2313. //Thread.Sleep(5000);
  2314. //更新
  2315. morkFs[i].UpdateProcess(potActions);
  2316. switch (potActions.Actions)
  2317. {
  2318. case nameof(StirFryPotActionEnum.加热开启):
  2319. StartFire(i);
  2320. MessageLog.GetInstance.Show(potActions.Actions);
  2321. break;
  2322. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2323. morkFs[i].Fire = 1;
  2324. SetFire(new List<int> { 1 }, i);
  2325. MessageLog.GetInstance.Show(potActions.Actions);
  2326. break;
  2327. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2328. morkFs[i].Fire = 2;
  2329. SetFire(new List<int> { 2 }, i);
  2330. MessageLog.GetInstance.Show(potActions.Actions);
  2331. break;
  2332. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2333. morkFs[i].Fire = 3;
  2334. SetFire(new List<int> { 3 }, i);
  2335. MessageLog.GetInstance.Show(potActions.Actions);
  2336. break;
  2337. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2338. morkFs[i].Fire = 4;
  2339. SetFire(new List<int> { 4 }, i);
  2340. MessageLog.GetInstance.Show(potActions.Actions);
  2341. break;
  2342. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2343. morkFs[i].Fire = 5;
  2344. SetFire(new List<int> { 5 }, i);
  2345. MessageLog.GetInstance.Show(potActions.Actions);
  2346. break;
  2347. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2348. morkFs[i].Fire = 6;
  2349. SetFire(new List<int> { 6 }, i);
  2350. MessageLog.GetInstance.Show(potActions.Actions);
  2351. break;
  2352. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2353. morkFs[i].Fire = 7;
  2354. SetFire(new List<int> { 7 }, i);
  2355. MessageLog.GetInstance.Show(potActions.Actions);
  2356. break;
  2357. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2358. morkFs[i].Fire = 8;
  2359. SetFire(new List<int> { 8 }, i);
  2360. MessageLog.GetInstance.Show(potActions.Actions);
  2361. break;
  2362. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2363. morkFs[i].Fire = 9;
  2364. SetFire(new List<int> { 9 }, i);
  2365. MessageLog.GetInstance.Show(potActions.Actions);
  2366. break;
  2367. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2368. morkFs[i].Fire = 10;
  2369. SetFire(new List<int> { 10 }, i);
  2370. MessageLog.GetInstance.Show(potActions.Actions);
  2371. break;
  2372. case nameof(StirFryPotActionEnum.停止加热):
  2373. StopFire(i);
  2374. MessageLog.GetInstance.Show(potActions.Actions);
  2375. break;
  2376. case nameof(StirFryPotActionEnum.加调料):
  2377. OutSeasonings(potActions.SeasoningLists, i);
  2378. MessageLog.GetInstance.Show(potActions.Actions);
  2379. break;
  2380. case nameof(StirFryPotActionEnum.取原料):
  2381. if (potActions.SeasoningLists[0].Loc == 1 ||
  2382. potActions.SeasoningLists[0].Loc == 9 ||
  2383. potActions.SeasoningLists[0].Loc == 10 ||
  2384. potActions.SeasoningLists[0].Loc == 18 ||
  2385. potActions.SeasoningLists[0].Loc == 19 ||
  2386. potActions.SeasoningLists[0].Loc == 27)
  2387. {
  2388. MessageLog.GetInstance.ShowEx("该取料位置禁止使用");
  2389. return;
  2390. }
  2391. //炒锅取菜状态置为未取到
  2392. morkFs[i].GetMaterialComplete = false;
  2393. if (isLocalFryingMode)
  2394. {
  2395. MaterialInfo materialInfo = new MaterialInfo();
  2396. materialInfo.Loc = potActions.SeasoningLists[0].Loc.ToString();
  2397. materialInfo.Id = "1232131";
  2398. materialInfo.Name = "本地炒制未知菜品";
  2399. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2400. //testi++;
  2401. }
  2402. else
  2403. {
  2404. if (potActions.MaterialLists != null)
  2405. {
  2406. foreach (var item in potActions.MaterialLists)
  2407. {
  2408. //通过ID获取有效的菜品对象
  2409. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance.GetVailedMaterial(item.MaterialId);
  2410. if (materialInfo == null)
  2411. {
  2412. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品[{item.MaterialId}]失败,库存不足");
  2413. continue;
  2414. }
  2415. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2416. }
  2417. }
  2418. else
  2419. {
  2420. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品失败,菜品列表为空");
  2421. }
  2422. }
  2423. MessageLog.GetInstance.Show(potActions.Actions);
  2424. break;
  2425. case nameof(StirFryPotActionEnum.开启搅拌):
  2426. StartStir(i);
  2427. MessageLog.GetInstance.Show(potActions.Actions);
  2428. break;
  2429. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2430. SetStir(new List<int> { 1 }, i);
  2431. MessageLog.GetInstance.Show(potActions.Actions);
  2432. break;
  2433. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2434. SetStir(new List<int> { 2 }, i);
  2435. MessageLog.GetInstance.Show(potActions.Actions);
  2436. break;
  2437. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2438. SetStir(new List<int> { 3 }, i);
  2439. MessageLog.GetInstance.Show(potActions.Actions);
  2440. break;
  2441. case nameof(StirFryPotActionEnum.关闭搅拌):
  2442. StopStir(i);
  2443. MessageLog.GetInstance.Show(potActions.Actions);
  2444. break;
  2445. case nameof(StirFryPotActionEnum.出餐启动):
  2446. //停止搅拌
  2447. StopStir(i);
  2448. //回原点位
  2449. StirArmGoOrigin(i);
  2450. //出餐启动
  2451. OutMeal(i);
  2452. MessageLog.GetInstance.Show(potActions.Actions);
  2453. break;
  2454. case nameof(StirFryPotActionEnum.道菜启动):
  2455. ret = OutFood(i, out error, true);
  2456. if (ret == false)
  2457. {
  2458. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2459. }
  2460. break;
  2461. case nameof(StirFryPotActionEnum.炒制菜品):
  2462. Thread.Sleep(potActions.During * 1000);
  2463. break;
  2464. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2465. StirArmGoOrigin(i);
  2466. MessageLog.GetInstance.Show(potActions.Actions);
  2467. break;
  2468. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2469. //出餐时,不允许搅拌臂去炒制位
  2470. lock (lock_OutMeal)
  2471. {
  2472. ret = StirArmGoWork(i, out error);
  2473. }
  2474. if (ret == false)
  2475. {
  2476. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2477. }
  2478. MessageLog.GetInstance.Show(potActions.Actions);
  2479. break;
  2480. case nameof(StirFryPotActionEnum.洗锅):
  2481. MessageLog.GetInstance.Show(potActions.Actions);
  2482. break;
  2483. default:
  2484. break;
  2485. }
  2486. }
  2487. Plc1Reset(i);//复位
  2488. Thread.Sleep(3000);
  2489. //回原点位
  2490. StirArmGoOrigin(i);
  2491. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COMPLETED_COOK, DeviceId = i);
  2492. //同时只能允许有一个出餐
  2493. lock (lock_OutMeal)
  2494. {
  2495. //出餐启动
  2496. OutMeal(i);
  2497. //等待25s出餐完毕
  2498. Thread.Sleep(25000);
  2499. }
  2500. MessageLog.GetInstance.Show($"菜品{res.GoodName}完成");
  2501. //菜品统计数量+1
  2502. morkFs[i].orderCount++;
  2503. StatsModel statsModel = statsModels.FirstOrDefault(p => p.Name == res.GoodName);
  2504. if (statsModel != null)
  2505. {
  2506. statsModel.Count++;
  2507. }
  2508. else
  2509. {
  2510. statsModels.Add(new StatsModel() { Name = res.GoodName, Count = 0 });
  2511. }
  2512. }
  2513. catch (Exception ex)
  2514. {
  2515. nowStirFryGood[i] = null;
  2516. //炒完后出队列
  2517. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2518. morkFs[i].FryWorking = false;
  2519. //初始化大屏
  2520. morkFs[i].ScreenClear();
  2521. //异常菜品统计数量+1
  2522. morkFs[i].orderAbnormalCount++;
  2523. TaskManage.GetInstance.StopTask($"炒锅{i}{res.GoodName}炒制线程");
  2524. MessageLog.GetInstance.ShowEx($"炒锅{i}炒制菜品{res.GoodName}出错,错误信息:" + ex.Message);
  2525. }
  2526. finally
  2527. {
  2528. //正在炒制数量-1
  2529. FryingCount--;
  2530. nowStirFryGood[i] = null;
  2531. //炒完后出队列
  2532. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2533. morkFs[i].FryWorking = false;
  2534. //初始化大屏
  2535. morkFs[i].ScreenClear();
  2536. }
  2537. }), String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)/*$"炒锅{i}炒制{res.GoodName}线程"*/, isRestart: true);
  2538. }
  2539. }
  2540. break;
  2541. }
  2542. }
  2543. }
  2544. }
  2545. /// <summary>
  2546. /// 更新菜品库的余量
  2547. /// </summary>
  2548. private void UpdateMaterialSurplus()
  2549. {
  2550. TaskManage.GetInstance.StartLong(new Action(() =>
  2551. {
  2552. List<MaterialInfo> listSurplus = MaterialSurplusOperation.GetInstance.materialSurplus.dicSurplus;
  2553. if (listSurplus == null)
  2554. {
  2555. return;
  2556. }
  2557. foreach (var surplus in listSurplus)
  2558. {
  2559. //找到已有的余量表
  2560. var batchingInfo = BatchingInfos.Find(o => o.BatchingId == surplus.Key);
  2561. //从当前下单
  2562. var stagingGoodBatching = stagingGoodBatchings.Find(o => o.BatchingId == surplus.Key);
  2563. //暂存的数量
  2564. int stagingCount = 0;
  2565. if (stagingGoodBatching != null)
  2566. {
  2567. stagingCount = stagingGoodBatching.BatchingCount;
  2568. }
  2569. if (batchingInfo == null)
  2570. {
  2571. //为空就新增
  2572. BatchingInfos.Add(new BatchingInfo() { BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount, BatchingLoc = surplus.Loc, BatchingId = surplus.Key });
  2573. }
  2574. else
  2575. {
  2576. batchingInfo.BatchingLoc = surplus.Loc;
  2577. batchingInfo.BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount;
  2578. }
  2579. }
  2580. Thread.Sleep(1000);
  2581. return;
  2582. }), "UpdateMaterialSurplus", true);
  2583. }
  2584. /// <summary>
  2585. /// 菜品库主流程
  2586. /// </summary>
  2587. private void MainProcessMaterial()
  2588. {
  2589. if (materialOperationQuenes.Count > 0)
  2590. {
  2591. //判断是否初始化与是否在工作中
  2592. if (ml_morkf.InitialComplete && !ml_morkf.MaterailIsWorking)
  2593. {
  2594. //待菜品库操作列出队列
  2595. if (materialOperationQuenes.TryDequeue(out var res))
  2596. {
  2597. Thread.Sleep(1000);
  2598. ml_morkf.MaterailIsWorking = true;
  2599. MessageLog.GetInstance.Show("开始操作菜品库");
  2600. //TaskManage.GetInstance.Start(new Action(()=>{
  2601. // GetMaterail(res.x_high, res.y, res.fryNum);
  2602. //}),"菜品库操作");
  2603. GetMaterailTest(res);
  2604. }
  2605. }
  2606. }
  2607. }
  2608. /// <summary>
  2609. /// 信号处理
  2610. /// </summary>
  2611. private void SingleProcess()
  2612. {
  2613. }
  2614. private void ScreenDataServer()
  2615. {
  2616. LocalMqtt.GetInstance.Init(ScreenDeviceType.小炒);
  2617. TaskManage.GetInstance.StartLong(new Action(() =>
  2618. {
  2619. //statsModels.Add(new StatsModel() { Name = "帝王蟹", Count = 666 });
  2620. ScreenModelMinWok maxWok = new ScreenModelMinWok
  2621. {
  2622. IsRun = IsHealth ? IsRun.运行 : IsRun.停止,//new Random().Next(0, 2) == 0 ? IsRun.运行 : IsRun.停止, //设备是否运行
  2623. WorkStatus_1 = morkFs[0].FryPot1_InitialComplete ? ((morkFs[0].Task != null) ? WorkStatus.工作 : WorkStatus.待机) : WorkStatus.停止,// (WorkStatus)new Random().Next(0, 3), //设备运行状态
  2624. WorkStatus_2 = morkFs[1].FryPot1_InitialComplete ? ((morkFs[1].Task != null) ? WorkStatus.工作 : WorkStatus.待机) : WorkStatus.停止,//(WorkStatus)new Random().Next(0, 3), //设备运行状态
  2625. RobotStatu = (WorkStatus)new Random().Next(0, 3), //机器人状态 待机 1 正常
  2626. Alarm = alarmModel, //告警集合
  2627. FailuresCount = alarmModel.Count, //故障数
  2628. StatsCount = statsModels, //统计菜品数量
  2629. MinWok_Dishes_1 = morkFs[0].GoodName,//"满汉全席",//当前炒制菜品名
  2630. MinWok_Dishes_2 = morkFs[1].GoodName,
  2631. MinWok_Task_1 = morkFs[0].Task,//当前任务
  2632. MinWok_Task_2 = morkFs[1].Task, //当前任务
  2633. //MinWok_Process_1 = new List<ProcessModel>() { new ProcessModel() { Id = 1, Name = "启动", Status = ProcessStatus.正在执行 }, new ProcessModel() { Id = 1, Name = "热油", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "炒制", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "出餐", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "结束", Status = ProcessStatus.未执行 } },
  2634. MinWok_Process_1 = morkFs[0].processModels, //炒锅当前任务流程
  2635. MinWok_Process_2 = morkFs[1].processModels, //炒锅当前任务流程
  2636. MinWok_HeatGear_1 = morkFs[0].FireNow, //炒锅加热档位
  2637. MinWok_HeatGear_2 = morkFs[1].FireNow, //炒锅加热档位
  2638. MinWok_Temp_1 = morkFs[0].TempNow, //炒锅1锅底温度
  2639. MinWok_Temp_2 = morkFs[1].TempNow, //炒锅1锅底温度
  2640. MinWok_StirGear_1 = morkFs[0].StirNow, //炒锅搅拌档位
  2641. MinWok_StirGear_2 = morkFs[1].StirNow, //炒锅搅拌档位
  2642. MinWok_OrderCount_1 = morkFs[0].orderCount, //订单数量
  2643. MinWok_OrderCount_2 = morkFs[1].orderCount, //订单数量
  2644. MinWok_ErrorOrderCount_1 = morkFs[0].orderAbnormalCount, //异常订单数量
  2645. MinWok_ErrorOrderCount_2 = morkFs[1].orderAbnormalCount, //异常订单数量
  2646. };
  2647. LocalMqtt.GetInstance.Publish(maxWok);
  2648. Thread.Sleep(1000);
  2649. }), "大屏数据上报", true);
  2650. }
  2651. public override void SimOrder()
  2652. {
  2653. }
  2654. /// <summary>
  2655. /// 菜品编号转换为坐标
  2656. /// </summary>
  2657. /// <param name="no"></param>
  2658. /// <param name="coordinate"></param>
  2659. /// <returns></returns>
  2660. public bool NoMaterial2Coordinate(string no, out Coordinate coordinate)
  2661. {
  2662. //默认返回0,0
  2663. coordinate = new Coordinate();
  2664. coordinate.X = 0;
  2665. coordinate.Y = 0;
  2666. try
  2667. {
  2668. if (MaterialCoordinate.GetInstance.dicNoMaterialCoordinate.ContainsKey(no))
  2669. {
  2670. coordinate = MaterialCoordinate.GetInstance.dicNoMaterialCoordinate[no];
  2671. return true;
  2672. }
  2673. else
  2674. {
  2675. return false;
  2676. }
  2677. }
  2678. catch (Exception ex)
  2679. {
  2680. return false;
  2681. }
  2682. finally
  2683. {
  2684. }
  2685. }
  2686. public enum Laser2CoordinateState
  2687. {
  2688. MaterialOverdo = 0,//菜品过量
  2689. MaterialNormal = 1,//菜品正常
  2690. MaterialEmpty = 2,//菜品为空
  2691. MaterialUnkown = 999,//菜品未知错误
  2692. }
  2693. }
  2694. }