using Edge.Core.Processor; using Edge.Core.IndustryStandardInterface.Pump; using LanTian_Pump_664_Or_886.MessageEntity; using LanTian_Pump_664_Or_886.MessageEntity.Outgoing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; using System.Text.Json.Serialization; using Edge.Core.UniversalApi; using Edge.Core.Processor.Dispatcher.Attributes; using Edge.Core.Processor.Communicator; namespace LanTian_Pump_664_Or_886 { public class PumpGroupParameter { public enum PumpModelEnum { // for all cases, this type of dispenser, like totalizer, amount, price data fields and etc., has smaller value range Model_664 = 0, // for all cases, this type of dispenser, like totalizer, amount, price data fields and etc., has wider value range Model_886 = 1 } public enum PumpAuthorizeModeEnum { /// /// in this mode, dispenser need get fc authorized then can start fueling. /// FC_Authorize = 0, /// /// in this mode, dispenser can start fueling without authorize from fc, so lift nozzle, fueling start. /// Pump_Self_Authorize = 1, } public class PumpParameter { public int PumpId { get; set; } /// /// setup in physical dispenser side. /// public byte Address { get; set; } public PumpModelEnum? PumpModel { get; set; } = PumpModelEnum.Model_664; public PumpAuthorizeModeEnum? PumpAuthorizeMode { get; set; } = PumpAuthorizeModeEnum.FC_Authorize; public int? AmountDecimalDigits { get; set; } = 2; public int? VolumeDecimalDigits { get; set; } = 2; public int? PriceDecimalDigits { get; set; } = 2; public int? VolumeTotalizerDecimalDigits { get; set; } = 2; } public IEnumerable PumpParameters { get; set; } } [MetaPartsRequired(typeof(HalfDuplexActivePollingDeviceProcessor<,>))] [MetaPartsRequired(typeof(ComPortCommunicator<>))] [MetaPartsRequired(typeof(TcpClientCommunicator<>))] [MetaPartsDescriptor( "lang-zh-cn:蓝天加油机lang-en-us:BlueSky Pump", "lang-zh-cn:用于驱动蓝天协议的加油机lang-en-us:Used for driven BlueSky Pump which use BlueSky Protocol", new[] { "lang-zh-cn:加油机lang-en-us:Pump" })] public class PumpGroupHandler : IEnumerable, IDeviceHandler { private IContext context; private List pumpHandlers; private IServiceProvider services; static ILogger logger = NullLogger.Instance; public PumpGroupHandler(string rawUglyEncodedCommaJsonStr, IServiceProvider services) { this.services = services; var loggerFactory = services.GetRequiredService(); logger = loggerFactory.CreateLogger("PumpHandler"); var jsonSerializerOptions = new JsonSerializerOptions() { WriteIndented = true, }; jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); var decoded = rawUglyEncodedCommaJsonStr.Replace("____UglyEncodedComma____", ","); var pumpGroupParameter = System.Text.Json.JsonSerializer.Deserialize(decoded, jsonSerializerOptions); this.CreatePumpHandlers(pumpGroupParameter); } [ParamsJsonSchemas("PumpGroupHandlerCtorParamsJsonSchemas")] public PumpGroupHandler(PumpGroupParameter pumpGroupParameter, IServiceProvider services) { this.services = services; var loggerFactory = services.GetRequiredService(); logger = loggerFactory.CreateLogger("PumpHandler"); this.CreatePumpHandlers(pumpGroupParameter); } private void CreatePumpHandlers(PumpGroupParameter pumpGroupParameter) { this.pumpHandlers = new List(); this.pumpHandlers.AddRange(pumpGroupParameter.PumpParameters.Select(p => new StatePumpHandler(p.PumpId, p.Address, p.PumpModel.Value, p.PumpAuthorizeMode.Value, p.AmountDecimalDigits.Value, p.VolumeDecimalDigits.Value, p.PriceDecimalDigits.Value, p.VolumeTotalizerDecimalDigits.Value, this.services))); } public IEnumerator GetEnumerator() { return this.pumpHandlers.GetEnumerator(); } public void Init(IContext context) { this.context = context; this.pumpHandlers.ForEach(p => p.Init(this.context)); var timeWindowWithActivePollingOutgoing = this.context.Outgoing as TimeWindowWithActivePollingOutgoing; int previousPolledHandlerIndex = 0; timeWindowWithActivePollingOutgoing.PollingMsgProducer = () => { if (this.pumpHandlers.Count <= previousPolledHandlerIndex) previousPolledHandlerIndex = 0; var target = this.pumpHandlers[previousPolledHandlerIndex++]; return new ReadPumpStateRequest() { Adrs = (byte)target.PumpPhysicalId }; }; } public Task Process(IContext context) { this.context = context; var ph = this.pumpHandlers.FirstOrDefault(p => (byte)(p.PumpPhysicalId) == context.Incoming.Message.Adrs); if (ph == null) { logger.LogInformation("PumpGroupHandler does not contain pumpHandler with physcialId: " + context.Incoming.Message.Adrs.ToString("X2")); return Task.CompletedTask; } return ph.Process(context); } IEnumerator IEnumerable.GetEnumerator() { return this.pumpHandlers.GetEnumerator(); } [UniversalApi] public Task ChangeFuelPriceAsync(int pumpId, int newPriceWithoutDecimalPoint, byte logicalNozzleId) { return this.pumpHandlers.FirstOrDefault(ph => ph.PumpId == pumpId)?.ChangeFuelPriceAsync(newPriceWithoutDecimalPoint, logicalNozzleId); } [UniversalApi] public Task> QueryTotalizerAsync(int pumpId, byte logicalNozzleId) { return this.pumpHandlers.FirstOrDefault(ph => ph.PumpId == pumpId)?.QueryTotalizerAsync(logicalNozzleId); } } }