using JiShe.CollectBus.Common.BuildSendDatas;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Common.Models;
using JiShe.CollectBus.Enums;
using JiShe.CollectBus.IotSystems.Devices;
using JiShe.CollectBus.IotSystems.MessageReceiveds;
using JiShe.CollectBus.IotSystems.Protocols;
using JiShe.CollectBus.Kafka.Producer;
using JiShe.CollectBus.Protocol.Abstracts;
using JiShe.CollectBus.Protocol.Models;
using JiShe.CollectBus.Protocol.T37612012.SendData;
using JiShe.CollectBus.Protocol3761;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
using Volo.Abp.Domain.Repositories;

namespace JiShe.CollectBus.Protocol.T37612012
{
    public class T37612012ProtocolPlugin : ProtocolPlugin
    {
        private readonly ILogger<T37612012ProtocolPlugin> _logger;

        private readonly IProducerService _producerService;

        private readonly IRepository<Device, Guid> _deviceRepository;
        private readonly ITcpService _tcpService;

        public readonly Dictionary<string, Telemetry3761PacketBuilder.T3761Delegate> T3761AFNHandlers;

        /// <summary>
        /// Initializes a new instance of the <see cref="T37612012ProtocolPlugin"/> class.
        /// </summary>
        /// <param name="serviceProvider">The service provider.</param>
        public T37612012ProtocolPlugin(IServiceProvider serviceProvider, ILogger<T37612012ProtocolPlugin> logger, ITcpService tcpService) : base(serviceProvider, logger)
        {
            _logger = logger;
            //_logger = serviceProvider.GetRequiredService<ILogger<StandardProtocolPlugin>>();
            _producerService = serviceProvider.GetRequiredService<IProducerService>();
            _deviceRepository = serviceProvider.GetRequiredService<IRepository<Device, Guid>>();
            _tcpService = tcpService;
            T3761AFNHandlers = Telemetry3761PacketBuilder.T3761AFNHandlers;
        }

        public override ProtocolInfo Info => new(nameof(T37612012ProtocolPlugin), "376.1", "TCP", "376.1协议", "DTS1980");

        public override async Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? sendAction = null)
        {
            TB3761? tB3761 = Analysis3761(messageReceived);
            if (tB3761 != null)
            {
                if (tB3761.AFN_FC?.AFN == (int)AFN.链路接口检测)
                {
                    if (tB3761.A == null || tB3761.A.Code.IsNullOrWhiteSpace() || tB3761.A.A3?.D1_D7 == null || tB3761.SEQ?.PSEQ == null)
                    {
                        _logger.LogError($"解析AFN.链路接口检测报文失败,报文：{messageReceived},TB3761:{tB3761.Serialize()}");
                    }
                    else
                    {
                        if (tB3761.DT?.Fn == (int)FN.登录)
                        {
                            // 登录回复
                            //todo 更新Redis数据缓存
                            if (tB3761.SEQ.CON == (int)CON.需要对该帧进行确认)
                                await LoginAsync(client, messageReceived, tB3761.A.Code, tB3761.A.A3?.D1_D7, tB3761.SEQ?.PSEQ);
                        }
                        else if (tB3761.DT?.Fn == (int)FN.心跳)
                        {
                            //todo 更新Redis数据缓存，主要是TCP连接，当前服务器连接配置数量满了以后，如何解决监控策略，通知新采购服务器
                            // 心跳回复
                            //心跳帧有两种情况：
                            //1. 集中器先有登录帧，再有心跳帧
                            //2. 集中器没有登录帧，只有心跳帧
                            await HeartbeatAsync(client, messageReceived, tB3761.A.Code, tB3761.A.A3?.D1_D7, tB3761.SEQ?.PSEQ);
                        }
                    }

                }
                await OnTcpNormalReceived(client, tB3761);
            }
            return (tB3761 as T)!;
        }

