123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- 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 ZhongSheng_NonIC_Pump
- {
- #region Ctor parameters
- public class PumpGroupConfig
- {
- /// <summary>
- /// 数据发送端的地址编号
- /// 一般是指FCC? 则应该是一个全局共享值,放0xE0
- /// </summary>
- public byte FccCommAddress { get; set; } = 0xE0;
- /// <summary>
- /// 数据接收端的地址编号
- /// 指油机端的配置值,应该是每个通讯链路都不一样,一个链路上可能有1个或者多个加油点
- /// </summary>
- public byte DispenserCommBoardAddress { get; set; }
- public List<PumpConfig> PumpConfigs { get; set; }
- }
- public class PumpConfig
- {
- /// <summary>
- /// used by Fcc inside, the classic pump id concept.
- /// </summary>
- public byte PumpId { get; set; }
- /// <summary>
- /// 枪号为以整个加油站为基础的油枪顺序编号
- /// 就是全站枪号?
- /// </summary>
- public byte DispenserSideNozzleId { get; set; }
- }
- #endregion
- /// <summary>
- /// 协议支持9600bps,8 位数据位,1 位起始位,1 位停止位,无校验位
- /// </summary>
- [MetaPartsRequired(typeof(HalfDuplexActivePollingDeviceProcessor<,>))]
- [MetaPartsRequired(typeof(ComPortCommunicator<>))]
- [MetaPartsRequired(typeof(TcpClientCommunicator<>))]
- [MetaPartsDescriptor(
- "lang-zh-cn:中升非IC卡加油机lang-en-us:ZhongSheng Non-IC card dispenser",
- "用于驱动 中升非IC卡 加油机, 它每把枪就是一个Pump即一个加油点,且油机上配置的枪号等同于全站枪号。此油机可以配置提枪直接出油,也可以配置成需要后台授权,请在加油机上配置(菜单IC卡支付方式中选择第4项即开启后台授权模式)。根据油机方的技术人员说明,我们中控这边对接的油机,都会是单枪单显,或者是2枪2显,不会有单面双单价的型号。 原生支持 8位数据位,1位起始位,1位停止位,无校验位RS422。",
- new[] { "lang-zh-cn:加油机lang-en-us:Pump" })]
- public class PumpGroupHandler : IEnumerable<IFdcPumpController>, IDeviceHandler<byte[], MessageTemplateBase>
- {
- private IServiceProvider services;
- private ILogger logger = NullLogger.Instance;
- public PumpGroupConfig pumpGroupConfig;
- protected IEnumerable<NozzleExtraInfo> nozzleExtraInfos;
- protected IContext<byte[], MessageTemplateBase> context;
- protected IEnumerable<StatePumpHandler> pumpHandlers;
- private object rotateFrameNo_Guard = new object();
- /// <summary>
- /// </summary>
- private byte rotateFrameNo = 0;
- /// <summary>
- /// get a valid FrameNo which from >=1 and <= 0x3F.
- /// </summary>
- /// <returns></returns>
- 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<ILoggerFactory>();
- this.logger = loggerFactory.CreateLogger("PumpHandler");
- this.pumpHandlers =
- pumpGroupConfig.PumpConfigs.Select(pc =>
- new StatePumpHandler(this, pc.PumpId, pc.DispenserSideNozzleId, services)).ToList();
- }
- public void OnFdcServerInit(Dictionary<string, object> parameters)
- {
- if (parameters != null && parameters.TryGetValue("NozzleProductMapping", out object param))
- {
- this.nozzleExtraInfos = param as IEnumerable<NozzleExtraInfo>;
- }
- }
- public void Init(IContext<byte[], MessageTemplateBase> context)
- {
- this.context = context;
- var timeWindowWithActivePollingOutgoing =
- this.context.Outgoing as TimeWindowWithActivePollingOutgoing<byte[], MessageTemplateBase>;
- //this.pollingInterval = timeWindowWithActivePollingOutgoing.PollingInterval;
- timeWindowWithActivePollingOutgoing.PollingMsgProducer =
- () =>
- {
- //if (!this.isCommConnected) return null;
- return new GenericInquiryRequest()
- {
- SourceAddress = this.pumpGroupConfig.FccCommAddress,
- TargetAddress = this.pumpGroupConfig.DispenserCommBoardAddress,
- FrameSeqNo = this.GenerateNewFrameNo(),
- };// this.GetNewMessageToken(target.PumpId));
- };
- 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<byte[], MessageTemplateBase> context)
- {
- this.context = context;
- //var ph = this.pumpHandlers.FirstOrDefault(p => (byte)(p.PumpPhysicalId) == context.Incoming.Message.SourceAddress);
- //if (ph == null)
- //{
- // logger.LogInformation("PumpGroupHandler does not contain pumpHandler with physcialId: "
- // + context.Incoming.Message.SourceAddress.ToString("X2"));
- // return Task.CompletedTask;
- //}
- //有可能是设备端是2枪2显,但将区别的逻辑放入到pumpHandler里面去处理
- foreach (var ph in this.pumpHandlers)
- await ph.Process(context);
- }
- public IEnumerator<IFdcPumpController> GetEnumerator()
- {
- return this.pumpHandlers.GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.pumpHandlers.GetEnumerator();
- }
- }
- }
|