123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
- using Edge.Core.Processor.Communicator;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace Dfs.WayneChina.HengshanPayTerminal
- {
- public class StateMachineMessageCutter : IMessageCutter<byte[]>
- {
- #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<MessageCutterInvalidMessageReadEventArg> OnInvalidMessageRead;
- private string loggerAppendix = "HengshanPay Terminal";
- private readonly SizableWindow<byte> 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<byte>();
- window.OnWindowFull += (data) =>
- {
- 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<byte> data)
- {
- return (int)Math.Round(((double)(data.Count(w => w == 0xFA)) / 2), MidpointRounding.AwayFromZero);
- }
- public int Reduce0xFAPair(IList<byte> target, int startIndex)
- {
- int reducedCount = 0;
- var faAppearedPositions = new List<int>();
- 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;
- }
- }
- }
|