using Edge.Core.Processor.Communicator; using System; using System.Linq; namespace GasConcentrations_Yt95h { 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("StateMachineMessageCutter"); private string loggerAppendix = "Yt95hEx_Handler msgCutter"; private readonly SizableWindow window; private State nextState = State.Uninitialized; public StateMachineMessageCutter() { this.window = new SizableWindow(2); this.window.OnWindowFull += (data) => { switch (nextState) { case State.Uninitialized: if (0 < data[0] && data[0] <= 255) { if (data[1] == 3 || data[1] == 4) { this.nextState = State.LengthReady; this.window.NewSize += 1; innerLogger.Debug($"{this.loggerAppendix} state is State.Uninitialized, will switch to LengthReady"); } else if (data[1] == 6 || data[1] == 16) { this.nextState = State.DataAddressReady; this.window.NewSize += 2; innerLogger.Debug($"{this.loggerAppendix} state is State.Uninitialized, will switch to DataAddressReady"); } else { ReadInvalidMessage(); } } else { ReadInvalidMessage(); } break; case State.LengthReady: //this.DumpWindowToQueue(); this.nextState = State.BodyReady; this.window.NewSize += (data[2] + 2); // data[2] The number of data bytes to follow innerLogger.Debug($"{this.loggerAppendix} MsgBodyLen caculated with: {this.window.NewSize}"); break; case State.DataAddressReady: this.nextState = State.BodyReady; this.window.NewSize += 4; innerLogger.Debug($"{this.loggerAppendix} MsgBodyLen caculated with: {this.window.NewSize}"); break; case State.BodyReady: this.Message = this.window.ToArray(); var safe = this.OnMessageCut; safe?.Invoke(this, null); this.nextState = State.Uninitialized; this.window.Clear(); break; default: throw new ArgumentOutOfRangeException(); } }; } private enum State { Uninitialized, LengthReady, DataAddressReady, BodyReady, } private void ReadInvalidMessage() { this.Message = this.window.ToArray(); var safeHandler = this.OnInvalidMessageRead; safeHandler?.Invoke(this, null); this.window.Clear(); } public void Feed(byte[] next) { for (int i = 0; i < next.Length; i++) { window.Add(next[i]); } } } }