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

IceCreamMachine.cs 14 KiB

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