        /// <summary>
        /// 正常帧处理，将不同的AFN进行分发
        /// </summary>
        /// <param name="tcpSessionClient"></param>
        /// <param name="messageHexString"></param>
        /// <param name="tB3761"></param>
        /// <returns></returns>
        private async Task OnTcpNormalReceived(ITcpSessionClient tcpSessionClient, TB3761 tB3761)
        {
            //string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, aFn);
            //todo 如何确定时标？目前集中器的采集频率，都是固定，数据上报的时候，根据当前时间，往后推测出应当采集的时间点作为时标。但是如果由于网络问题，数据一直没上报的情况改怎么计算？
            //await _producerBus.PublishAsync(ProtocolConst.SubscriberReceivedEventName, new MessageReceived
            //{
            //    ClientId = client.Id,
            //    ClientIp = client.IP,
            //    ClientPort = client.Port,
            //    MessageHexString = messageHexString,
            //    DeviceNo = deviceNo,
            //    MessageId = NewId.NextGuid().ToString()
            //});

            if (tB3761.AFN_FC.BaseHexMessage == null || tB3761.DT.BaseHexMessage == null || tB3761.BaseHexMessage.HexMessageString == null)
            {
                _logger.LogError("376.1协议解析AFN失败");
                return;
            }
            // 登录心跳已做了处理，故需要忽略登录和心跳帧
            //if (tB3761.DT.Fn == (int)FN.登录 || tB3761.DT.Fn == (int)FN.心跳)
            //    return;
            //TODO：根据AFN进行分流推送到kafka
            string topicName = string.Format(ProtocolConst.AFNTopicNameFormat, tB3761.AFN_FC.AFN.ToString().PadLeft(2, '0'));
            tB3761.MessageId = Guid.NewGuid().ToString();
            tB3761.ReceivedTime = DateTime.Now;
            MessageProtocolAnalysis<TB3761> messageReceivedAnalysis = new MessageProtocolAnalysis<TB3761>()
            {
                ClientId = tcpSessionClient.Id,
                ClientIp = tcpSessionClient.IP,
                ClientPort = tcpSessionClient.Port,
                MessageHexString = tB3761.BaseHexMessage.HexMessageString!,
                DeviceNo = tB3761.A.Code!,
                MessageId = tB3761.MessageId,
                ReceivedTime = tB3761.ReceivedTime.ToString("yyyy-MM-dd HH:mm:ss"),
                Data = tB3761
            };

            List<string> topics = ProtocolConstExtensions.GetAllTopicNamesByReceived();
            if (topics.Contains(topicName))
                await _producerService.ProduceAsync(topicName, messageReceivedAnalysis);
            else
            {
                _logger.LogError($"不支持的上报kafka主题：{topicName}");
                await _producerService.ProduceAsync(ProtocolConst.SubscriberReceivedEventName, messageReceivedAnalysis);
            }

        }


        /// <summary>
        /// 登录回复
        /// </summary>
        /// <param name="client"></param>
        /// <param name="code"></param>
        /// <param name="msa"></param>
        /// <param name="pseq"></param>
        /// <returns></returns>
        public async Task LoginAsync(ITcpSessionClient client, string messageReceived, string code, int? msa, int? pseq)
        {
            string oldClientId = $"{client.Id}";
            await client.ResetIdAsync(code);
            var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code);
            if (deviceInfoList != null && deviceInfoList.Count > 1)
            {
                //todo 推送集中器编号重复预警
                _logger.LogError($"集中器编号：{code}，存在多个集中器，请检查集中器编号是否重复");
                return;
            }

