123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- using Edge.Core.Processor;
- using Edge.Core.IndustryStandardInterface.Pump;
- using HengShan_Pump_TQC_IFSF.MessageEntity;
- using HengShan_Pump_TQC_IFSF.MessageEntity.Incoming;
- using HengShan_Pump_TQC_IFSF.MessageEntity.Outgoing;
- using Edge.Core.Parser.BinaryParser.Util;
- 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;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Edge.Core.Processor.Communicator;
- namespace HengShan_Pump_TQC_IFSF
- {
- /// <summary>
- /// silent means this pump group handler never actively send data to TQC, this is a solution for
- /// a special TQC pump only passthrough sales data to FC, because it's controlled by other party FC.
- /// </summary>
- [MetaPartsRequired(typeof(GenericDeviceProcessor<,>))]
- [MetaPartsRequired(typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>))]
- [MetaPartsDescriptor(
- "lang-zh-cn:HS TQC只读模式加油机lang-en-us:HS TQC readonly mode pump",
- "lang-zh-cn:用于中石化站中驱动只读模式下的基于TCP连接的IFSF协议的 Wayne-WT30 或者 恒山-TH22 协议的加油机lang-en-us:Used for SinoPec site to driven pumps set in readonly mode, and the model are Wayne-WT30 or HengShan-TH22, which using IFSF protocol on TCP",
- new[] { "lang-zh-cn:加油机lang-en-us:Pump" })]
- public class SilentPumpGroupHandler : PumpGroupHandler
- {
- private System.Timers.Timer timelyCheckConnection;
- private DateTime lastTimeRecieveHearbeat;
- [ParamsJsonSchemas("PumpGroupHandlerCtorParamsJsonSchemas")]
- public SilentPumpGroupHandler(PumpGroupConfiguration pumpGroupConfiguration, IServiceProvider services)
- : base(pumpGroupConfiguration, services)
- {
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="pumpsXmlConfiguration"></param>
- public SilentPumpGroupHandler(int fccIfsfSubnetValue, int fccIfsfNodeValue, string pumpsXmlConfiguration)
- : base(fccIfsfSubnetValue, fccIfsfNodeValue, pumpsXmlConfiguration)
- {
- // sample
- //<PumpGroup ifsfSubNet='2' ifsfNode='1'>
- // <Pump pumpId='1' physicalId='0x21'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x11' />
- // <Nozzle logicalId='2' physicalId='0x12' />
- // </Nozzles>
- // </Pump>
- // <Pump pumpId='2' physicalId='0x22'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x11' />
- // <Nozzle logicalId='2' physicalId='0x12' "/>
- // </Nozzles>
- // </Pump>
- // <Pump pumpId='3' physicalId='0x23'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x13' />
- // <Nozzle logicalId='2' physicalId='0x14' />
- // </Nozzles>
- // </Pump>
- // <Pump pumpId='4' physicalId='0x24'>
- // <Nozzles>
- // <Nozzle logicalId='1' physicalId='0x15' />
- // <Nozzle logicalId='2' physicalId='0x16' />
- // </Nozzles>
- // </Pump>
- //</PumpGroup>
- }
- public override void Init(IContext<byte[], IfsfMessageBase> context)
- {
- base.context = context;
- this.context.Communicator.OnConnected += (e, f) =>
- {
- // each time communicator get disconnect, will trigger a re-init.
- logger.Info("node " + this.tqcPumpGroupInitializer.ifsfRecipientNode + ", OnCommunicator Connected, will hard set all pumps to Idle state anyway");
- this.pumpHandlers.ForEach(p => p.HandleFpStatusChange(FuellingPointStatus.Idle, null));
- };
- this.context.Communicator.OnDisconnected += (e, f) =>
- {
- logger.Info("node " + this.tqcPumpGroupInitializer.ifsfRecipientNode + ", OnCommunicator Disconnected, will hard set all pumps to Closed state anyway");
- this.pumpHandlers.ForEach(p => p.HandleFpStatusChange(FuellingPointStatus.Closed, null));
- };
- base.pumpHandlers.ForEach(p => p.Init(this.context));
- this.timelyCheckConnection = new Timer(6000);
- this.timelyCheckConnection.Elapsed += (_, __) =>
- {
- if (DateTime.Now.Subtract(this.lastTimeRecieveHearbeat).TotalSeconds >= 6)
- {
- //logger.Debug("Heartbeat timed out, will turn all pumps("
- // + this.pumpHandlers.Select(p => p.QueryStatus().ToString()).Aggregate((acc, n) => acc + "," + n)
- // + ") to Closed state");
- this.pumpHandlers.ForEach(p => p.HandleFpStatusChange(FuellingPointStatus.Closed, null));
- }
- };
- this.timelyCheckConnection.Start();
- }
- protected override void CreatePumpHandlers(IEnumerable<XmlNode> pumpElements)
- {
- foreach (XmlNode pumpElement in pumpElements)
- {
- byte pumpPhysicalIdValue;
- var rawPumpPhysicalId = pumpElement.Attributes["physicalId"].Value;
- 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);
- SilentPumpHandler pumpHandler = new SilentPumpHandler(this, int.Parse(pumpElement.Attributes["pumpId"].Value),
- pumpPhysicalIdValue,
- base.recipientSubnet, base.recipientNode,
- pumpElement.InnerXml, GetNewMessageToken);
- base.pumpHandlers.Add(pumpHandler);
- }
- }
- public override Task Process(IContext<byte[], IfsfMessageBase> context)
- {
- base.context = context;
- switch (context.Incoming.Message)
- {
- case CommunicationDb_Event_ACK usedAsHeartBeat:
- this.lastTimeRecieveHearbeat = DateTime.Now;
- context.Outgoing.Write(new AcknowledgeMessage(
- usedAsHeartBeat.OriginatorSubnet,
- usedAsHeartBeat.OriginatorNode,
- PumpGroupHandler.originatorSubnet, PumpGroupHandler.originatorNode,
- usedAsHeartBeat.MessageToken,
- usedAsHeartBeat.DatabaseId,
- MessageAcknowledgeStatus.ACK_PositiveAcknowledgeDataReceived
- ));
- break;
- //case LogicalNozzleDb_Nozzle_PhyId_Event_ACK nozzlePhyIdEvent:
- // this.pumpHandlers.Where(h => h.ifsfFuelPointId == nozzlePhyIdEvent.TargetFuelPointId).ToList().ForEach(p => p.Process(context));
- // break;
- //case FuellingPointDb_FpStatus_Event fpStatusEvent:
- // this.pumpHandlers.Where(h => h.ifsfFuelPointId == fpStatusEvent.TargetFuelPointId).ToList().ForEach(p => p.Process(context));
- // break;
- //case FuellingPointDb_FpRunningTransaction_Event fpRunningTrxEvent:
- // this.pumpHandlers.Where(h => h.ifsfFuelPointId == fpRunningTrxEvent.TargetFuelPointId).ToList().ForEach(p => p.Process(context));
- // break;
- default: base.RouteMessageToHandlers(context); break;
- }
- return Task.CompletedTask;
- }
- }
- }
|