using BPA.Helper; using BPASmartClient.Model; using BPASmartClient.Model.冰淇淋.Enum; using BPASmartClient.Peripheral; using BPASmartClient.SerialPort; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using static BPA.Helper.EventBus; using static BPASmartClient.GSIceCream.MessageDefine; namespace BPASmartClient.GSIceCream { public class IceCreamMachine : BasePeripheral { //通讯代理 SerialPortClient commProxy = null; //是否下发指令,主线程等待 private bool free = false; //心跳指令 private byte[] cmdHeartDW; //数据仓库 private DataStorage dataStorage = new DataStorage(); //串口COM口 public string PortName { get; set; } //串口波特率 public string BaudRate { get; set; } //心跳时间 private DateTime lastRefreshTime = DateTime.MinValue; //是否在线 public bool OnLine { get { return DateTime.Now.Subtract(lastRefreshTime).TotalSeconds <= 3; } } //private volatile static IceCreamMachine _Instance; //public static IceCreamMachine GetInstance => _Instance ?? (_Instance = new IceCreamMachine()); public IceCreamMachine() { ICMSG_Heart_DW heartDW = new ICMSG_Heart_DW(); cmdHeartDW = IcPack.StructureToByte(heartDW); } /// /// 主线程开始运行 /// public override void Start() { try { commProxy.Start(); free = false; MainLoop(); } catch (Exception ex) { MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]"); } } /// /// 停止运行 /// public override void Stop() { try { commProxy.Stop(); IsConnected = false; free = true; } catch (Exception ex) { MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]"); } } private MSG_RESOLVE_STEP currentStep; private void MainLoop() { TaskManage.GetInstance.StartLong(new Action(() => { if (!free) { commProxy.SendData(cmdHeartDW); } Thread.Sleep(500); }), "冰淇淋询问线程"); TaskManage.GetInstance.StartLong(new Action(() => { ResolveMsg(); }), "冰淇淋解析线程"); } int contentLength = 0; int currentContentOffset = 0; private void ResolveMsg() { List temp = new List(); //一系列解包 while (dataStorage.GetSize() > 0) { byte item = dataStorage.GetData(); switch (currentStep) { case MSG_RESOLVE_STEP.NONE: if (item == MessageDefine.HEADER1) { temp.Add(item); currentStep = MSG_RESOLVE_STEP.HEADER1; continue; } break; case MSG_RESOLVE_STEP.HEADER1: if (item == MessageDefine.HEADER2_UP) { temp.Add(item); currentStep = MSG_RESOLVE_STEP.HEADER2; continue; } else { temp.Clear(); currentStep = MSG_RESOLVE_STEP.NONE; continue; } case MSG_RESOLVE_STEP.HEADER2: switch ((IC_CMD)item) { case IC_CMD.HEART: temp.Add(item); contentLength = MessageDefine.MSG_LENGTH[(IC_CMD)item]; currentContentOffset = 0; currentStep = MSG_RESOLVE_STEP.CMD; break; default: temp.Clear(); currentStep = MSG_RESOLVE_STEP.NONE; break; } break; } int retry = 3; while (dataStorage.GetSize() < contentLength + 2 && retry >= 0) { retry--; Thread.Sleep(100); } if (retry < 0) { currentStep = MSG_RESOLVE_STEP.NONE; currentContentOffset = 0; contentLength = 0; continue; } while (currentContentOffset < contentLength) { item = dataStorage.GetData(); temp.Add(item); currentContentOffset++; } retry = 3; while (dataStorage.GetSize() < 2 && retry >= 0) { retry--; Thread.Sleep(100); } temp.Add(dataStorage.GetData()); temp.Add(dataStorage.GetData()); ProcessMsg(temp.ToArray()); currentStep = MSG_RESOLVE_STEP.NONE; continue; } Thread.Sleep(5); } private void ProcessHeart(ICMSG_Heart_UP heartUpMsg) { IsConnected = OnLine; status["IceCreamIsConnected"] = OnLine; status["IceCreamCurrentMode"] = heartUpMsg.MS; status["IceCreamYLWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.YLWD_L, heartUpMsg.YLWD_H }, 0); status["IceCreamHQWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.HQWD_L, heartUpMsg.HQWD_H }, 0); status["IceCreamHJWD"] = BitConverter.ToInt16(new byte[] { heartUpMsg.HJWD_L, heartUpMsg.HJWD_H }, 0); status["IceCreamDL"] = BitConverter.ToInt16(new byte[] { heartUpMsg.DL_L, heartUpMsg.DL_H }, 0); status["IceCreamFault"] = (MORKI_FAULT)BitConverter.ToInt16(new byte[] { heartUpMsg.GZ_L, heartUpMsg.GZ_H }, 0); heartUpMsg.HasGZ(out string msg); status["IceCreamError"] = msg; status["IceCreamCXB"] = heartUpMsg.CXB; status["IceCreamDLCompleted"] = (heartUpMsg.DLTJ >> 4 & 1) == 1; if (RTrig.GetInstance("打料完成检测").Start((bool)status["IceCreamDLCompleted"])) { MessageLog.GetInstance.Show("打料完成"); } if (RTrig.GetInstance("打料中检测").Start(!(bool)status["IceCreamDLCompleted"])) { MessageLog.GetInstance.Show("打料中"); } Thread.Sleep(100); } private void ProcessModeUp(ICMSG_MODE_UP modeUpMsg) { MessageLog.GetInstance.Show(string.Format("模式返回为:{0}", modeUpMsg.Mode)); } public void ProcessMsg(byte[] data) { lastRefreshTime = DateTime.Now; try { if (data.Length < 5) return; switch (data[2]) { case (byte)IC_CMD.HEART: var msg = IcPack.ByteToStructure(data.ToArray()); ProcessHeart(msg); break; case (byte)IC_CMD.MODE: var modeUp = IcPack.ByteToStructure(data.ToArray()); ProcessModeUp(modeUp); break; } } catch (Exception ex) { } } protected override void InitStatus() { status["IceCreamYLWD"] = (short)0; status["IceCreamHQWD"] = (short)0; status["IceCreamHJWD"] = (short)0; status["IceCreamDL"] = (short)0; status["IceCreamDY"] = (short)0; status["IceCreamCurrentMode"] = MORKI_MODE.待机模式; status["IceCreamFault"] = MORKI_FAULT.未发生故障; status["IceCreamCXB"] = (byte)0; status["IceCreamCXB_Threshold"] = (byte)0; status["IceCreamDLCompleted"] = true; status["IceCreamIsConnected"] = false; } public override void Init() { //广深冰淇淋机模式设置 commProxy = new SerialPortClient(communicationPar.SerialPort, (BaudRates)communicationPar.BaudRate); commProxy.SetDataStorage(dataStorage); EventBus.GetInstance.Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) { try { free = true; Thread.Sleep(200); var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(((GSIceCream_ModeSetEvent)@event).Mode)); commProxy.SendData(data); Thread.Sleep(200); free = false; MessageLog.GetInstance.Show(string.Format("设置模式[{0}]", Enum.GetName(typeof(MORKI_MODE), ((GSIceCream_ModeSetEvent)@event).Mode))); } catch (Exception ex) { MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]"); } }); //广深冰淇淋机打料 EventBus.GetInstance.Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) { try { if ((MORKI_FAULT)status["IceCreamFault"] != MORKI_FAULT.未发生故障) { MessageLog.GetInstance.Show(string.Format("当前存在故障[{0}%],不允许制作", (MORKI_FAULT)status["IceCreamFault"])); new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish(); callBack?.Invoke(false); return; } if ((byte)status["IceCreamCXB"] <= 86) { MessageLog.GetInstance.Show(string.Format("当前成型比[{0}%],低于86%,不允许制作", (byte)status["IceCreamCXB"])); new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish(); callBack?.Invoke(false); return; } bool modeRight = (MORKI_MODE)status["IceCreamCurrentMode"] == MORKI_MODE.制冷模式; if (!modeRight) { free = true; Thread.Sleep(200); var temp = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.制冷模式)); commProxy.SendData(temp); Thread.Sleep(200); free = false; MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]", MORKI_MODE.制冷模式)); DateTime freeTime = DateTime.Now.AddSeconds(5); while (DateTime.Now < freeTime) { Thread.Sleep(10); modeRight = (MORKI_MODE)status["IceCreamCurrentMode"] == MORKI_MODE.制冷模式; if (modeRight) break; } } if (modeRight) { free = true; Thread.Sleep(200); var data = IcPack.StructureToByte(ICMSG_MODE_DW.Build(MORKI_MODE.打料)); commProxy.SendData(data); Thread.Sleep(200); free = false; new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = true }.Publish(); MessageLog.GetInstance.Show(string.Format("出料操作->设置模式[{0}]", MORKI_MODE.打料)); callBack?.Invoke(true); } else { MessageLog.GetInstance.Show(string.Format("出料操作->模式切换失败,当前模式[{0}],不允许出料", (MORKI_MODE)status["IceCreamCurrentMode"])); new GSIceCream_EndCookEvent() { DeviceId = DeviceId, Status = false }.Publish(); callBack?.Invoke(false); } } catch (Exception ex) { MessageLog.GetInstance.ShowEx($"BPASmartClient.GSIceCream 中引发错误,IceCreamMachine 类,描述:[{ex.Message}]"); callBack?.Invoke(false); } }); InitStatus(); //测试用 Start(); MessageLog.GetInstance.Show("冰淇淋机器初始化完成"); } public override void WriteData(string address, object value) { } } }