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

IceCreamMachine.cs 14 KiB

1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. 
  2. using BPA.Helper;
  3. using BPASmartClient.Model;
  4. using BPASmartClient.Model.冰淇淋.Enum;
  5. using BPASmartClient.Peripheral;
  6. using BPASmartClient.SerialPort;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Threading;
  11. using static BPA.Helper.EventBus;
  12. using static BPASmartClient.GSIceCream.MessageDefine;
  13. namespace BPASmartClient.GSIceCream
  14. {
  15. public class IceCreamMachine : BasePeripheral
  16. {
  17. //通讯代理
  18. SerialPortClient commProxy = null;
  19. //是否下发指令,主线程等待
  20. private bool free = false;
  21. //心跳指令
  22. private byte[] cmdHeartDW;
  23. //数据仓库
  24. private DataStorage<byte> dataStorage = new DataStorage<byte>();
  25. //串口COM口
  26. public string PortName { get; set; }
  27. //串口波特率
  28. public string BaudRate { get; set; }
  29. //心跳时间
  30. private DateTime lastRefreshTime = DateTime.MinValue;
  31. //是否在线
  32. public bool OnLine { get { return DateTime.Now.Subtract(lastRefreshTime).TotalSeconds <= 3; } }
  33. //private volatile static IceCreamMachine _Instance;
  34. //public static IceCreamMachine GetInstance => _Instance ?? (_Instance = new IceCreamMachine());
  35. public IceCreamMachine()
  36. {
  37. ICMSG_Heart_DW heartDW = new ICMSG_Heart_DW();
  38. cmdHeartDW = IcPack.StructureToByte(heartDW);
  39. }
  40. /// <summary>
  41. /// 主线程开始运行
  42. /// </summary>
  43. public override void Start()
  44. {
  45. try
  46. {
  47. commProxy.Start();
  48. free = false;
  49. MainLoop();
  50. }
  51. catch (Exception ex)
  52. {
  53. MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]");
  54. }
  55. }
  56. /// <summary>
  57. /// 停止运行
  58. /// </summary>
  59. public override void Stop()
  60. {
  61. try
  62. {
  63. commProxy.Stop();
  64. IsConnected = false;
  65. free = true;
  66. }
  67. catch (Exception ex)
  68. {
  69. MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]");
  70. }
  71. }
  72. private MSG_RESOLVE_STEP currentStep;
  73. private void MainLoop()
  74. {
  75. TaskManage.GetInstance.StartLong(new Action(() =>
  76. {
  77. if (!free)
  78. {
  79. commProxy.SendData(cmdHeartDW);
  80. }
  81. Thread.Sleep(500);
  82. }), "冰淇淋询问线程");
  83. TaskManage.GetInstance.StartLong(new Action(() =>
  84. {
  85. ResolveMsg();
  86. }), "冰淇淋解析线程");
  87. }
  88. int contentLength = 0;
  89. int currentContentOffset = 0;
  90. private void ResolveMsg()
  91. {
  92. List<byte> temp = new List<byte>();
  93. //一系列解包
  94. while (dataStorage.GetSize() > 0)
  95. {
  96. byte item = dataStorage.GetData();
  97. switch (currentStep)
  98. {
  99. case MSG_RESOLVE_STEP.NONE:
  100. if (item == MessageDefine.HEADER1)
  101. {
  102. temp.Add(item);
  103. currentStep = MSG_RESOLVE_STEP.HEADER1;
  104. continue;
  105. }
  106. break;
  107. case MSG_RESOLVE_STEP.HEADER1:
  108. if (item == MessageDefine.HEADER2_UP)
  109. {
  110. temp.Add(item);
  111. currentStep = MSG_RESOLVE_STEP.HEADER2;
  112. continue;
  113. }
  114. else
  115. {
  116. temp.Clear();
  117. currentStep = MSG_RESOLVE_STEP.NONE;
  118. continue;
  119. }
  120. case MSG_RESOLVE_STEP.HEADER2:
  121. switch ((IC_CMD)item)
  122. {
  123. case IC_CMD.HEART:
  124. temp.Add(item);
  125. contentLength = MessageDefine.MSG_LENGTH[(IC_CMD)item];
  126. currentContentOffset = 0;
  127. currentStep = MSG_RESOLVE_STEP.CMD;
  128. break;
  129. default:
  130. temp.Clear();
  131. currentStep = MSG_RESOLVE_STEP.NONE;
  132. break;
  133. }
  134. break;
  135. }
  136. int retry = 3;
  137. while (dataStorage.GetSize() < contentLength + 2 && retry >= 0)
  138. {
  139. retry--;
  140. Thread.Sleep(100);
  141. }
  142. if (retry < 0)
  143. {
  144. currentStep = MSG_RESOLVE_STEP.NONE;
  145. currentContentOffset = 0;
  146. contentLength = 0;
  147. continue;
  148. }
  149. while (currentContentOffset < contentLength)
  150. {
  151. item = dataStorage.GetData();
  152. temp.Add(item);
  153. currentContentOffset++;
  154. }
  155. retry = 3;
  156. while (dataStorage.GetSize() < 2 && retry >= 0)
  157. {
  158. retry--;
  159. Thread.Sleep(100);
  160. }
  161. temp.Add(dataStorage.GetData());
  162. temp.Add(dataStorage.GetData());
  163. ProcessMsg(temp.ToArray());
  164. currentStep = MSG_RESOLVE_STEP.NONE;
  165. continue;
  166. }
  167. Thread.Sleep(5);
  168. }
  169. private void ProcessHeart(ICMSG_Heart_UP heartUpMsg)
  170. {
  171. IsConnected = OnLine;
  172. status["IceCreamIsConnected"] = OnLine;
  173. status["IceCreamCurrentMode"] = heartUpMsg.MS;
  174. status["IceCreamYLWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.YLWD_L, heartUpMsg.YLWD_H }, 0);
  175. status["IceCreamHQWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.HQWD_L, heartUpMsg.HQWD_H }, 0);
  176. status["IceCreamHJWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.HJWD_L, heartUpMsg.HJWD_H }, 0);
  177. status["IceCreamDL"] = BitConverter.ToInt16(new byte[] { heartUpMsg.DL_L, heartUpMsg.DL_H }, 0);
  178. status["IceCreamFault"] = (MORKI_FAULT)BitConverter.ToInt16(new byte[] { heartUpMsg.GZ_L, heartUpMsg.GZ_H }, 0);
  179. heartUpMsg.HasGZ(out string msg);
  180. status["IceCreamError"] = msg;
  181. status["IceCreamCXB"] = heartUpMsg.CXB;
  182. status["IceCreamDLCompleted"] = (heartUpMsg.DLTJ >> 4 & 1) == 1;
  183. if (RTrig.GetInstance("打料完成检测").Start((bool)status["IceCreamDLCompleted"]))
  184. {
  185. MessageLog.GetInstance.Show("打料完成");
  186. }
  187. if (RTrig.GetInstance("打料中检测").Start(!(bool)status["IceCreamDLCompleted"]))
  188. {
  189. MessageLog.GetInstance.Show("打料中");
  190. }
  191. Thread.Sleep(100);
  192. }
  193. private void ProcessModeUp(ICMSG_MODE_UP modeUpMsg)
  194. {
  195. MessageLog.GetInstance.Show(string.Format("模式返回为:{0}", modeUpMsg.Mode));
  196. }
  197. public void ProcessMsg(byte[] data)
  198. {
  199. lastRefreshTime = DateTime.Now;
  200. try
  201. {
  202. if (data.Length < 5)
  203. return;
  204. switch (data[2])
  205. {
  206. case (byte)IC_CMD.HEART:
  207. var msg = IcPack.ByteToStructure<ICMSG_Heart_UP>(data.ToArray());
  208. ProcessHeart(msg);
  209. break;
  210. case (byte)IC_CMD.MODE:
  211. var modeUp = IcPack.ByteToStructure<ICMSG_MODE_UP>(data.ToArray());
  212. ProcessModeUp(modeUp);
  213. break;
  214. }
  215. }
  216. catch (Exception ex)
  217. {
  218. }
  219. }
  220. protected override void InitStatus()
  221. {
  222. status["IceCreamYLWD"] = (short)0;
  223. status["IceCreamHQWD"] = (short)0;
  224. status["IceCreamHJWD"] = (short)0;
  225. status["IceCreamDL"] = (short)0;
  226. status["IceCreamDY"] = (short)0;
  227. status["IceCreamCurrentMode"] = MORKI_MODE.待机模式;
  228. status["IceCreamFault"] = MORKI_FAULT.未发生故障;
  229. status["IceCreamCXB"] = (byte)0;
  230. status["IceCreamCXB_Threshold"] = (byte)0;
  231. status["IceCreamDLCompleted"] = true;
  232. status["IceCreamIsConnected"] = false;
  233. }
  234. public override void Init()
  235. {
  236. //广深冰淇淋机模式设置
  237. commProxy = new SerialPortClient(communicationPar.SerialPort, (BaudRates)communicationPar.BaudRate);
  238. commProxy.SetDataStorage(dataStorage);
  239. EventBus.GetInstance().Subscribe<GSIceCream_ModeSetEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  240. {
  241. try
  242. {
  243. free = true;
  244. Thread.Sleep(200);
  245. var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(((GSIceCream_ModeSetEvent)@event).Mode));
  246. commProxy.SendData(data);
  247. Thread.Sleep(200);
  248. free = false;
  249. MessageLog.GetInstance.Show(string.Format("设置模式[{0}]", Enum.GetName(typeof(MORKI_MODE), ((GSIceCream_ModeSetEvent)@event).Mode)));
  250. }
  251. catch (Exception ex)
  252. {
  253. MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]");
  254. }
  255. });
  256. //广深冰淇淋机打料
  257. EventBus.GetInstance().Subscribe<GSIceCream_DischargeEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  258. {
  259. try
  260. {
  261. if ((MORKI_FAULT)status["IceCreamFault"] != MORKI_FAULT.未发生故障)
  262. {
  263. MessageLog.GetInstance.Show(string.Format("当前存在故障[{0}%],不允许制作", (MORKI_FAULT)status["IceCreamFault"]));
  264. new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish();
  265. callBack?.Invoke(false);
  266. return;
  267. }
  268. if ((byte)status["IceCreamCXB"] <= 86)
  269. {
  270. MessageLog.GetInstance.Show(string.Format("当前成型比[{0}%],低于86%,不允许制作", (byte)status["IceCreamCXB"]));
  271. new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish();
  272. callBack?.Invoke(false);
  273. return;
  274. }
  275. bool modeRight = (MORKI_MODE)status["IceCreamCurrentMode"] == MORKI_MODE.制冷模式;
  276. if (!modeRight)
  277. {
  278. free = true;
  279. Thread.Sleep(200);
  280. var temp = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.制冷模式));
  281. commProxy.SendData(temp);
  282. Thread.Sleep(200);
  283. free = false;
  284. MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]", MORKI_MODE.制冷模式));
  285. DateTime freeTime = DateTime.Now.AddSeconds(5);
  286. while (DateTime.Now < freeTime)
  287. {
  288. Thread.Sleep(10);
  289. modeRight = (MORKI_MODE)status["IceCreamCurrentMode"] == MORKI_MODE.制冷模式;
  290. if (modeRight)
  291. break;
  292. }
  293. }
  294. if (modeRight)
  295. {
  296. free = true;
  297. Thread.Sleep(200);
  298. var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.打料));
  299. commProxy.SendData(data);
  300. Thread.Sleep(200);
  301. free = false;
  302. new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = true }.Publish();
  303. MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]", MORKI_MODE.打料));
  304. callBack?.Invoke(true);
  305. }
  306. else
  307. {
  308. MessageLog.GetInstance.Show(string.Format("出料操作->模式切换失败,当前模式[{0}],不允许出料", (MORKI_MODE)status["IceCreamCurrentMode"]));
  309. new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish();
  310. callBack?.Invoke(false);
  311. }
  312. }
  313. catch (Exception ex)
  314. {
  315. MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]");
  316. callBack?.Invoke(false);
  317. }
  318. });
  319. InitStatus();
  320. //测试用
  321. Start();
  322. MessageLog.GetInstance.Show("冰淇淋机器初始化完成");
  323. }
  324. public override void WriteData(string address, object value)
  325. {
  326. }
  327. }
  328. }