using System; using System.Linq; using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump; using Edge.Core.Processor.Communicator; namespace Dfs.WayneChina.HengshanTerminalWrapper { public class StateMachineMessageCutter : IMessageCutter { public byte[] Message { get; private set; } public event EventHandler OnMessageCut; public event EventHandler OnInvalidMessageRead; static NLog.Logger innerLogger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("Communicator"); private string loggerAppendix = "HengshanICTerm msgCutter "; private readonly SizableWindow window; private State nextState = State.Uninitialized; /// /// Constructor /// public StateMachineMessageCutter() { //this.initWindowSize = initWindowSize; this.window = new SizableWindow(); this.window.OnWindowFull += (data) => { switch (nextState) { case State.Uninitialized: if (data.First() == 0xFF) { //前导码(0FFH) +长度(0-20H) this.window.NewSize = 2; this.nextState = State.LengthReady; //innerLogger.Debug(this.loggerAppendix + " state is State.Uninitialized and next is 0xFF, switch to LengthReady"); } else { this.OnInvalidMessageRead?.Invoke(this, new MessageCutterInvalidMessageReadEventArg() { Message = "invalid byte[0]: 0x" + data.First().ToString("x2") + ", will skip" }); this.window.Clear(); } break; case State.LengthReady: var lengthByte = this.window.Skip(1).First(); if (lengthByte > 0x20) { this.OnInvalidMessageRead?.Invoke(this, new MessageCutterInvalidMessageReadEventArg() { Message = "invalid lengthByte: 0x" + lengthByte.ToString("x2") + ", should <=0x20, still keep it" }); } // 1 is header 0xFF, another 1 is XRL this.window.NewSize = lengthByte + 2; this.nextState = State.BodyReady; break; case State.BodyReady: //innerLogger.Debug(this.loggerAppendix + " Fire OnMessageConstructed with innerQueue: " + this.buffer.ToHexLogString()); this.Message = this.window.ToArray(); var safe = this.OnMessageCut; safe?.Invoke(this, null); this.nextState = State.Uninitialized; this.window.Clear(); //this.window.NewSize = this.initWindowSize; break; default: throw new ArgumentOutOfRangeException(); } }; } private enum State { Uninitialized, //HeaderSeeking, //HeaderReady, LengthReady, BodyReady, } public void Feed(byte[] next) { //innerLogger.Debug(this.loggerAppendix + " " + next.ToHexLogString() + " is feed in Window in state: " + nextState); for (int i = 0; i < next.Length; i++) this.window.Add(next[i]); } } }