using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Configuration; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using Timer = System.Timers.Timer; using System.Collections; using Edge.Core.Processor; using Edge.Core.IndustryStandardInterface.Pump; using Wayne.FDCPOSLibrary; using System.Xml; using Edge.Core.Database.Models; using System.Threading.Tasks; using Edge.Core.Processor.Communicator; using Edge.Core.Processor.Dispatcher.Attributes; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Stateless; using Edge.Core.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Gilbarco_Pump { #region Ctor parameters public class PumpGroupConfig { /// /// 数据发送端的地址编号 /// 一般是指FCC? 则应该是一个全局共享值,放0xE0 /// public byte FccCommAddress { get; set; } = 0xE0; /// /// 数据接收端的地址编号 /// 指油机端的配置值,应该是每个通讯链路都不一样,一个链路上可能有1个或者多个加油点 /// public byte DispenserCommBoardAddress { get; set; } public List PumpConfigs { get; set; } } public class PumpConfig { /// /// used by Fcc inside, the classic pump id concept. /// public byte PumpId { get; set; } /// /// 枪号为以整个加油站为基础的油枪顺序编号 /// 就是全站枪号? /// public byte DispenserSideNozzleId { get; set; } } #endregion /// /// 协议支持5787bps,8 位数据位,1 位起始位,1 位停止位,Even校验位 /// [MetaPartsRequired(typeof(HalfDuplexActivePollingDeviceProcessor<,>))] [MetaPartsRequired(typeof(ComPortCommunicator<>))] [MetaPartsRequired(typeof(TcpClientCommunicator<>))] [MetaPartsDescriptor( "lang-zh-cn:吉尔巴克加油机lang-en-us:Gilbarco dispenser", "用于驱动 吉尔巴克 加油机", new[] { "lang-zh-cn:加油机lang-en-us:Pump" })] public class PumpGroupHandler : IEnumerable, IDeviceHandler { private IServiceProvider services; private ILogger logger = NullLogger.Instance; public PumpGroupConfig pumpGroupConfig; protected IEnumerable nozzleExtraInfos; protected IContext context; protected IEnumerable pumpHandlers; private object rotateFrameNo_Guard = new object(); /// /// private byte rotateFrameNo = 0; /// /// get a valid FrameNo which from >=1 and <= 0x3F. /// /// public byte GenerateNewFrameNo() { lock (this.rotateFrameNo_Guard) { //return 0; if (this.rotateFrameNo > 0x3E) this.rotateFrameNo = 0; return (byte)(++this.rotateFrameNo); } } [ParamsJsonSchemas("PumpGroupHandlerCtorParamsJsonSchemas")] public PumpGroupHandler(PumpGroupConfig pumpGroupConfig, IServiceProvider services) { this.pumpGroupConfig = pumpGroupConfig; this.services = services; var loggerFactory = services.GetRequiredService(); this.logger = loggerFactory.CreateLogger("PumpHandler"); this.pumpHandlers = pumpGroupConfig.PumpConfigs.Select(pc => new StatePumpHandler(this, pc.PumpId, pc.DispenserSideNozzleId, services)).ToList(); } public void OnFdcServerInit(Dictionary parameters) { if (parameters != null && parameters.TryGetValue("NozzleProductMapping", out object param)) { this.nozzleExtraInfos = param as IEnumerable; } } public void Init(IContext context) { this.context = context; var timeWindowWithActivePollingOutgoing = this.context.Outgoing as TimeWindowWithActivePollingOutgoing; //this.pollingInterval = timeWindowWithActivePollingOutgoing.PollingInterval; timeWindowWithActivePollingOutgoing.PollingMsgProducer = () => { return null; }; this.pumpHandlers.ToList().ForEach(p => p.Init(this.context)); this.context.Incoming.OnLongTimeNoSeeMessage += (_, __) => { this.pumpHandlers.ToList().ForEach(p => p.TriggerPumpOffline()); }; this.context.Incoming.LongTimeNoSeeMessageTimeout = 6000; } public async Task Process(IContext context) { this.context = context; foreach (var ph in this.pumpHandlers) await ph.Process(context); } public IEnumerator GetEnumerator() { return this.pumpHandlers.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.pumpHandlers.GetEnumerator(); } } }