123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- using Edge.Core.Configuration;
- using Edge.Core.IndustryStandardInterface.Pump;
- using Edge.Core.Parser.BinaryParser.Util;
- using Edge.Core.Processor;
- using Edge.Core.Processor.Communicator;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using HengShan_Pump_TQC_IFSF.MessageEntity;
- using HengShan_Pump_TQC_IFSF.MessageEntity.Incoming;
- using HengShan_Pump_TQC_IFSF.MessageEntity.Outgoing;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Xml;
- using Wayne.FDCPOSLibrary;
- using Timer = System.Timers.Timer;
- namespace HengShan_Pump_TQC_IFSF
- {
- /// <summary>
- /// DIT ifsf pump has some different with TQC ifsf.
- /// 1. DIT support multiple ifsf node(one fp is a node) in single communicator, thus in a pumpGroup, multiple pumps could have different ifsf node value.
- /// 2. DIT pump's fuel product code is specified in a pump side.
- /// further more, there're 2 types of DIT, one can change code by web page, another one, looks pretty much the same as
- /// TCP IFSF TQC, could not support web page config, then have to do it at the dispenser keyboard, the FCC could not change it,
- /// sometimes, though the request and response can go through, actually no change in pump side.
- /// thus, need align FCC's product config before run FCC.
- /// </summary>
- [MetaPartsRequired(typeof(GenericDeviceProcessor<,>))]
- [MetaPartsRequired(typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>))]
- [MetaPartsRequired(typeof(IfsfMessageBase))]
- [MetaPartsDescriptor(
- "lang-zh-cn:HS DIT TQC加油机lang-en-us:HS DIT TQC pump",
- "lang-zh-cn:用于驱动基于TCP连接的IFSF协议的 恒山-DIT 加油机lang-en-us:Used for driven HengShan-DIT dispensers which using IFSF protocol on TCP",
- new[] { "lang-zh-cn:加油机lang-en-us:Pump" })]
- public class DitPumpGroupHandler : IEnumerable<IFdcPumpController>, IDeviceHandler<byte[], IfsfMessageBase>
- {
- #region Ctor parameters
- public class PumpGroupConfiguration
- {
- //public byte AmountDecimalDigits { get; set; }
- //public byte VolumeDecimalDigits { get; set; }
- //public byte PriceDecimalDigits { get; set; }
- //public byte VolumeTotalizerDecimalDigits { get; set; }
- public byte FccIfsfSubnetValue { get; set; }
- public byte FccIfsfNodeValue { get; set; }
- /// <summary>
- /// all pumps in this group share one SubNet value
- /// </summary>
- public byte PumpGroupIfsfSubnetValue { get; set; }
- public List<PumpConfiguration> PumpConfigurations { get; set; }
- }
- public class PumpConfiguration
- {
- public byte PumpIfsfNodeValue { get; set; }
- public byte PumpId { get; set; }
- /// <summary>
- /// 0x21 - 0x24
- /// </summary>
- public byte PhysicalId { get; set; }
- public List<NozzleConfiguration> NozzleConfigurations { get; set; }
- }
- public class NozzleConfiguration
- {
- public byte LogicalId { get; set; }
- /// <summary>
- /// 0x11 - 0x18
- /// </summary>
- public byte PhysicalId { get; set; }
- }
- #endregion
- private object syncObject = new object();
- private Guid uniqueId = Guid.NewGuid();
- private IEnumerable<NozzleExtraInfo> nozzleExtraInfos;
- /// <summary>
- /// Each ifsf node device need a standalone initializer.
- /// </summary>
- internal IEnumerable<TqcPumpGroupInitializerSimple> tqcPumpGroupInitializers;
- //protected static ILog logger = log4net.LogManager.GetLogger("PumpHandler");
- protected static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("PumpHandler");
- protected IContext<byte[], IfsfMessageBase> context;
- protected List<DitPumpHandler> pumpHandlers = new List<DitPumpHandler>();
- /// <summary>
- /// the pump side ifsf Subnet value.
- /// </summary>
- protected byte recipientSubnet = 1;
- /// <summary>
- /// the pump side ifsf Node values under this PumpGroup.
- /// </summary>
- protected List<byte> recipientNodes = new List<byte>();
- /// <summary>
- /// ifsf subnet value for FCC.
- /// </summary>
- public static byte originatorSubnet = 2;
- /// <summary>
- /// Ifsf node value for FCC.
- /// </summary>
- public static byte originatorNode = 1;
- [ParamsJsonSchemas("DitPumpGroupHandlerCtorParamsJsonSchemas")]
- public DitPumpGroupHandler(PumpGroupConfiguration pumpGroupConfiguration, IServiceProvider services)
- {
- originatorSubnet = pumpGroupConfiguration.FccIfsfSubnetValue;
- originatorNode = pumpGroupConfiguration.FccIfsfNodeValue;
- this.recipientSubnet = pumpGroupConfiguration.PumpGroupIfsfSubnetValue;
- this.recipientNodes.AddRange(pumpGroupConfiguration.PumpConfigurations.Select(pc => pc.PumpIfsfNodeValue));
- logger.Info("node " + this.recipientNodes.Select(n => n.ToString()).Aggregate((acc, n) => acc + ", " + n) + ", Will create " + pumpGroupConfiguration.PumpConfigurations.Count
- + " pump handlers for this TQC connection according from pumpGroupConfiguration");
- this.CreatePumpHandlers(pumpGroupConfiguration);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="pumpsXmlConfiguration"></param>
- public DitPumpGroupHandler(int fccIfsfSubnetValue, int fccIfsfNodeValue, string pumpsXmlConfiguration)
- {
- originatorSubnet = (byte)fccIfsfSubnetValue;
- originatorNode = (byte)fccIfsfNodeValue;
- // sample, a PumpGroup has a shared(for all pumps) ifsfSubNet value, each pump has an ifsfNode value
- //<PumpGroup ifsfSubNet='1'>
- // <Pump id='1' physicalId='0x21' ifsfNode='6'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x11' />
- // <Nozzle logicalId='2' physicalId='0x12' />
- // </Nozzles>
- // </Pump>
- // <Pump id='2' physicalId='0x22' ifsfNode='5'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x11' />
- // <Nozzle logicalId='2' physicalId='0x12' "/>
- // </Nozzles>
- // </Pump>
- // <Pump id='3' physicalId='0x23' ifsfNode='3'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x13' />
- // <Nozzle logicalId='2' physicalId='0x14' />
- // </Nozzles>
- // </Pump>
- // <Pump id='4' physicalId='0x24' ifsfNode='2'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x15' />
- // <Nozzle logicalId='2' physicalId='0x16' />
- // </Nozzles>
- // </Pump>
- //</PumpGroup>
- XmlDocument xmlDocument = new XmlDocument();
- xmlDocument.LoadXml(pumpsXmlConfiguration);
- var pumpGroupElement = xmlDocument.GetElementsByTagName("PumpGroup").Cast<XmlElement>().First();
- this.recipientSubnet = byte.Parse(pumpGroupElement.Attributes["ifsfSubNet"].Value);
- var pumpElements = xmlDocument.GetElementsByTagName("Pump");
- foreach (var pumpXmlNode in pumpElements.Cast<XmlNode>())
- if (pumpXmlNode.Attributes["ifsfNode"] != null)
- {
- this.recipientNodes.Add(byte.Parse(pumpXmlNode.Attributes["ifsfNode"].Value));
- }
- else
- throw new ArgumentNullException("Must specify attribute: 'ifsfNode' for each pump XmlNode");
- logger.Info("node " + this.recipientNodes.Select(n => n.ToString()).Aggregate((acc, n) => acc + ", " + n) + ", Will create " + pumpElements.Count
- + " pump handlers for this TQC connection according from local config");
- this.CreatePumpHandlers(pumpElements);
- }
- protected virtual void CreatePumpHandlers(XmlNodeList pumpElements)
- {
- foreach (XmlNode pumpElement in pumpElements)
- {
- byte pumpPhysicalIdValue;
- var rawPumpPhysicalId = pumpElement.Attributes["physicalId"].Value;//.Substring(2);
- if (rawPumpPhysicalId.StartsWith("0x") || rawPumpPhysicalId.StartsWith("0X"))
- pumpPhysicalIdValue = byte.Parse(pumpElement.Attributes["physicalId"].Value.Substring(2), NumberStyles.HexNumber);
- else
- pumpPhysicalIdValue = byte.Parse(pumpElement.Attributes["physicalId"].Value);
- if (pumpPhysicalIdValue < 0x21 || pumpPhysicalIdValue > 0x24)
- throw new ArgumentException("ifsf fuel point id must be range from 0x21 to 0x24, while the configuration passed in " + rawPumpPhysicalId);
- DitPumpHandler pumpHandler = new DitPumpHandler(this,
- int.Parse(pumpElement.Attributes["pumpId"].Value),
- pumpPhysicalIdValue,
- this.recipientSubnet,
- byte.Parse(pumpElement.Attributes["ifsfNode"].Value),
- pumpElement.InnerXml, GetNewMessageToken);
- this.pumpHandlers.Add(pumpHandler);
- }
- }
- protected virtual void CreatePumpHandlers(PumpGroupConfiguration pumpGroupConfiguration)
- {
- foreach (var pumpConfig in pumpGroupConfiguration.PumpConfigurations)
- {
- DitPumpHandler pumpHandler = new DitPumpHandler(this,
- pumpConfig.PumpId,
- pumpConfig.PhysicalId,
- this.recipientSubnet,
- pumpConfig.PumpIfsfNodeValue,
- pumpConfig.NozzleConfigurations,
- GetNewMessageToken);
- this.pumpHandlers.Add(pumpHandler);
- }
- }
- /// <summary>
- /// will be called at the Init stage of FdcServerApp, that means before the calling the Start() for all the Processors.
- /// </summary>
- /// <param name="parameters"></param>
- public void OnFdcServerInit(Dictionary<string, object> parameters)
- {
- if (parameters != null && parameters.TryGetValue("NozzleProductMapping", out object param))
- {
- this.nozzleExtraInfos = param as IEnumerable<NozzleExtraInfo>;
- }
- this.tqcPumpGroupInitializers = this.recipientNodes.Select(rcpNodeValue =>
- {
- var phs = this.pumpHandlers.Where(ph => ph.recipientNode == rcpNodeValue);
- logger.Info("Creating a TqcPumpGroupInitializer for node: " + rcpNodeValue
- + ", managed pump Id(s): " + phs.Select(ph => ph.PumpId.ToString()).Aggregate((acc, n) => acc + ", " + n));
- var initor = new TqcPumpGroupInitializerSimple(this.nozzleExtraInfos, originatorSubnet, originatorNode,
- this.recipientSubnet, rcpNodeValue, phs, this.GetNewMessageToken);
- initor.OnInitTimeout += (cc, dd) =>
- {
- };
- initor.OnInitDone += (ee, ff) =>
- {
- };
- //logger.Info(" created a TqcPumpGroupInitializer for node: " + rcpNodeValue);
- return initor;
- }).ToList();
- this.pumpHandlers.ForEach(ph => ph.OnFdcServerInit(parameters));
- }
- public virtual void Init(IContext<byte[], IfsfMessageBase> context)
- {
- this.context = context;
- bool isCommConnected = false;
- this.context.Communicator.OnConnected += async (e, f) =>
- {
- var comm = context.Communicator as HengShan_TQC_IFsfMessageTcpIpCommunicator<IfsfMessageBase>;
- logger.Info("TqcPumpGroupInitializer, Communicator Connected(to pump server: " + (comm?.pumpServerTcpListeningIpAddress ?? "") + "), will start init each Initializer...");
- isCommConnected = true;
- foreach (var initor in this.tqcPumpGroupInitializers)
- {
- while (isCommConnected)
- {
- initor.Reset();
- if (initor.CurrentStatus == TqcPumpGroupInitializerSimple.Status.UnInit)
- initor.FeedIn(this.context);
- else
- logger.Info("TqcPumpGroupInitializer, node " + initor.ifsfRecipientNode + " is already in a initing process, just wait for finish...");
- // may refine in future for wait the init Done event.
- var initResult = await initor.InitDoneTaskCompletionSource.Task;
- if (initResult)
- {
- logger.Info("TqcPumpGroupInitializer, node " + initor.ifsfRecipientNode + ", init done, will query all FP status and routed following msg to PumpHandlers");
- // query all FP status, answer will be routed to each PumpHandler to handle.
- this.context.Outgoing.Write(
- new FuellingPointDbRequest_Read_FuelPointState(
- this.recipientSubnet,
- initor.ifsfRecipientNode,
- originatorSubnet,
- originatorNode,
- this.GetNewMessageToken(),
- 0x20));
- //var nozzleProductConfig
- // = Configurator.Default.NozzleExtraInfoConfiguration.Mapping;
- initor.pumpHandlers.SelectMany(p => p.Nozzles).ToList().ForEach(n =>
- {
- var boundProductNo = this.nozzleExtraInfos.First(c => c.PumpId == n.PumpId && c.NozzleLogicalId == n.LogicalId).ProductBarcode;
- logger.Info("TqcPumpGroupInitializer, node " + initor.ifsfRecipientNode
- + ", will write back price to nozzle on pump " + n.PumpId + ", logicalNozzleId: " + n.LogicalId + ", boundProductNo: " + boundProductNo
- + " to new Init Price(without decimal points): " + initor.PriceBook[boundProductNo]);
- n.RealPriceOnPhysicalPump = initor.PriceBook[boundProductNo];
- });
- break;
- }
- else
- {
- logger.Info("TqcPumpGroupInitializer, node " + initor.ifsfRecipientNode + ", init timed out, will start it over...");
- //initor.Reset();
- //initor.FeedIn(this.context);
- }
- }
- }
- };
- this.context.Communicator.OnDisconnected += (e, f) =>
- {
- var comm = context.Communicator as HengShan_TQC_IFsfMessageTcpIpCommunicator<IfsfMessageBase>;
- logger.Info("TqcPumpGroupInitializer, Communicator Disconnected(to pump server: " + (comm?.pumpServerTcpListeningIpAddress ?? "") + ")...");
- foreach (var initor in this.tqcPumpGroupInitializers)
- {
- initor.Reset();
- isCommConnected = false;
- initor.pumpHandlers.ToList().ForEach(p => p.HandleFpStatusChange(FuellingPointStatus.Inoperative, null));
- }
- };
- this.pumpHandlers.ForEach(p => p.Init(this.context));
- }
- private byte rotateMsgToken = 0;
- public byte GetNewMessageToken()
- {
- if (rotateMsgToken == (0xFF & 0x01F))
- rotateMsgToken = 0;
- else
- rotateMsgToken++;
- return rotateMsgToken;
- }
- public virtual Task Process(IContext<byte[], IfsfMessageBase> context)
- {
- this.context = context;
- var initor = this.tqcPumpGroupInitializers?.FirstOrDefault(i => i.ifsfRecipientNode == context.Incoming.Message.OriginatorNode);
- if (initor == null)
- {
- // must has initor created first
- return Task.CompletedTask;
- }
- if (!initor.IsInitDone)
- {
- initor.FeedIn(context);
- return Task.CompletedTask;
- }
- this.RouteMessageToHandlers(context);
- return Task.CompletedTask;
- }
- protected virtual void RouteMessageToHandlers(IContext<byte[], IfsfMessageBase> context)
- {
- switch (context.Incoming.Message)
- {
- case FuellingPointDb_FpStatus_Event fpStatusEvent:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == fpStatusEvent.TargetFuelPointId
- && h.recipientNode == fpStatusEvent.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingPointDb_FpStatus_Answer fpStatusAnswer:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == fpStatusAnswer.TargetFuelPointId
- && h.recipientNode == fpStatusAnswer.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingPointDb_FpRunningTransaction_Event fpRunningTrxEvent:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == fpRunningTrxEvent.TargetFuelPointId
- && h.recipientNode == fpRunningTrxEvent.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingPointDb_FpRunningTransaction_Event_ACK fpRunningTrxEvent:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == fpRunningTrxEvent.TargetFuelPointId
- && h.recipientNode == fpRunningTrxEvent.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingTrxDb_TransactionBufferStatus_Event trxBufferStatusEvent:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == trxBufferStatusEvent.TargetFuelPointId
- && h.recipientNode == trxBufferStatusEvent.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingTrxDb_TransactionBufferStatus_Event_ACK trxBufferStatusEvent:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == trxBufferStatusEvent.TargetFuelPointId
- && h.recipientNode == trxBufferStatusEvent.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- case FuellingTrxDb_TransactionBufferStatus_Answer trxBufferStatusAnswer:
- this.pumpHandlers.Where(h => h.PumpPhysicalId == trxBufferStatusAnswer.TargetFuelPointId
- && h.recipientNode == trxBufferStatusAnswer.OriginatorNode).ToList().ForEach(p => p.Process(context));
- break;
- //default: this.pumpHandlers.ForEach(p => p.Process(context)); break;
- }
- }
- public IEnumerator<IFdcPumpController> GetEnumerator()
- {
- return this.pumpHandlers.GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.pumpHandlers.GetEnumerator();
- }
- public Guid Id => this.uniqueId;
- internal class TqcPumpGroupInitializerSimple
- {
- System.Timers.Timer initTimeoutTimer = new Timer(initTimeout);
- const int initTimeout = 10000;
- /// <summary>
- /// will fire when reached timed out time, and state is still not Done.
- /// </summary>
- public event EventHandler OnInitTimeout;
- /// <summary>
- /// false indicates init timed out, true indicates init done successfully.
- /// </summary>
- public TaskCompletionSource<bool> InitDoneTaskCompletionSource = new TaskCompletionSource<bool>();
- public event EventHandler OnInitDone;
- /// <summary>
- /// init process will firstly read all necessary config values in TQC, and then execute the write operations.
- /// this event will be fired once those config values were read, and write operation is still not perform.
- /// </summary>
- public event EventHandler OnTqcExistedConfigRead;
- private List<FuellingPointDb_FpStatus_Answer> fpStatus_Answers
- = new List<FuellingPointDb_FpStatus_Answer>();
- private List<LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answer> logicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers
- = new List<LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answer>();
- /// <summary>
- /// Gets pre-config value in TQC pump.
- /// </summary>
- public IEnumerable<LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answer> LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers => this.logicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers;
- private List<ProductDb_ProductNo_Answer> productDb_ProductNo_Answers
- = new List<ProductDb_ProductNo_Answer>();
- /// <summary>
- /// Gets pre-config value in TQC pump.
- /// </summary>
- public IEnumerable<ProductDb_ProductNo_Answer> ProductDb_ProductNo_Answers => this.productDb_ProductNo_Answers;
- private List<ProductPerFuellingModeDb_ProductPrice_Answer> productPerFuellingModeDb_ProductPrice_Answers
- = new List<ProductPerFuellingModeDb_ProductPrice_Answer>();
- /// <summary>
- /// Gets pre-config value in TQC pump.
- /// </summary>
- public IEnumerable<ProductPerFuellingModeDb_ProductPrice_Answer> ProductPerFuellingModeDb_ProductPrice_Answers => this.productPerFuellingModeDb_ProductPrice_Answers;
- private Dictionary<int, int> priceBook = new Dictionary<int, int>();
- /// <summary>
- /// Gets or set the init price for each product.
- /// default price init policy is read from pricebook, if found then apply, otherwise use pre-config value read from pump.
- /// should follow-> barcode:rawFormatPriceWithoutDecimalPoints
- /// </summary>
- public Dictionary<int, int> PriceBook => this.priceBook;
- private byte ifsfSelfSubnet;
- private byte ifsfSelfNode;
- private byte ifsfRecipientSubnet;
- public byte ifsfRecipientNode;
- public IEnumerable<DitPumpHandler> pumpHandlers;
- Func<byte> msgTokenGenerator;
- private List<int> thisTqcProductBarcodes;
- private Status currentStatus;
- public Status CurrentStatus
- {
- get { return this.currentStatus; }
- private set
- {
- //logger.Debug("PumpInitializer, node " + ifsfRecipientNode + ", Status switched from " + this.currentStatus + " to " + value);
- this.currentStatus = value;
- }
- }
- //private DateTime previousRequestingTime;
- private byte? pendingForAckMsgToken;
- public enum Status
- {
- UnInit = 0,
- Wait_Answer_Query_All_FuelPointState,
- Wait_Answer_Close_All_FuelPoint,
- Wait_Answer_Query_Caculator_Overall_Info,
- Wait_Answer_Read_All_Nozzle_ProductInfo_PhyId,
- Wait_Answer_Read_All_ProductNumber,
- Wait_Answer_Read_All_ProductPrice,
- //Sending_Add_Recipient_Addr,
- Wait_ACK_Add_Recipient_Addr,
- //Sending_Clear_ProductNumber_In_Caculator,
- Wait_ACK_Clear_ProductNumber_In_ProductDb,
- //Sending_Set_ProductNumber_In_Caculator,
- Wait_ACK_Set_ProductNumber_In_ProductDb,
- //Sending_Link_Meter_To_CaculatorSlot,
- Wait_ACK_Link_Meter_To_ProductDb_ProductNoSlot,
- //Sending_Set_AUTH_MODE,
- Wait_ACK_Set_AUTH_MODE,
- //Sending_Set_Price,
- Wait_ACK_Set_Price,
- //Sending_Set_Nozzle_To_CacalatorSlot,
- Wait_ACK_Set_Nozzle_To_ProductDb_ProductNoSlot,
- //Sending_Set_FP_Default_FuellingMode,
- Wait_ACK_Set_FP_Default_FuellingMode,
- //Send_Open_FP,
- //Wait_ACK_Open_FP,
- Done
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="selfSubnet">fc ifsf subnet value</param>
- /// <param name="selfNode">fc ifsf node value</param>
- /// <param name="ifsfRecipientSubnet">remote ifsf recipient subnet value</param>
- /// <param name="ifsfRecipientNode">remote ifsf recipient node value</param>
- /// <param name="pumpHandlers">pump handlers created from the pump Group handler</param>
- /// <param name="msgTokenGenerator"></param>
- public TqcPumpGroupInitializerSimple(IEnumerable<NozzleExtraInfo> nozzleExtraInfos, byte selfSubnet, byte selfNode, byte ifsfRecipientSubnet, byte ifsfRecipientNode,
- IEnumerable<DitPumpHandler> pumpHandlers, Func<byte> msgTokenGenerator)
- {
- this.ifsfSelfSubnet = selfSubnet;
- this.ifsfSelfNode = selfNode;
- this.ifsfRecipientSubnet = ifsfRecipientSubnet;
- this.ifsfRecipientNode = ifsfRecipientNode;
- this.pumpHandlers = pumpHandlers;
- this.msgTokenGenerator = msgTokenGenerator;
- this.thisTqcProductBarcodes =
- pumpHandlers.SelectMany(ph => ph.Nozzles)
- .Select(n => nozzleExtraInfos.FirstOrDefault(npc => npc.PumpId == n.PumpId && npc.NozzleLogicalId == n.LogicalId)?.ProductBarcode)
- .Where(n => n != null).Select(n => n.Value).Distinct().OrderBy(o => o).ToList();
- //this.thisTqcProductBarcodes = nozzleProductConfig.Select(s => s.ProductBarcode).Distinct().OrderBy(o => o).ToList();
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " current TQC local configuration indicates total have "
- + this.thisTqcProductBarcodes.Count + " product barcodes: " + this.thisTqcProductBarcodes.Select(s => s.ToString()).Aggregate((acc, n) => acc + ", " + n));
- this.initTimeoutTimer.Elapsed += (a, b) =>
- {
- this.initTimeoutTimer.Stop();
- if (!this.IsInitDone)
- {
- this.InitDoneTaskCompletionSource.SetResult(false);
- var safe = this.OnInitTimeout;
- safe(this, null);
- }
- };
- }
- private byte next_ActualInPump_ProductNumber_In_ProductDb_ProductNoSlot_Index = 1;
- private byte next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index = 1;
- //private byte next_Link_Meter_to_ProductNumber_Index = 1;
- private byte next_site_nozzle_Index = 1;
- private byte next_Fp_Index = 1;
- /// <summary>
- /// if it was Done, return false. otherwise, the init is kicking off, return true.
- /// </summary>
- /// <param name="context"></param>
- /// <returns></returns>
- public bool FeedIn(IContext<byte[], IfsfMessageBase> context)
- {
- var comm = context.Communicator as HengShan_TQC_IFsfMessageTcpIpCommunicator<IfsfMessageBase>;
- if (!this.initTimeoutTimer.Enabled) this.initTimeoutTimer.Start();
- if (IsInitDone) return false;
- switch (this.CurrentStatus)
- {
- case Status.UnInit:
- {
- logger.Info("PumpInitializerSimple, node " + ifsfRecipientNode + " start Init(to pump server: " + (comm?.pumpServerTcpListeningIpAddress ?? "") + "), firstly Query_Caculator_Overall_Info...");
- this.next_Fp_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending CaculatorDbRequest_Read_FuelPoint_Product_FuelMode_Meter_Info...");
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new CaculatorDbRequest_Read_FuelPoint_Product_FuelMode_Meter_Info(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value
- ));
- this.CurrentStatus = Status.Wait_Answer_Query_Caculator_Overall_Info;
- break;
- }
- case Status.Wait_Answer_Query_Caculator_Overall_Info:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken)
- {
- var dataParser = DatabaseDataParser.New().Convert(ifsfMsg.RawDatabaseData.ToArray());
- var numberOfProducts = dataParser.DataIds.First(i => i.Item1 == 0x02).Item2.ToInt32();
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " CaculatorDbRequest_Read_FuelPoint_Product_FuelMode_Meter_Info Acked,\r\n" +
- "Read caculatorDbOverallInfo, No_Products: " + numberOfProducts
- + ", No_Fuelling_Modes: " + dataParser.DataIds.First(i => i.Item1 == 0x03).Item2.ToInt32()
- + ", No_Meters: " + (dataParser.DataIds.FirstOrDefault(i => i.Item1 == 0x04)?.Item2?.ToInt32() ?? -1)
- + ", No_FP: " + dataParser.DataIds.First(i => i.Item1 == 0x05).Item2.ToInt32()
- + ", Auth_State_Mode: " + dataParser.DataIds.First(i => i.Item1 == 0x0B).Item2.ToInt32());
- if (numberOfProducts != this.thisTqcProductBarcodes.Count)
- {
- logger.Info("!!!!!!PumpInitializer, node " + ifsfRecipientNode + " This TQC MUST config " + numberOfProducts + " products, but now trying to load local config with " + this.thisTqcProductBarcodes.Count + " products");
- }
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " Send LogicalNozzleDb_Read_Nozzle_ProductInfo_PhyId for FP: 0x"
- + pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId.ToHexLogString());
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new LogicalNozzleDb_Read_Nozzle_ProductInfo_PhyId(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, (byte)(pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId), 0x10));
- this.CurrentStatus = Status.Wait_Answer_Read_All_Nozzle_ProductInfo_PhyId;
- }
- break;
- }
- case Status.Wait_Answer_Read_All_Nozzle_ProductInfo_PhyId:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken.Value)
- {
- var historyIncoming = context.Incoming as HistoryKeepIncoming<IfsfMessageBase>;
- this.logicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers.AddRange(
- historyIncoming.History.Where(h => (h.Item1 is LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answer im)
- && im.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && im.MessageToken == this.pendingForAckMsgToken)
- .Select(s => s.Item1 as LogicalNozzleDb_Nozzle_ProductInfo_PhyId_Answer).OrderBy(a => a.LogicalNozzleId));
- if (++next_Fp_Index <= pumpHandlers.Count())
- {
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " LogicalNozzleDb_Read_Nozzle_ProductInfo_PhyId Acked");
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " Send LogicalNozzleDb_Read_Nozzle_ProductInfo_PhyId for FP: 0x"
- + pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId.ToHexLogString());
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new LogicalNozzleDb_Read_Nozzle_ProductInfo_PhyId(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, (byte)(pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId), 0x10));
- this.CurrentStatus = Status.Wait_Answer_Read_All_Nozzle_ProductInfo_PhyId;
- }
- else
- {
- foreach (var answer in this.logicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers)
- logger.Info(" node " + ifsfRecipientNode + " Read nozzles info for FP: 0x" + answer.TargetFuelPointId.ToHexLogString()
- + ", with logicalId: 0x" + answer.LogicalNozzleId.ToHexLogString()
- + ", with physicalId: 0x" + answer.PhyscialNozzleId.ToHexLogString()
- + ", with product slotId: 0x" + answer.LinkedProductSlotId_InProductDbProdcutNoSlot.ToHexLogString());
- next_Fp_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending ProductDbRequest_Read_ProductNo");
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- // will receive several answers and an ACK messages since this is a query all request.
- context.Outgoing.Write(new ProductDbRequest_Read_ProductNo(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, 0));
- this.CurrentStatus = Status.Wait_Answer_Read_All_ProductNumber;
- }
- }
- break;
- }
- case Status.Wait_Answer_Read_All_ProductNumber:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken)
- {
- var historyIncoming = context.Incoming as HistoryKeepIncoming<IfsfMessageBase>;
- //logger.Debug("************" + historyIncoming.History.Select(a => a.Item1.GetType().Name).Aggregate((acc, n) => acc + ", " + n));
- //logger.Debug("************historyIncoming.History.Count: " + historyIncoming.History.Count);
- this.productDb_ProductNo_Answers.AddRange(
- historyIncoming.History.Where(h => (h.Item1 is ProductDb_ProductNo_Answer im)
- && im.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && im.MessageToken == this.pendingForAckMsgToken).Select(s => s.Item1 as ProductDb_ProductNo_Answer).OrderBy(a => a.ProductSlotId));
- if (this.productDb_ProductNo_Answers.Any())
- {
- logger.Info(" node " + ifsfRecipientNode + " Read all existed product number in a TQC which are: " + this.productDb_ProductNo_Answers.Select(s => s.ProductNumber + "(in 0x" + s.ProductSlotId.ToHexLogString() + ")").Aggregate((acc, n) => acc + ", " + n));
- string actualProductNumber = this.productDb_ProductNo_Answers.ElementAt(this.next_ActualInPump_ProductNumber_In_ProductDb_ProductNoSlot_Index - 1).ProductNumber;//this.siteProductBarcodes[next_Clear_ProductNumber_In_Caculator_SlotIndex - 1].ToString();
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- // each Product will receive a serial of answers for its differnt FuelMode since we input 0x10 as query all FM.
- context.Outgoing.Write(new ProductPerFuellingModeDbRequest_Read_ProductPrice(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, actualProductNumber, 0x11));
- this.CurrentStatus = Status.Wait_Answer_Read_All_ProductPrice;
- }
- else
- {
- /* TQC without any product configed, happened for fresh new TQC pump (get hardware reset or just shipped from factory??), handle here */
- logger.Info(" node " + ifsfRecipientNode + " has no ProductDb_ProductNo_Answer received, seems there're no product configurated in this TQC yet, will directly Clear Set_ProductNumber_In_ProductDb");
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending Clear ProductNumber in ProductDb slot index: " + next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index);
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new ProductDbRequest_Write_SetProductNumber(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value,
- next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index, null));
- this.CurrentStatus = Status.Wait_ACK_Set_ProductNumber_In_ProductDb;
- }
- }
- break;
- }
- case Status.Wait_Answer_Read_All_ProductPrice:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken.Value)
- {
- var historyIncoming = context.Incoming as HistoryKeepIncoming<IfsfMessageBase>;
- var resultSetsForOneProduct = historyIncoming.History.Where(h => (h.Item1 is ProductPerFuellingModeDb_ProductPrice_Answer im)
- && im.MessageType == MessageType.IFSF_MESSAGE_TYPE_ANSWER
- && im.MessageToken == this.pendingForAckMsgToken).Select(s => s.Item1 as ProductPerFuellingModeDb_ProductPrice_Answer);
- logger.Info(" node " + ifsfRecipientNode + ", Read one existed product price with product number: "
- + resultSetsForOneProduct.Last().ProductNumber
- + ", price are: " + resultSetsForOneProduct.OrderBy(a => a.FuelModeId).Select(s => s.Price + " in FM:0x" + s.FuelModeId.ToString("X")).Aggregate((acc, n) => acc + ", " + n));
- this.productPerFuellingModeDb_ProductPrice_Answers.AddRange(resultSetsForOneProduct);
- if (this.productDb_ProductNo_Answers.Count() >= ++next_ActualInPump_ProductNumber_In_ProductDb_ProductNoSlot_Index)
- {
- string actualProductNumber = this.productDb_ProductNo_Answers.ElementAt(this.next_ActualInPump_ProductNumber_In_ProductDb_ProductNoSlot_Index - 1).ProductNumber;//this.siteProductBarcodes[next_Clear_ProductNumber_In_Caculator_SlotIndex - 1].ToString();
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(new ProductPerFuellingModeDbRequest_Read_ProductPrice(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, actualProductNumber, 0x10));
- this.CurrentStatus = Status.Wait_Answer_Read_All_ProductPrice;
- }
- else
- {
- next_ActualInPump_ProductNumber_In_ProductDb_ProductNoSlot_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " Read_All_ProductPrice done!");
- var safe = this.OnTqcExistedConfigRead;
- safe?.Invoke(this, null);
- next_site_nozzle_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending CaculatorDbRequest_Write_Set_AuthStateMode_MinFuelingVol_MinDisplayVol");
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new CaculatorDbRequest_Write_Set_AuthStateMode_MinFuelingVol_MinDisplayVol(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value,
- CaculatorDbRequest_Write_Set_AuthStateMode_MinFuelingVol_MinDisplayVol.Caculator_Auth_State_Mode.AUTH_State_Allowed));
- this.CurrentStatus = Status.Wait_ACK_Set_AUTH_MODE;
- }
- }
- break;
- }
- case Status.Wait_ACK_Set_AUTH_MODE:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ACK
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken.Value)
- {
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " CaculatorDbRequest_Write_Set_AuthStateMode_MinFuelingVol_MinDisplayVol Acked.");
- var targetBarcode = this.thisTqcProductBarcodes[next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index - 1];
- int newInitPriceWithoutDecimalPoints;
- if (this.PriceBook.ContainsKey(targetBarcode))
- newInitPriceWithoutDecimalPoints = this.PriceBook[targetBarcode];
- else
- {
- // try load the existed pre-configed price value which just read from TQC pump.
- var preConfigedPriceOnPump = this.productPerFuellingModeDb_ProductPrice_Answers.FirstOrDefault(p => p.FuelModeId == 0x11 && p.ProductNumber == targetBarcode.ToString().PadLeft(8, '0'))?.Price;
- if (string.IsNullOrEmpty(preConfigedPriceOnPump))
- newInitPriceWithoutDecimalPoints = 1883 + next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index;
- else
- newInitPriceWithoutDecimalPoints = int.Parse(preConfigedPriceOnPump);
- this.PriceBook.Add(targetBarcode, newInitPriceWithoutDecimalPoints);
- }
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending ProductPerFuellingModeDbRequest_Write_SetPrice, productNo: "
- + targetBarcode.ToString()
- + ", new price(without decimalPoints): " + newInitPriceWithoutDecimalPoints.ToString());
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new ProductPerFuellingModeDbRequest_Write_SetPrice(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value,
- targetBarcode.ToString(), newInitPriceWithoutDecimalPoints.ToString()
- , 0x11)
- );
- this.CurrentStatus = Status.Wait_ACK_Set_Price;
- }
- break;
- }
- case Status.Wait_ACK_Set_Price:
- {
- if (context.Incoming.Message is AcknowledgeMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ACK
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken.Value)
- {
- if (ifsfMsg.OverallStatus != MessageAcknowledgeStatus.ACK_PositiveAcknowledgeDataReceived)
- logger.Error(" node " + ifsfRecipientNode + ", set price for product failed!");
- if (this.thisTqcProductBarcodes.Count >= ++next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index)
- {
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " ProductPerFuellingModeDbRequest_Write_SetPrice Acked.");
- var targetBarcode = this.thisTqcProductBarcodes[next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index - 1];
- int newInitPriceWithoutDecimalPoints;
- if (this.PriceBook != null && this.PriceBook.ContainsKey(targetBarcode))
- newInitPriceWithoutDecimalPoints = this.PriceBook[targetBarcode];
- else
- {
- // try load the existed pre-configed price value which just read from TQC pump.
- var preConfigedPriceOnPump = this.productPerFuellingModeDb_ProductPrice_Answers.FirstOrDefault(p => p.FuelModeId == 0x11 && p.ProductNumber == targetBarcode.ToString().PadLeft(8, '0'))?.Price;
- if (string.IsNullOrEmpty(preConfigedPriceOnPump))
- newInitPriceWithoutDecimalPoints = 1883 + next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index;
- else
- newInitPriceWithoutDecimalPoints = int.Parse(preConfigedPriceOnPump);
- this.PriceBook.Add(targetBarcode, newInitPriceWithoutDecimalPoints);
- }
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " sending ProductPerFuellingModeDbRequest_Write_SetPrice, productNo: "
- + targetBarcode.ToString()
- + ", new price(without decimalPoints): " + newInitPriceWithoutDecimalPoints.ToString());
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- //logger.Info("PumpInitializer, node "+ifsfRecipientNode+" will set product: " + this.siteProductBarcodes[next_Clear_ProductNumber_In_Caculator_SlotIndex - 1].ToString() + " with price " + (1883 + next_Clear_ProductNumber_In_Caculator_SlotIndex).ToString());
- context.Outgoing.Write(
- new ProductPerFuellingModeDbRequest_Write_SetPrice(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, targetBarcode.ToString(), newInitPriceWithoutDecimalPoints.ToString(), 0x11)
- );
- this.CurrentStatus = Status.Wait_ACK_Set_Price;
- }
- else
- {
- next_Clear_ProductNumber_In_ProductDb_ProductNoSlot_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " set product Price(8 products) in fuel mode 0x11 done!");
- //this.CurrentStatus = Status.Sending_Set_Nozzle_To_CacalatorSlot;
- // now we only have fuelling mode 0x11.
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " Send FuellingPointDbRequest_Write_SetDefaultFuellingMode,\r\n" +
- "FP: 0x" + pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId.ToHexLogString() + " set to fuelling mode 0x11");
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new FuellingPointDbRequest_Write_SetDefaultFuellingMode(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, (byte)(pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId), 1));
- this.CurrentStatus = Status.Wait_ACK_Set_FP_Default_FuellingMode;
- }
- }
- break;
- }
- case Status.Wait_ACK_Set_FP_Default_FuellingMode:
- {
- if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_ACK
- && ifsfMsg.MessageToken == this.pendingForAckMsgToken.Value)
- {
- if (++next_Fp_Index <= pumpHandlers.Count())
- {
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " FuellingPointDbRequest_Write_SetDefaultFuellingMode Acked");
- // now we only have fuelling mode 0x11.
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " Send FuellingPointDbRequest_Write_SetDefaultFuellingMode,\r\n" +
- "FP Default fuelling mode, FP: 0x" + pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId.ToHexLogString());
- this.pendingForAckMsgToken = this.msgTokenGenerator();
- context.Outgoing.Write(
- new FuellingPointDbRequest_Write_SetDefaultFuellingMode(this.ifsfRecipientSubnet,
- this.ifsfRecipientNode,
- this.ifsfSelfSubnet,
- this.ifsfSelfNode,
- this.pendingForAckMsgToken.Value, (byte)(pumpHandlers.ElementAt(next_Fp_Index - 1).PumpPhysicalId), 1));
- this.CurrentStatus = Status.Wait_ACK_Set_FP_Default_FuellingMode;
- }
- else
- {
- next_Fp_Index = 1;
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + " set fp default fuelling mode all done!");
- logger.Info("PumpInitializer, node " + ifsfRecipientNode + "(pump server ip: " + (comm?.pumpServerTcpListeningIpAddress ?? "") + ") DONE!!!");
- this.CurrentStatus = Status.Done;
- this.InitDoneTaskCompletionSource.SetResult(true);
- var safe = this.OnInitDone;
- safe?.Invoke(this, null);
- }
- }
- break;
- }
- }
- return true;
- }
- public bool IsInitDone => this.CurrentStatus == Status.Done;
- public void Reset()
- {
- this.CurrentStatus = Status.UnInit;
- this.initTimeoutTimer.Stop();
- this.InitDoneTaskCompletionSource = new TaskCompletionSource<bool>();
- this.logicalNozzleDb_Nozzle_ProductInfo_PhyId_Answers.Clear();
- this.productDb_ProductNo_Answers.Clear();
- this.productPerFuellingModeDb_ProductPrice_Answers.Clear();
- }
- }
- #region IDisposable Support
- private bool disposedValue = false; // To detect redundant calls
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: dispose managed state (managed objects).
- }
- // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
- // TODO: set large fields to null.
- disposedValue = true;
- }
- }
- // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
- // ~PumpHandler() {
- // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- // Dispose(false);
- // }
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- // TODO: uncomment the following line if the finalizer is overridden above.
- // GC.SuppressFinalize(this);
- }
- IEnumerator<IFdcPumpController> IEnumerable<IFdcPumpController>.GetEnumerator()
- {
- return this.pumpHandlers.GetEnumerator();
- }
- #endregion
- }
- }
|