123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927 |
- using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
- using Edge.Core.Parser.BinaryParser.Util;
- using SinochemCarplateService.Models;
- using SinochemCloudClient.Models;
- using SinochemPosClient.Models;
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using Wayne.Lib.StateEngine;
- using WayneChina_IcCardReader_SinoChem.MessageEntity;
- using WayneChina_IcCardReader_SinoChem.MessageEntity.Incoming;
- using WayneChina_IcCardReader_SinoChem.MessageEntity.Outgoing;
- using Edge.Core.IndustryStandardInterface.Pump;
- namespace SinochemInternetPlusApp
- {
- public class ReceiptLine
- {
- public ReceiptLine(byte[] bytes, int lineWidth)
- {
- Line = new byte[lineWidth];
- bytes.CopyTo(Line, 0);
- }
- public byte[] Line { get; set; }
- }
- public class FuelingPoint : StateManager
- {
- #region Fields
- //Immutable after construction
- public int FuelingPointId { get; }
- private byte initialSqNo = 0;
- private byte sqNo;
- private object syncObj = new object();
- private Queue<IcCardReaderMessageBase> outboundMsgQueue = new Queue<IcCardReaderMessageBase>();
- private object queueSyncObj = new object();
- private object evSyncObj = new object();
- private List<int> requestIdList = new List<int>();
- private object reqIdSyncObj = new object();
- private bool printerIdle = true;
- private object printerSyncObj = new object();
- private byte currentSqNo { get; set; }
- private object sqNoSyncObj = new object();
- private IFdcPumpController callingPump;
- #endregion
- #region Timeout values
- //in seconds
- public int CardReaderDisplayTimeout { get { return 10; } }
- //in milliseconds
- public int CardReaderBackToIdleTimeout { get { return 2000; } }
- #endregion
- #region Properties
- /// <summary>
- /// Current physical nozzle id, reflecting the running nozzle of this FP.
- /// </summary>
- public int CurrentNozzleId { get; set; }
- /// <summary>
- /// The physical nozzles associated with this fueling point
- /// </summary>
- public IEnumerable<int> AssociatedNozzles { get; set; }
- public Eps Eps { get; set; }
- public EpsTransaction CurrentEpsTrx { get; set; }
- public TransactionMode CurrentTrxMode { get; set; }
- public long? AuthorizationId { get; set; }
- public byte ResetSqNo;
- public override string EntityType => "FuelingPoint";
- public override string EntitySubType => "";
- public IEnumerable<EpsTransactionModel> ActiveTrx { get; set; }
- public CardOnlineVerificationRequest OnlineVerificationRequest { get; set; }
- public WayneChina_IcCardReader_SinoChem.Handler CurrentCardReader => Eps.GetHandler(FuelingPointId);
- public SignDataResponse SignedData { get; internal set; }
- public List<ReceiptLine> CurrentReceipt { get; set; }
- public bool CardReaderDisabled { get; set; } = false;
- public byte IdleStateCardReaderSqNo { get; set; }
- public int GetPrinterCount { get; set; }
- /// <summary>
- /// Site id aka Station number
- /// </summary>
- public string StationNo => App.AppSettings["SinochemSiteId"];
- /// <summary>
- /// Site name aka Station name
- /// </summary>
- public string StationName => App.AppSettings["SinochemSiteName"];
- private bool printReceiptEnabled => Convert.ToBoolean(App.AppSettings["PrintReceiptEnabled"]);
- private bool printQRCodeEnabled => Convert.ToBoolean(App.AppSettings["PrintQrCodeOnReceiptEnabled"]);
- #endregion
- #region Request Id operations
- public void AddRequestId(int reqIid)
- {
- lock (reqIdSyncObj)
- {
- requestIdList.Add(reqIid);
- }
- }
- public void RemoveRequestId(int reqIid)
- {
- lock (reqIdSyncObj)
- {
- requestIdList.Remove(reqIid);
- }
- }
- public bool ContainsRequestId(int reqIid)
- {
- lock (reqIdSyncObj)
- {
- return requestIdList.Contains(reqIid);
- }
- }
- public void ClearAllRequestIds()
- {
- lock (reqIdSyncObj)
- {
- foreach (var id in requestIdList)
- {
- debugLogger.Add($"Clearing RequestId: {id}");
- }
- requestIdList.Clear();
- }
- }
- #endregion
- #region Constructor
- public FuelingPoint(int nozzleId, IEnumerable<int> associatedNozzles, Eps eps) : base(nozzleId, "FuelingPoint")
- {
- FuelingPointId = nozzleId;
- AssociatedNozzles = associatedNozzles;
- Eps = eps;
- }
- #endregion
- #region DB & Trx handling
- /// <summary>
- /// Create an eps trx given the mop type.
- /// </summary>
- /// <param name="mop"></param>
- internal void CreateEpsTransaction(TransactionMode mop)
- {
- CurrentEpsTrx = EpsTransaction.CreateEpsTrx(CurrentNozzleId, mop, debugLogger);
- }
- internal void LockTrxInXiaofei2AsEpsTrx()
- {
- if (CurrentEpsTrx.MoveFromXiaofei2())
- {
- }
- else
- {
- debugLogger.Add("trx in xiaofei2 not found!!!!");
- }
- }
- #endregion
- #region Cloud & POS interactions
- internal void NotifyPosAync()
- {
- ThreadPool.QueueUserWorkItem(_ =>
- {
- TrxNotificationResponse response = Eps.NotifySuccessfulTrxToPos(CurrentEpsTrx.Model, debugLogger);
- if (response != null && response.IsSuccessful())
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.PosNotifyOk));
- }
- else
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.PosNotifyFailed));
- }
- });
- }
- internal void SendPaymentToCloudAsync()
- {
- ThreadPool.QueueUserWorkItem(_ =>
- {
- PaymentResponse response = Eps.SendPaymentToCloud(CurrentEpsTrx.Model, debugLogger);
- if (response != null && response.IsSuccessful())
- {
- stateMachine.IncomingEvent(GenericEvent.Create(EventType.CloudPaymentOk, this, response));
- }
- else
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.CloudPaymentFailed));
- }
- });
- }
- internal void SendBalanceQueryToCloudAsync(string cardNo, string encryptedPin, string tid, int nozzleId)
- {
- ThreadPool.QueueUserWorkItem(_ =>
- {
- BalanceInquiryResponse response = Eps.SendBalanceInquiryToCloud(cardNo, encryptedPin, tid, nozzleId, debugLogger);
- if (response != null && response.IsSuccessful())
- {
- stateMachine.IncomingEvent(GenericEvent.Create(EventType.CloudBalanceOk, this, response));
- }
- else
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.CloudBalanceFailed));
- }
- });
- }
- #endregion
- #region Pump interactions
- internal void AuthorizePumpAsync(decimal authAmount)
- {
- Eps.AuthorizePumpAsync(callingPump, CurrentNozzleId, authAmount);
- }
- internal List<int> GetAllNozzlesOnThisSide()
- {
- List<int> nozzles = new List<int>();
- foreach (var fp in CurrentCardReader.SupportedNozzles)
- {
- var fuelingPoint = this.Eps.GetFuelingPoint(fp);
- if (fuelingPoint != null)
- nozzles.AddRange(fuelingPoint.AssociatedNozzles);
- }
- return nozzles;
- }
- #endregion
- #region Eps state config and signal
- protected override void ConfigStates()
- {
- States.CONFIGURATION.Config(stateMachine.StateTransitionLookup);
- }
- public void SignalShutdown()
- {
- Console.Out.WriteLine("SignalShutdown");
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.ShutdownRequest));
- }
- public void FinalStateReached(string name)
- {
- Console.Out.WriteLine(name + " FinalStateReached");
- }
- #endregion
- #region Card Plate
- public void SignalNewCarplate(CarPlateTrxRequest request)
- {
- lock (evSyncObj)
- {
- if (request != null && AssociatedNozzles.Contains(Convert.ToInt32(request.gun)))
- {
- debugLogger.AddIfActive
- ($"New car plate info arrived: Gun: {request.gun}, License plate No: {request.car_Number}, Balance: {request.amount}");
- stateMachine.IncomingEvent(GenericEvent.Create(EventType.CarPlateScanned, this, request));
- }
- }
- }
- #endregion
- #region Display on dispenser interactions
- public void SignalDisplayResponseReceived(DisplayResponse response)
- {
- debugLogger.AddIfActive("DisplayResponse from big screen");
- stateMachine.IncomingEvent(new GenericEvent<DisplayResponseEventArgs>(
- EventType.DisplayResponseReceived, this, new DisplayResponseEventArgs(response)));
- }
- public void SignalTrxOpRequest(TransactionOperation request)
- {
- debugLogger.AddIfActive($"Transaction operation request from big screen, Trx id: {request.TrxId}");
- stateMachine.IncomingEvent(new GenericEvent<TransactionOperationEventArgs>(EventType.TrxOpRequest, this, new TransactionOperationEventArgs(request)));
- }
- #endregion
- #region Card reader signals
- public void SingalAckReceived(ACK cardReaderMessage)
- {
- lock (sqNoSyncObj)
- {
- if (cardReaderMessage.MessageSeqNumber == currentSqNo)
- {
- debugLogger.AddIfActive($"Received card reader message with MsgSqNo = {cardReaderMessage.MessageSeqNumber}");
- outboundMsgQueue.Dequeue();
- debugLogger.AddIfActive($"Removed the message from the queue");
- }
- }
- stateMachine.IncomingEvent(new GenericEvent<CardReaderAckEventArgs>(EventType.CardReaderAck, this, new CardReaderAckEventArgs(cardReaderMessage)));
- }
- public void SignalCardReaderDisconnected()
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.CardReaderDisconnected));
- }
- public void SignalCardReaderDisabled()
- {
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.ICCardReaderDisabled));
- }
- public void SignalCardReaderHeartbeat(HeartBeat heartBeat)
- {
- SendNextCardReaderMessage();
- }
- public void SignalSignedDataArrived(SignDataResponse cardReaderMessage)
- {
- debugLogger.AddIfActive("sending ack for SignDataResponse");
- SendAckToCardReader(cardReaderMessage.SourceAddress, cardReaderMessage.MessageSeqNumber);
- stateMachine.IncomingEvent(new GenericEvent<SignedDataEventArgs>(EventType.DataSigned, this, new SignedDataEventArgs(cardReaderMessage)));
- }
- public void SingalCardReaderStateEvent(CardReaderStateEvent cardReaderStateEvent)
- {
- debugLogger.AddIfActive($"CardReaderStateEvent \n source address: {cardReaderStateEvent.SourceAddress} \n SqNo: {cardReaderStateEvent.MessageSeqNumber} \n Reader state: {cardReaderStateEvent.State.ToString()}");
- SendAckToCardReader(cardReaderStateEvent.SourceAddress, cardReaderStateEvent.MessageSeqNumber);
- stateMachine.IncomingEvent(new GenericEvent<CardReaderStateEventArgs>(EventType.ReaderStateChanged, this, new CardReaderStateEventArgs(cardReaderStateEvent)));
- }
- private void SendAckToCardReader(byte srcAddress, byte sqNo)
- {
- ACK ack = new ACK { SourceAddress = srcAddress, MessageSeqNumber = sqNo };
- if (CurrentCardReader != null)
- CurrentCardReader.Write(ack);
- }
- public void SignalCardExternalCheckFailure(CardExternalCheckErrorRequest cardReaderMessage)
- {
- debugLogger.AddIfActive($"IC Card check failure, Error reason: {cardReaderMessage.ErrorType.ToString()}");
- SendAckToCardReader(cardReaderMessage.SourceAddress, cardReaderMessage.MessageSeqNumber);
- stateMachine.IncomingEvent(new GenericEvent<ExternalCheckFailedEventArgs>(EventType.ExternalCheckFailure, this, new ExternalCheckFailedEventArgs(cardReaderMessage)));
- }
- public void SignalCardOnlineVerification(CardOnlineVerificationRequest cardReaderMessage)
- {
- debugLogger.AddIfActive($"IC Card online verification request, Card No: {cardReaderMessage.CardNo}, Encrypted PIN: {cardReaderMessage.EncryptedPIN}, TID: {cardReaderMessage.TID}");
- SendAckToCardReader(cardReaderMessage.SourceAddress, cardReaderMessage.MessageSeqNumber);
- stateMachine.IncomingEvent(new GenericEvent<CardOnlineVerificationEventArgs>(EventType.OnlineVerification, this, new CardOnlineVerificationEventArgs(cardReaderMessage)));
- }
- #endregion
- #region Pump signals
- internal void SignalNozzleLifted(IFdcPumpController callingPump, int sitewiseNozzleId)
- {
- debugLogger.Add("SignalNozzleLifted, nozzleid -- " + sitewiseNozzleId);
- this.callingPump = callingPump;
- stateMachine.IncomingEvent(
- new GenericEvent<NozzleLiftedEventArgs>(
- EventType.NozzleLifted,
- this,
- new NozzleLiftedEventArgs() { NozzleId = sitewiseNozzleId }));
- }
- internal void SignalNozzleReplaced(int sitewiseNozzleId)
- {
- debugLogger.Add("SignalNozzleReplaced, nozzleid -- " + sitewiseNozzleId);
- stateMachine.IncomingEvent(
- new GenericEvent<NozzleReplacedEventArgs>(
- EventType.NozzleReplaced,
- this,
- new NozzleReplacedEventArgs() { NozzleId = sitewiseNozzleId }));
- }
- internal void SignalAuthOk(long? authId)
- {
- debugLogger.Add("SignalAuthOk -- " + authId);
- AuthorizationId = authId;
- var arg = new GenericEventArg<string>(DateTime.Now.ToString("HH:mm:ss"));
- stateMachine.IncomingEvent(GenericEvent.Create(EventType.PumpAuthOk, this, arg));
- }
- internal void SignalAuthFailed()
- {
- debugLogger.Add("SignalAuthFailed");
- stateMachine.IncomingEvent(new StateEngineEvent(EventType.PumpAuthFailed));
- }
- internal void SignalFuelingDone(int nozzleId, int seqNum, decimal fuelAmount, decimal fuelingQty, long authId)
- {
- debugLogger.Add("SignalFuelingDone -- " + authId);
- stateMachine.IncomingEvent(new GenericEvent<FuelingDoneEventArgs>(EventType.FuelingDone, this,
- new FuelingDoneEventArgs
- {
- NozzleId = nozzleId,
- FuelingSqNo = seqNum,
- Amount = fuelAmount,
- Quantity = fuelingQty,
- AuthId = authId
- }));
- }
- #endregion
- #region Card reader support
- /// <summary>
- /// Sender side's sequence number, 01H-0FH, when program restarted, use 00H.
- /// </summary>
- /// <returns>The sequence number byte.</returns>
- public byte GetSenderSideSqNo()
- {
- lock (syncObj)
- {
- if (initialSqNo == 0)
- {
- sqNo = initialSqNo;
- initialSqNo = 1;
- return sqNo;
- }
- byte nextSqNo = (byte)(sqNo++ % 16);
- if (nextSqNo == 0)
- {
- sqNo++;
- return initialSqNo;
- }
- return nextSqNo;
- }
- }
- public byte CardReaderSrcAddr
- {
- get
- {
- return (byte)(CurrentCardReader?.GetAddressForNozzleId(FuelingPointId));
- }
- }
- public void SendCommand(IcCardReaderMessageBase command, out byte sqNo)
- {
- command.MessageSeqNumber = GetSenderSideSqNo();
- command.SourceAddress = CardReaderSrcAddr;
- sqNo = command.MessageSeqNumber;
- PendMessage(command);
- }
- public void PendMessage(IcCardReaderMessageBase msg)
- {
- lock (queueSyncObj)
- {
- outboundMsgQueue.Enqueue(msg);
- }
- }
- public void SendNextCardReaderMessage()
- {
- lock (queueSyncObj)
- {
- if (outboundMsgQueue.Count > 0)
- {
- var msgToSend = outboundMsgQueue.Peek();
- lock (sqNoSyncObj)
- {
- currentSqNo = msgToSend.MessageSeqNumber;
- }
- debugLogger.AddIfActive($"Peek and send Card reader message {msgToSend.GetType().ToString()} with MsgSqNo = {msgToSend.MessageSeqNumber}");
- CurrentCardReader?.Write(msgToSend);
- }
- else
- {
- var eot = new EOT
- {
- SourceAddress = CardReaderSrcAddr,
- MessageSeqNumber = 0
- };
-
- CurrentCardReader?.Write(eot);
- }
- }
- }
- #endregion
- #region Receipt
- public void BuildReceipt()
- {
- if (CurrentReceipt == null)
- CurrentReceipt = new List<ReceiptLine>();
- else
- CurrentReceipt.Clear();
- List<string> bodyLines = new List<string>();
- List<string> header = new List<string>();
- List<string> product = new List<string>();
- List<string> payment = new List<string>();
- ReceiptModel receiptModel = ReceiptModelBuilder.BuildReceiptModel(CurrentEpsTrx, CurrentTrxMode);
- string lineSeparator = "------------------------------";
- string emptyLine = " ";
- string receiptHeaderReceiptType = string.Format($" {receiptModel.TrxModeName}小票 ");
- string stationName = "油站名称:" + StationName;
- string trxTimeStamp = "时间:" + Utilities.ConvertDateTimeToReadble(DateTime.Now);
- string runningNumberLine = "流水号:" + receiptModel.RunningNumber;
- string cardNoLine = "卡号:" + receiptModel.CardNo;
- string gradeNameLine = "油品:" + receiptModel.GradeName;
- string nozzleIdLine = "枪号:" + receiptModel.NozzleId;
- string ppuLine = "单价:" + receiptModel.PPU + "元/升";
- string qtyLine = "数量:" + receiptModel.Qty + "升";
- string amountLine = "金额:" + receiptModel.Amount + "元";
- string dueAmountLine = string.Format($"应付: {receiptModel.DueAmount}元");
- string discountLine = string.Format($"优惠: {receiptModel.DiscountAmount}元");
- string payAmountLine = string.Format($"实付: {receiptModel.PayAmount}元");
- header.Add(receiptHeaderReceiptType);
- header.Add(emptyLine);
- header.Add(stationName);
- header.Add(trxTimeStamp);
- header.Add(runningNumberLine);
- header.Add(cardNoLine);
- header.Add(lineSeparator);
- //Add header
- bodyLines.AddRange(header);
- product.Add(gradeNameLine);
- product.Add(nozzleIdLine);
- product.Add(ppuLine);
- product.Add(qtyLine);
- product.Add(amountLine);
- product.Add(lineSeparator);
- //Add product details
- bodyLines.AddRange(product);
- payment.Add(dueAmountLine);
- payment.Add(discountLine);
- payment.Add(payAmountLine);
- payment.Add(lineSeparator);
-
- //Add payment details
- bodyLines.AddRange(payment);
- //QR code
- if (printQRCodeEnabled)
- {
- string invoicePromptLine = string.Format(" 如需发票,请扫描二维码 ");
- bodyLines.Add(invoicePromptLine);
- bodyLines.Add(emptyLine);
- }
- //Thanks line
- string thanksLine = " 谢谢惠顾,欢迎再次光临 ";
- CreateReceiptLine(bodyLines);
- if (printQRCodeEnabled)
- {
- debugLogger.Add("EInvocie URL: " + receiptModel.InvoiceUrl);
- CreateQRCode(receiptModel.InvoiceUrl);
- //CreateQRCode("http://invoicetest-invoicetest-invoicetest-invoicetest-invoicetest-invoicetestinvoicetest.com/orderno=12345678901234567890123456789012345678901234567890");
- }
- CreateReceiptEnd(thanksLine);
- }
- private void CreateReceiptLine(List<string> lines)
- {
- List<byte> targetBytes = new List<byte>();
- foreach (var line in lines)
- {
- var bytes = Encoding.GetEncoding("GB2312").GetBytes(line);
- targetBytes.Add(0x01);
- targetBytes.AddRange(EnsureLength(bytes));
- CurrentReceipt.Add(new ReceiptLine(targetBytes.ToArray(), 31));
- targetBytes.Clear();
- }
- }
- private void CreateQRCode(string url)
- {
- int frameLen = 80;
- byte[] source = Encoding.ASCII.GetBytes(url);
- List<byte> target = new List<byte>();
- if (source.Length <= frameLen)
- {
- byte[] buffer = new byte[source.Length];
- Buffer.BlockCopy(source, 0, buffer, 0, source.Length);
- target.Add(0x04);
- target.AddRange(buffer);
- CurrentReceipt.Add(new ReceiptLine(target.ToArray(), source.Length + 1));
- target.Clear();
- }
- else
- {
- for (int i = 0; i < source.Length; i += frameLen)
- {
- if (source.Length - i < frameLen)
- {
- byte[] buffer = new byte[source.Length - i];
- Buffer.BlockCopy(source, i, buffer, 0, source.Length - i);
- target.Add(0x04);
- target.AddRange(buffer);
- CurrentReceipt.Add(new ReceiptLine(target.ToArray(), source.Length - i + 1));
- }
- else
- {
- byte[] buffer = new byte[frameLen];
- Buffer.BlockCopy(source, i, buffer, 0, frameLen);
- target.Add(0x03);
- target.AddRange(buffer);
- CurrentReceipt.Add(new ReceiptLine(target.ToArray(), frameLen + 1));
- }
- target.Clear();
- }
- }
- }
- private void CreateReceiptEnd(string endLine)
- {
- List<byte> targetBytes = new List<byte>();
- var bytes = Encoding.GetEncoding("GB2312").GetBytes(endLine);
- targetBytes.Add(0x02);
- targetBytes.AddRange(bytes);
- CurrentReceipt.Add(new ReceiptLine(targetBytes.ToArray(), 31));
- targetBytes.Clear();
- }
- private byte[] EnsureLength(byte[] bytes)
- {
- if (bytes.Length < 30)
- {
- List<byte> targetBytes = new List<byte>();
- targetBytes.AddRange(bytes);
- for (int i = 0; i < 30 - bytes.Length; i++)
- {
- targetBytes.Add(0x20);
- }
- return targetBytes.ToArray();
- }
- else
- {
- return bytes.Take(30).ToArray();
- }
- }
- public byte[] GetNextReceiptLine(int i)
- {
- debugLogger.Add("nfe current i = " + i);
- debugLogger.Add("nfe total count = " + CurrentReceipt.Count);
- if (i <= CurrentReceipt.Count - 1)
- return CurrentReceipt.ElementAt(i).Line;
- return null;
- }
- #endregion
- #region Card reader trx handling
- public void SetICCardReaderToCarPlateIdle(out byte sqNo)
- {
- StartFuelPresetProcessRequest setCardReaderToIdle = new StartFuelPresetProcessRequest(StartFuelPresetProcessReason.CarPlatePaymentIsInProcessing)
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = setCardReaderToIdle.MessageSeqNumber;
- PendMessage(setCardReaderToIdle);
- }
- public void NotifyCardReaderTrxDone(out byte sqNo)
- {
- NotifyTransactionIsDoneRequest trxDoneRequest = new NotifyTransactionIsDoneRequest()
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = trxDoneRequest.MessageSeqNumber;
- PendMessage(trxDoneRequest);
- }
- public void CloseICCardReader(out byte sqNo)
- {
- CloseCardReaderRequest closeCardReader = new CloseCardReaderRequest
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = closeCardReader.MessageSeqNumber;
- PendMessage(closeCardReader);
- }
- public void OpenCardReader(out byte? sqNo)
- {
- OpenCardReaderRequest openCardReader = new OpenCardReaderRequest
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = openCardReader.MessageSeqNumber;
- PendMessage(openCardReader);
- }
- public void SendICCardDisplay(string carPlate, out byte sqNo)
- {
- string licenseNo = carPlate;
- byte[] newbytes = new byte[64];
- for (int i = 0; i < 64; i++)
- {
- newbytes[i] = 0x20;
- }
- byte[] bytes = Encoding.GetEncoding("gb2312").GetBytes(licenseNo);
- if (bytes.Count() < 64)
- bytes.CopyTo(newbytes, 0);
- DisplayRequest displayRequest = new DisplayRequest(newbytes, CardReaderDisplayTimeout)
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = displayRequest.MessageSeqNumber;
- PendMessage(displayRequest);
- }
- public byte[] GetMAC(EpsTransactionModel epsTrxModel)
- {
- debugLogger.AddIfActive($"fuel amount: {epsTrxModel.amount}");
- debugLogger.AddIfActive($"fuel quantity: {epsTrxModel.qty}");
- string cardNo = epsTrxModel.card_no;// "8888118001000078417";
- string carPlate = string.IsNullOrEmpty(epsTrxModel.car_number) ? "晋A12345" : epsTrxModel.car_number;
- byte[] chsByte = Encoding.Unicode.GetBytes(carPlate[0].ToString());
- byte[] b1 = { chsByte[1], chsByte[0] };
- string asciiBytes = carPlate.Substring(1, 6).PadRight(8, ' ');
- byte[] b2 = Encoding.ASCII.GetBytes(asciiBytes);
- byte[] newBytes = new byte[b1.Length + b2.Length];
- b1.CopyTo(newBytes, 0);
- b2.CopyTo(newBytes, 2);
- if (string.IsNullOrEmpty(epsTrxModel.car_number))
- newBytes = new byte[10] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
- string ts = epsTrxModel.created_time.ToString("yyyyMMddHHmmss");//"20180425110509";
- double fuelAmount = epsTrxModel.amount;//10.00;
- double fuelVolume = epsTrxModel.qty;//1.00;
- int nozzleNumber = epsTrxModel.jihao;
- string tid = epsTrxModel.tid;//"111001000633";
- var targetSignBytes = cardNo.PadLeft(20, '0').ToBCD()
- .Concat(newBytes)
- .Concat(ts.ToBCD()
- .Concat(((int)((decimal)fuelAmount * 100)).GetBinBytes(4))
- .Concat(((int)((decimal)fuelVolume * 100)).GetBinBytes(4))
- .Concat(nozzleNumber.GetBCDBytes(2)));
- return targetSignBytes.ToArray();
- //string cardNumber = "08888118001000078417";//carPlateTrxRequest.card_No;
- ////string carPlate = Encoding.GetEncoding("gbk").GetString(Encoding.GetEncoding("gbk").GetBytes("晋A12345"));//carPlateTrxRequest.car_Number));
- //string carPlate = "晋A12345";
- //byte[] b = Encoding.Unicode.GetBytes(carPlate[0].ToString());
- //byte[] b1 = { b[1], b[0] };
- //string sss = carPlate.Substring(0, 6).PadRight(8, ' ');
- //byte[] b2 = Encoding.ASCII.GetBytes(sss);
- //byte[] newBytes = new byte[b1.Length + b2.Length];
- //b1.CopyTo(newBytes, 0);
- //b2.CopyTo(newBytes, 2);
- //string ts = "20180425110509";
- //DateTime fuelingTime = DateTime.Now;
- //int fuelAmount = 10;
- //int fuelVolume = 1;
- //int nozzleNumber = 2;
- //var targetSignBytes = cardNumber.PadRight(20, ' ').ToBCD()
- // .Concat(newBytes)
- // //.Concat(Encoding.GetEncoding("gbk").GetBytes(carPlate))
- // .Concat(ts.ToBCD()// fuelingTime.ToString("yyyyMMddHHmmss"))
- // .Concat(fuelAmount.GetBinBytes(4))
- // .Concat(fuelVolume.GetBinBytes(4))
- // .Concat(nozzleNumber.GetBCDBytes(2)));
- //return targetSignBytes.ToArray();
- //string cardNumber = carPlateTrxRequest.card_No;
- //string carPlate = Encoding.GetEncoding("gbk").GetString(Encoding.GetEncoding("gbk").GetBytes(carPlateTrxRequest.car_Number));
- //DateTime fuelingTime = DateTime.Now;
- //int fuelAmount = 99;
- //int fuelVolume = 14;
- //int nozzleNumber = 1;
- //var targetSignBytes = cardNumber.PadRight(20, ' ').ToBCD()
- // .Concat(Encoding.GetEncoding("gbk").GetBytes(carPlate))
- // .Concat(ASCIIEncoding.ASCII.GetBytes(fuelingTime.ToString("yyyyMMddHHmmss"))
- // .Concat(fuelAmount.GetBinBytes(4))
- // .Concat(fuelVolume.GetBinBytes(4))
- // .Concat(nozzleNumber.GetBCDBytes(2)));
- //var expected = new byte[] { 0xFA, 0xD2, }.Concat((targetSignBytes.Count() + 1).GetBCDBytes(2))
- // .Concat(new byte[] { 0x05 })
- // .Concat(targetSignBytes)
- // .Concat(new byte[] { 0x84, 0xb0 });
- var signDataRequest = new SignDataRequest(targetSignBytes.ToArray())
- {
- MessageSeqNumber = GetSenderSideSqNo(),
- SourceAddress = CardReaderSrcAddr
- };
- sqNo = signDataRequest.MessageSeqNumber;
- PendMessage(signDataRequest);
- }
- #endregion
- #region Printer
- public bool GetPrinter()
- {
- lock (printerSyncObj)
- {
- if (printerIdle == true)
- {
- printerIdle = false;
- return true;
- }
- else
- {
- GetPrinterCount++;
- return false;
- }
- }
- }
- public void ReleasePrinter()
- {
- lock (printerSyncObj)
- {
- printerIdle = true;
- }
- }
- #endregion
- #region Cleanup
- public void Cleanup()
- {
- CurrentEpsTrx = null;
- CurrentTrxMode = TransactionMode.Unknown;
- AuthorizationId = null;
- CurrentNozzleId = Eps.InvalidNozzleId;
- GetPrinterCount = 0;
- }
- #endregion
- }
- }
|