using Edge.Core.Processor.Communicator; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HengshanPaymentTerminal { public class StateMachineMessageCutter : IMessageCutter { #region Internal State enum private enum State { Uninitialized, LengthReady, BodyReady, EtxReady, CrcReady } #endregion #region Fields public byte[] Message { get; private set; } public event EventHandler OnMessageCut; public event EventHandler OnInvalidMessageRead; private string loggerAppendix = "HengshanPay Terminal"; private readonly SizableWindow window; private State nextState = State.Uninitialized; private const int STX = 0xFA; #endregion #region Logger static NLog.Logger innerLogger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("Communicator"); #endregion public StateMachineMessageCutter() { window = new SizableWindow(); window.OnWindowFull += (data) => { Message = window.ToArray(); var safe = OnMessageCut; safe?.Invoke(this, null); nextState = State.Uninitialized; window.Clear(); //switch (nextState) //{ // case State.Uninitialized: // if (data.First() == STX) // { // window.NewSize = 6; // nextState = State.LengthReady; // } // else // { // OnInvalidMessageRead?.Invoke(this, new MessageCutterInvalidMessageReadEventArg() // { // Message = "invalid byte[0]: 0x" + data.First().ToString("x2") + ", will skip" // }); // window.Clear(); // } // break; // case State.LengthReady: // var countSTX = window.Count(b => b == STX); // if (countSTX > 1) // { // //Console.WriteLine($"0xFA count: {countSTX}"); // innerLogger.Info($"0xFA count: {countSTX}"); // int index = window.ToList().LastIndexOf(STX); // var tempArray = window.Skip(index).ToArray(); // window.Clear(); // nextState = State.Uninitialized; // Feed(tempArray); // return; // } // int bodyLen = window[4] * 10 + window[5]; // if (bodyLen > 256 || bodyLen < 2) // { // var safe8 = this.OnInvalidMessageRead; // safe8?.Invoke(this, new MessageCutterInvalidMessageReadEventArg() // { // Message = "Message body length is not valid, len is: " + bodyLen // }); // nextState = State.Uninitialized; // window.Clear(); // window.NewSize = 1; // return; // } // window.NewSize += bodyLen; // nextState = State.BodyReady; // break; // case State.BodyReady: // window.NewSize = window.Skip(4).Take(2).ToArray().ToInt32() + 6 + 3; // nextState = State.CrcReady; // break; // case State.CrcReady: // var stxCount = window.Count(b => b == STX); // if (stxCount > 1) // { // //Console.WriteLine($"0xFA count: {stxCount}"); // innerLogger.Info($"0xFA count: {stxCount}"); // int length = window.Count; // if (window[length - 3] == 0xFF) // { // //Console.WriteLine("ETX exists, consider it a complete message"); // innerLogger.Info("ETX exists, consider it a complete message"); // } // else // { // int index = window.ToList().LastIndexOf(STX); // if (index + 2 <= window.Count - 1) // { // byte trailingByte1 = window[index + 1]; // byte trailingByte2 = window[index + 2]; // if (trailingByte1 == trailingByte2 && trailingByte1 <= 6 && trailingByte1 > 0) // { // //Console.WriteLine("Possible mix of incompleted messages"); // innerLogger.Info("Possible mix of incompleted messages"); // var tempArray = window.Skip(index).ToArray(); // window.Clear(); // nextState = State.Uninitialized; // Feed(tempArray); // return; // } // } // } // } // Message = window.ToArray(); // var safe = OnMessageCut; // safe?.Invoke(this, null); // nextState = State.Uninitialized; // window.Clear(); // break; // default: // throw new ArgumentOutOfRangeException(); //} }; } public void Feed(byte[] data) { for (int i = 0; i < data.Length; i++) { window.Add(data[i]); } } private int Get0xFAPairCountInWindow(IEnumerable data) { return (int)Math.Round(((double)(data.Count(w => w == 0xFA)) / 2), MidpointRounding.AwayFromZero); } public int Reduce0xFAPair(IList target, int startIndex) { int reducedCount = 0; var faAppearedPositions = new List(); for (int i = startIndex; i < target.Count; i++) { if (target[i] == 0xFA) { if (i <= (target.Count - 2)) { if (target[i + 1] == 0xFA) { faAppearedPositions.Add(i); i++; } } } } for (int i = 0; i < faAppearedPositions.Count; i++) { target.RemoveAt(faAppearedPositions[i] - i); reducedCount++; } return reducedCount; } } }