            var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code);
            if (entity == null)
            {
                await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online));
            }
            else
            {
                entity.UpdateByLoginAndHeartbeat(oldClientId);
                await _deviceRepository.UpdateAsync(entity);
            }

            var messageReceivedLoginEvent = new MessageReceivedLogin
            {
                ClientId = code,
                ClientIp = client.IP,
                ClientPort = client.Port,
                MessageHexString = messageReceived,
                DeviceNo = code,
                MessageId = Guid.NewGuid().ToString(),
                ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            };
            await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginReceivedEventName, messageReceivedLoginEvent);
            var reqParam = new ReqParameter2
            {
                AFN = AFN.确认或否认,
                FunCode = (int)CFromStationFunCode.链路数据,
                PRM = PRM.从动站报文,
                A = code,
                Seq = new Seq()
                {
                    TpV = TpV.附加信息域中无时间标签,
                    FIRFIN = FIRFIN.单帧,
                    CON = CON.需要对该帧进行确认,
                    PRSEQ = pseq!.Value
                },
                MSA = msa!.Value,
                Pn = 0,
                Fn = 1
            };
            var bytes = Build3761SendData.BuildSendCommandBytes(reqParam);
            var issuedEventMessage = new IssuedEventMessage
            {
                ClientId = messageReceivedLoginEvent.ClientId,
                DeviceNo = messageReceivedLoginEvent.DeviceNo,
                Message = bytes,
                Type = IssuedEventType.Login,
                MessageId = messageReceivedLoginEvent.MessageId
            };
            if (_tcpService.ClientExists(issuedEventMessage.ClientId))
            {
                await _tcpService.SendAsync(issuedEventMessage.ClientId, issuedEventMessage.Message);
                _logger.LogInformation($"集中器地址{issuedEventMessage.ClientId} 登录回复下发内容:{Convert.ToHexString(bytes)}");
                await _producerService.ProduceAsync(ProtocolConst.SubscriberLoginIssuedEventName, issuedEventMessage);
            }
        }

        /// <summary>
        /// 心跳帧解析
        /// </summary>
        /// <param name="client"></param>
        /// <param name="code"></param>
        /// <param name="msa"></param>
        /// <param name="pseq"></param>
        /// <returns></returns>
        public async Task HeartbeatAsync(ITcpSessionClient client, string messageReceived, string code, int? msa, int? pseq)
        {

            string clientId = code;
            string oldClientId = $"{client.Id}";
            var deviceInfoList = await _deviceRepository.GetListAsync(a => a.Number == code);
            if (deviceInfoList != null && deviceInfoList.Count > 1)
            {
                //todo 推送集中器编号重复预警
                _logger.LogError($"集中器编号：{code}，存在多个集中器，请检查集中器编号是否重复");
                return;
            }

            var entity = deviceInfoList?.FirstOrDefault(a => a.Number == code);
            if (entity == null) //没有登录帧的设备，只有心跳帧
            {
                await client.ResetIdAsync(clientId);
                await _deviceRepository.InsertAsync(new Device(code, oldClientId, DateTime.Now, DateTime.Now, DeviceStatus.Online));
            }
            else
            {
                if (clientId != oldClientId)
                {
                    entity.UpdateByLoginAndHeartbeat(oldClientId);
                }
                else
                {
                    entity.UpdateByLoginAndHeartbeat();
                }

                await _deviceRepository.UpdateAsync(entity);
            }

            var messageReceivedHeartbeatEvent = new MessageReceivedHeartbeat
            {
                ClientId = clientId,
                ClientIp = client.IP,
                ClientPort = client.Port,
                MessageHexString = messageReceived,
                DeviceNo = code,
                MessageId = Guid.NewGuid().ToString(),
                ReceivedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            };
            await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatReceivedEventName, messageReceivedHeartbeatEvent);

            var reqParam = new ReqParameter2()
            {
                AFN = AFN.确认或否认,
                FunCode = (int)CFromStationFunCode.链路数据,
                PRM = PRM.从动站报文,
                A = code,
                Seq = new Seq()
                {
                    TpV = TpV.附加信息域中无时间标签,
                    FIRFIN = FIRFIN.单帧,
                    CON = CON.不需要对该帧进行确认,
                    PRSEQ = pseq!.Value,
                },
                MSA = msa!.Value,
                Pn = 0,
                Fn = 1
            };
            var bytes = Build3761SendData.BuildSendCommandBytes(reqParam);

            IssuedEventMessage issuedEventMessage = new IssuedEventMessage
            {
                ClientId = messageReceivedHeartbeatEvent.ClientId,
                DeviceNo = messageReceivedHeartbeatEvent.DeviceNo,
                Message = bytes,
                Type = IssuedEventType.Heartbeat,
                MessageId = messageReceivedHeartbeatEvent.MessageId
            };
            if (_tcpService.ClientExists(issuedEventMessage.ClientId))
            {
                await _tcpService.SendAsync(issuedEventMessage.ClientId, bytes);
                _logger.LogWarning($"集中器地址{issuedEventMessage.ClientId} 心跳回复下发内容:{Convert.ToHexString(bytes)}");
                await _producerService.ProduceAsync(ProtocolConst.SubscriberHeartbeatIssuedEventName, issuedEventMessage);
            }


        }

        /// <summary>
        /// 组装报文
        /// </summary>
        /// <param name="request">报文构建参数</param>
        /// <returns></returns>
        public override async Task<ProtocolBuildResponse> BuildAsync(ProtocolBuildRequest request)
        {
            if (request == null)
            {
                throw new Exception($"{nameof(T37612012ProtocolPlugin)} 报文构建失败，参数为空");
            }
            var itemCodeArr = request.ItemCode.Split('_');
            var aFNStr = itemCodeArr[0];
            var aFN = (AFN)aFNStr.HexToDec();
            var fn = int.Parse(itemCodeArr[1]);
            Telemetry3761PacketResponse builderResponse = null;

            List<string> dataUnit = new List<string>();
            //数据转发场景 10H_F1_1CH
            if (aFNStr == "10" && request.SubProtocolRequest != null && string.IsNullOrWhiteSpace(request.SubProtocolRequest.ItemCode) == false)
            {
                //var t645PacketHandlerName = $"C{request.SubProtocolRequest.ItemCode}_Send";
                //Telemetry645PacketResponse t645PacketResponse = null;

                //if (T645ControlHandlers != null && T645ControlHandlers.TryGetValue(t645PacketHandlerName
                //  , out var t645PacketHandler))
                //{
                //    t645PacketResponse = t645PacketHandler(new Telemetry645PacketRequest()
                //    {
                //        MeterAddress = request.SubProtocolRequest.MeterAddress,
                //        Password = request.SubProtocolRequest.Password,
                //        ItemCode = request.SubProtocolRequest.ItemCode,
                //    });
                //}

                //if (t645PacketResponse != null)
                //{
                //    dataUnit = t645PacketResponse.Data;
                //}
            }

            string afnMethonCode = $"AFN{aFNStr}_Fn_Send";
            if (T3761AFNHandlers != null && T3761AFNHandlers.TryGetValue(afnMethonCode
                    , out var handler))
            {
                builderResponse = handler(new Telemetry3761PacketRequest()
                {
                    FocusAddress = request.FocusAddress,
                    Fn = fn,
                    Pn = request.Pn,
                    DataUnit = dataUnit,
                });
            }

            if (builderResponse == null)
            {
                return new ProtocolBuildResponse();
            }

            var result = builderResponse.Adapt<ProtocolBuildResponse>();
            result.IsSuccess = true;

            return await Task.FromResult(result);
        }




        /// <summary>
        /// 解析376.1帧
        /// </summary>
        /// <param name="messageReceived"></param>
        /// <returns></returns>
        public virtual TB3761? Analysis3761(string messageReceived)
        {
            try
            {
                var hexStringList = messageReceived.StringToPairs();
                // 初步校验
                if (hexStringList.Count < 6 || hexStringList.FirstOrDefault() != "68" || hexStringList.Skip(5).Take(1).FirstOrDefault() != "68" || hexStringList.Count < 18 || hexStringList.LastOrDefault() != "16")
                {
                    _logger.LogError($"解析Analysis3761校验不通过,报文：{messageReceived}");
                }
                else
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    TB3761 tB3761 = new TB3761
                    {
                        BaseHexMessage=baseHexMessage,
                        C = Analysis_C(hexStringList),
                        A = Analysis_A(hexStringList),
                        AFN_FC = Analysis_AFN_FC(hexStringList),
                        SEQ = Analysis_SEQ(hexStringList),
                        UnitData = Analysis_UnitData(hexStringList),
                        DA = Analysis_DA(hexStringList),
                        DT = Analysis_DT(hexStringList)
                    };
                    return tB3761;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis3761错误,报文：{messageReceived},异常：{ex.Message}");
            }
            return null;
        }

        /// <summary>
        /// 控制域C解析
        /// </summary>
        /// <returns></returns>
        public virtual C Analysis_C(List<string> hexStringList)
        {
            C c = new C();
            try
            {
                if (hexStringList.Count > 6)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(6, 1) // 控制域 1字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    string binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
                    c = new C
                    {
                        BaseHexMessage = baseHexMessage,
                        FC = binStr.Substring(binStr.Length - 4, 4).BinToDec(),
                        FCV = binStr.Substring(3, 1).BinToDec(),
                        FCB = binStr.Substring(2, 1).BinToDec(),
                        PRM = binStr.Substring(1, 1).BinToDec(),
                        DIR = binStr.Substring(0, 1).BinToDec()
                    };
                    return c;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_C错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }

            return c;
        }

        /// <summary>
        /// 地址域A解析
        /// </summary>
        /// <param name="hexStringList"></param>
        /// <returns></returns>
        public virtual A Analysis_A(List<string> hexStringList)
        {
            A a = new A();
            try
            {
                if (hexStringList.Count > 7)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(7, 5) // 地址域 5个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    a = new A
                    {
                        BaseHexMessage = baseHexMessage,
                        A1 = baseHexMessage.HexMessageList.ListReverseToStr(0, 2),//.DataConvert(10);//行政区划码A1 
                        A2 = baseHexMessage.HexMessageList.ListReverseToStr(2, 2).PadLeft(5, '0').HexToDec(),//终端地址A2
                        A3 = Analysis_A3(baseHexMessage.HexMessageList) //主站地址和组地址标志A3
                    };
                    a.Code = $"{a.A1.PadLeft(4, '0')}{a.A2.ToString()!.PadLeft(5, '0')}";

                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_A错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }

            return a;

        }

        /// <summary>
        /// 站地址和组地址标志A3
        /// </summary>
        /// <param name="hexAList">地址域A集合</param>
        /// <returns></returns>
        public virtual A3 Analysis_A3(List<string> hexAList)
        {
            A3 a3 = new A3();
            try
            {
                if (hexAList.Count != 0)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexAList.GetRange(4, 1) // 站地址和组地址标志A3 1个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
                    a3 = new A3
                    {
                        BaseHexMessage = baseHexMessage,
                        D0 = binStr.Substring(binStr.Length - 1, 1).BinToDec(),
                        D1_D7 = binStr.Substring(0, binStr.Length - 1).BinToDec()
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_A3错误,报文：{string.Join("", hexAList)},异常：{ex.Message}");
            }

            return a3;
        }

        /// <summary>
        /// AFN_FC功能码
        /// </summary>
        /// <returns></returns>
        public virtual AFN_FC Analysis_AFN_FC(List<string> hexStringList)
        {
            AFN_FC aFN_FC = new AFN_FC();
            try
            {
                if (hexStringList.Count > 12)
                {

                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(12, 1) //AFN功能码 1个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);

                    aFN_FC = new AFN_FC
                    {
                        BaseHexMessage = baseHexMessage,
                        AFN = baseHexMessage.HexMessageString.HexToDec(),
                    };
                }

            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_AFN_FC错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }

            return aFN_FC;
        }

        /// <summary>
        /// 解析帧序列域SEQ
        /// </summary>
        /// <returns></returns>
        public virtual SEQ Analysis_SEQ(List<string> hexStringList)
        {
            SEQ seq = new SEQ();
            try
            {
                if (hexStringList.Count>13)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(13, 1) //帧序列域 SEQ 1个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
                    seq = new SEQ
                    {
                        BaseHexMessage= baseHexMessage,
                        PSEQ = binStr.Substring(binStr.Length - 4, 4).BinToDec(),
                        CON = binStr.Substring(3, 1).BinToDec(),
                        FIN = binStr.Substring(2, 1).BinToDec(),
                        FIR = binStr.Substring(1, 1).BinToDec(),
                        TpV = binStr.Substring(0, 1).BinToDec()
                    };
                }

            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_SEQ错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }
            return seq;
        }


        /// <summary>
        /// 数据单元标识及数据单元数据
        /// </summary>
        public virtual UnitData Analysis_UnitData(List<string> hexStringList)
        {
            UnitData unitData = new UnitData();
            try
            {
                if (hexStringList.Count>14)
                {
                    unitData = new UnitData
                    {
                        HexMessageList = hexStringList.GetRange(14, hexStringList.Count - 14 - 2) //总数字节数-固定长度报文头-控制域C-地址域A-校验和CS-结束字符（16H）
                    };
                    unitData.HexMessageString = string.Join(" ", unitData.HexMessageList);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_UnitData错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }
            return unitData;
        }

        /// <summary>
        /// 信息点DA Pn
        /// </summary>
        /// <returns></returns>
        public virtual DA Analysis_DA(List<string> hexStringList)
        {
            DA da = new DA();
            try
            {
                if (hexStringList.Count > 14)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(14, 2) //信息点DA Pn  2个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    var da1 = baseHexMessage.HexMessageList[0];
                    var da2 = baseHexMessage.HexMessageList[1];
                    da = new DA()
                    {
                        BaseHexMessage = baseHexMessage,
                        Pn = CalculatePn(da1, da2)
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_DA错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }
            return da;
        }

        /// <summary>
        /// 信息类DT Fn
        /// </summary>
        /// <returns></returns>
        public virtual DT Analysis_DT(List<string> hexStringList)
        {
            DT dt = new DT();
            try
            {
                if (hexStringList.Count > 16)
                {
                    BaseHexMessage baseHexMessage = new BaseHexMessage
                    {
                        HexMessageList = hexStringList.GetRange(16, 2) //信息类DT Fn 2个字节
                    };
                    baseHexMessage.HexMessageString = string.Join(" ", baseHexMessage.HexMessageList);
                    var dt1 = baseHexMessage.HexMessageList[0];
                    var dt2 = baseHexMessage.HexMessageList[1];
                    dt = new DT()
                    {
                        BaseHexMessage = baseHexMessage,
                        Fn = CalculateFn(dt1, dt2)
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"解析Analysis_DT错误,报文：{string.Join("", hexStringList)},异常：{ex.Message}");
            }

            return dt;

        }


        /// <summary>
        /// 计算Pn
        /// </summary>
        /// <param name="da1"></param>
        /// <param name="da2"></param>
        /// <returns></returns>
        public static int CalculatePn(string da1, string da2) => (da2.HexToDec() - 1) * 8 + (8 - da1.HexTo4BinZero().IndexOf(da1.Equals("00") ? "0" : "1"));


        /// <summary>
        /// 计算Fn
        /// </summary>
        /// <param name="dt1"></param>
        /// <param name="dt2"></param>
        /// <returns></returns>
        public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));



        #region 上行命令

        //68 
        //32 00
        //32 00
        //68
        //C9  1100'1001. 控制域C。
        // D7=1, （终端发送）上行方向。
        // D6=1, 此帧来自启动站。
        // D5=0, (上行方向)要求访问位。表示终端无事件数据等待访问。
        // D4=0, 保留
        // D3~D0=9, 功能码。链路测试

        //20 32  行政区划码
        //90 26  终端地址
        //00 主站地址和组地址标志。终端为单地址。 //3220 09 87 2
        // 终端启动的发送帧的 MSA 应为 0, 其主站响应帧的 MSA 也应为 0.
        //02 应用层功能码。AFN=2, 链路接口检测
        //70 0111'0000. 帧序列域。无时间标签、单帧、需要确认。
        //00 00  信息点。DA1和DA2全为“0”时，表示终端信息点。
        //01 00 信息类。F1, 登录。
        //44  帧尾，包含用户区数据校验和
        //16  帧结束标志

        /// <summary>
        /// 解析上行命令
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public CommandReulst? AnalysisCmd(string cmd)
        {
            CommandReulst? commandReulst = null;
            var hexStringList = cmd.StringToPairs();

            if (hexStringList.Count < hearderLen)
            {
                return commandReulst;
            }
            //验证起始字符
            if (!hexStringList[0].IsStartStr() || !hexStringList[5].IsStartStr())
            {
                return commandReulst;
            }

            var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}";
            var lenBin = lenHexStr.HexToBin();
            var len = lenBin.Remove(lenBin.Length - 2).BinToDec();
            //验证长度
            if (hexStringList.Count - 2 != hearderLen + len)
                return commandReulst;

            var userDataIndex = hearderLen;
            var c = hexStringList[userDataIndex];//控制域 1字节
            userDataIndex += 1;

            var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节         
            var a = AnalysisA(aHexList);
            var a3Bin = aHexList[4].HexToBin().PadLeft(8, '0');
            var mSA = a3Bin.Substring(0, 7).BinToDec();
            userDataIndex += 5;

            var aFN = (AFN)hexStringList[userDataIndex].HexToDec();//1字节
            userDataIndex += 1;

            var seq = hexStringList[userDataIndex].HexToBin().PadLeft(8, '0');
            var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1));
            var fIRFIN = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2));
            var cON = (CON)Convert.ToInt32(seq.Substring(3, 1));
            var prseqBin = seq.Substring(4, 4);
            userDataIndex += 1;

            // (DA2 - 1) * 8 + DA1 = pn           
            var da1Bin = hexStringList[userDataIndex].HexToBin();
            var da1 = da1Bin == "0" ? 0 : da1Bin.Length;
            userDataIndex += 1;
            var da2 = hexStringList[userDataIndex].HexToDec();
            var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1;
            userDataIndex += 1;
            //(DT2*8)+DT1=fn
            var dt1Bin = hexStringList[userDataIndex].HexToBin();
            var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0;
            userDataIndex += 1;
            var dt2 = hexStringList[userDataIndex].HexToDec();
            var fn = dt2 * 8 + dt1;
            userDataIndex += 1;

            //数据单元
            var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList();

            //EC
            //Tp
            commandReulst = new CommandReulst()
            {
                A = a,
                MSA = mSA,
                AFN = aFN,
                Seq = new Seq()
                {
                    TpV = tpV,
                    FIRFIN = fIRFIN,
                    CON = cON,
                    PRSEQ = prseqBin.BinToDec(),
                },
                CmdLength = len,
                Pn = pn,
                Fn = fn,
                HexDatas = datas
            };

            return commandReulst;
        }

        /// <summary>
        /// 解析地址
        /// </summary>
        /// <param name="aHexList"></param>
        /// <returns></returns>
        private string AnalysisA(List<string> aHexList)
        {
            var a1 = aHexList[1] + aHexList[0];
            var a2 = aHexList[3] + aHexList[2];
            var a2Dec = a2.HexToDec();
            var a3 = aHexList[4];
            var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}";
            return a;
        }

        #endregion
    }
}
