|
- using DotNetty.Buffers;
- using DotNetty.Transport.Channels;
- using Microsoft.Extensions.Logging;
- using NearCardAttendance.Common.helper;
- using NearCardAttendance.Service.TcpServer.Mapper;
- using NearCardAttendance.Service.TcpServer.Protocol;
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Channels;
- using System.Threading.Tasks;
- using NearCardAttendance.Model;
- using Microsoft.Extensions.Options;
- using TelpoDataService.Util.Entities.GpsCard;
- using TelpoDataService.Util;
- using TelpoDataService.Util.Clients;
- using TelpoDataService.Util.Models;
- using TelpoDataService.Util.QueryObjects;
-
- namespace NearCardAttendance.Service.TcpServer.Handler
- {
- public class RegisterHandler : ChannelHandlerAdapter
- {
- private readonly ILogger<RegisterHandler> _logger;
- private readonly HttpHelper _httpHelper = default!;
- //private readonly IDisposable _loggerScope = default!;
- private readonly ServiceConfig _configService;
- private readonly GpsCardAccessorClient<GpsDeviceConfig> _deviceConfigApiClient;
-
- //private readonly TcpClientsManager _managerTcpClients;
- //private readonly ScheduleResendManager _managerScheduleResend;
-
- public RegisterHandler(ILogger<RegisterHandler> logger, GpsCardAccessorClient<GpsDeviceConfig> deviceConfigApiClient,HttpHelper httpHelper, IOptions<ServiceConfig> configService)
- {
- _logger = logger;
- _httpHelper = httpHelper;
- _configService = configService.Value;
- _deviceConfigApiClient= deviceConfigApiClient;
- }
-
- public override void ChannelActive(IChannelHandlerContext context)
- {
- base.ChannelActive(context); // Pass the event to the next handler
- }
-
- public override async void ChannelInactive(IChannelHandlerContext context)
- {
- try
- {
- await Task.CompletedTask;
- }
- catch (Exception ex)
- {
- _logger.LogInformation($"{nameof(RegisterHandler)} --- {nameof(ChannelInactive)} 出错\n{ex.Message}\n{ex.StackTrace}");
- }
- }
-
- public override void HandlerRemoved(IChannelHandlerContext context)
- {
- base.HandlerRemoved(context);
- }
-
- public override async void ChannelRead(IChannelHandlerContext context, object message)
- {
- if (message is ProtocolParser parser)
- {
- try
- {
- using (_logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = parser.SeqNo }))
- {
- //认证
- //if (parser.FuncNo.Equals("10"))
- //{
- // #region 认证业务
- // // PHONE_AUTHEN
- // ProtocolWrapper phoneAuthWrapper = new(parser.FuncNo, parser.SeqNo, "1");
- // await SendToTcpClientAsync(phoneAuthWrapper, context.Channel);
-
- // // ABT_STATUS 延时3秒 给终端同步时间
- // await context.Channel.EventLoop.Schedule(async () =>
- // {
- // ProtocolWrapper abtStatusWrapper = new("82", parser.SeqNo, DateTime.Now.ToString("yyyyMMddHHmmss"));
- // await SendToTcpClientAsync(abtStatusWrapper, context.Channel);
- // },TimeSpan.FromSeconds(3));
-
- // #endregion
- //}
- //else if (parser.FuncNo.Equals("82"))
- //{
- // // 认证成功
- // _logger.LogInformation($"认证成功{parser.Data}.");
- //}
- //// 心跳
- //else if (parser.FuncNo.Equals("05"))
- //{
- // ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo,"");
- // await SendToTcpClientAsync(stdtSignRecsWrapper, context.Channel);
- //} // STDT_SIGN_RECS
- //else if (parser.FuncNo.Equals("04"))
- //{
- // // 回应设备
- // ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo,"1");
- // await SendToTcpClientAsync(stdtSignRecsWrapper, context.Channel);
- // // 刷卡考勤信息,需要推送给第三方平台
-
- // //var url = "";
-
- // //await _httpHelper.HttpToPostAsync(url, new object());
- //}
- //// STDT_SCHOOL_RECS
- //else if (parser.FuncNo.Equals("08"))
- //{
- // _logger.LogInformation($"接受STDT_SCHOOL_RECS 08 成功{parser.Data}.");
- // ProtocolWrapper stdtSchoolRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
- // await SendToTcpClientAsync(stdtSchoolRecsWrapper, context.Channel);
- //}
-
-
- //switch (parser.FuncNo)
- //{
- // case "10":
- // break;
-
- // case "82":
- // break;
- // default:
- // break;
- //}
-
- switch (parser.FuncNo)
- {
- case "10":
- await HandleAuthenticationAsync(parser, context.Channel);
- break;
- case "82":
- await HandleAuthenticationSuccessAsync(parser, context.Channel);
- break;
- case "05":
- await SendHeartbeatAsync(parser, context.Channel);
- break;
- case "04":
- await HandleSignRecsAsync(parser, context.Channel);
- break;
- case "08":
- await HandleStdtSchoolRecsAsync(parser, context.Channel);
- break;
- default:
- _logger.LogInformation($"未处理业务,func_no:{parser.FuncNo},seq_no{parser.SeqNo},data:{parser.Data}");
- break;
- }
- }
- }
- catch (Exception ex)
- {
- _logger.LogInformation($"{nameof(RegisterHandler)} --- {nameof(ChannelRead)} 处理消息 {parser.SeqNo} 出错\n{ex.Message}\n{ex.StackTrace}");
-
- }
-
- }
- }
-
- /// <summary>
- /// 发送到TCP客户端
- /// </summary>
- /// <param name="wrapper"></param>
- /// <param name="channel"></param>
- private async Task SendToTcpClientAsync(ProtocolWrapper wrapper, IChannel channel)
- {
-
- string protocolMsg = wrapper.GenerateProtocolString();
-
- // 发送protocolMsg到tcp客户端
- await channel
- .WriteAndFlushAsync(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(protocolMsg)))
- .ContinueWith(Action => {
- _logger.LogInformation($"{nameof(RegisterHandler)} -- {nameof(SendToTcpClientAsync)} -- 下发设备内容:\n{protocolMsg}");
- });
- }
-
- /// <summary>
- /// 认证业务
- /// </summary>
- /// <param name="parser"></param>
- /// <param name="channel"></param>
- /// <returns></returns>
- private async Task HandleAuthenticationAsync(ProtocolParser parser, IChannel channel)
- {
- ProtocolWrapper phoneAuthWrapper = new(parser.FuncNo, parser.SeqNo, "1");
- await SendToTcpClientAsync(phoneAuthWrapper, channel);
-
- await channel.EventLoop.Schedule(async () =>
- {
- ProtocolWrapper abtStatusWrapper = new("82", parser.SeqNo, DateTime.Now.ToString("yyyyMMddHHmmss"));
- await SendToTcpClientAsync(abtStatusWrapper, channel);
- }, TimeSpan.FromSeconds(3));
- }
-
- /// <summary>
- /// 认证业务成功
- /// </summary>
- /// <param name="parser"></param>
- /// <param name="channel"></param>
- /// <returns></returns>
- private async Task HandleAuthenticationSuccessAsync(ProtocolParser parser, IChannel channel)
- {
- _logger.LogInformation($"认证成功: func_no:{parser.FuncNo},seq_no{parser.SeqNo},data:{parser.Data}.");
- await Task.CompletedTask;
-
- }
-
- /// <summary>
- /// CONNECT_STATUS 网络连接状态查询[取值:05] (心跳业务)
- /// </summary>
- /// <param name="parser"></param>
- /// <param name="channel"></param>
- /// <returns></returns>
- private async Task SendHeartbeatAsync(ProtocolParser parser, IChannel channel)
- {
- ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo, "");
- await SendToTcpClientAsync(stdtSignRecsWrapper, channel);
- }
-
- /// <summary>
- /// STDT_SIGN_RECS 学生签到记录[取值:04]
- /// </summary>
- /// <param name="parser"></param>
- /// <param name="channel"></param>
- /// <returns></returns>
- private async Task HandleSignRecsAsync(ProtocolParser parser, IChannel channel)
- {
- ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
- await SendToTcpClientAsync(stdtSignRecsWrapper, channel);
-
- var deviceId = parser.Data.Substring(0, 18).TrimEnd();
- var cardId= parser.Data.Substring(18,18).TrimEnd();
- var studentId = parser.Data.Substring(36,18).TrimEnd();
- var startTime = parser.Data.Substring(54, 14).TrimEnd();
- // Push card attendance information to third-party platform
- //var url = "https://midplat.xinhualeyu.com/dev-api/user/electronicCardAttendance/receiveTbAttendanceRecord";
-
- #region IC卡转换为IMEI
- var config= await _deviceConfigApiClient.GetFirstAsync(new GeneralParam
- {
- Filters = new List<QueryFilterCondition>
- {
- new QueryFilterCondition
- {
- Key=nameof(GpsDeviceConfig.IdNumber),
- Value=cardId,
- ValueType=QueryValueTypeEnum.String,
- Operator=QueryOperatorEnum.Equal
- }
- },
- OrderBys=new List<OrderByCondition>
- {
- new OrderByCondition
- {
- IsDesc=true,
- Key=nameof(GpsDeviceConfig.LastUpdate),
- }
- }
- }, new RequestHeader { RequestId = parser.SeqNo }).ConfigureAwait(false);
-
- #endregion
-
- if (config!=null)
- {
- var url = _configService.XinHuaLeYuUrl;
- var data = new
- {
- attendanceStatus = 2, //考勤状态: 0.进 1.出 2.未知
- attendanceTime = DateTime.ParseExact(startTime, "yyyyMMddHHmmss", null).ToString("yyyy-MM-dd HH:mm:ss"),
- imei = config.Imei
- };
- var res = await _httpHelper.HttpToPostAsync(url, data);
- _logger.LogInformation($"{nameof(HandleSignRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}");
- }
- else
- {
- _logger.LogInformation("找不到IC卡转换为IMEI的对应关系");
- }
-
- }
-
- /// <summary>
- /// STDT_SCHOOL_RECS 学生进校离校记录[取值:08]
- /// </summary>
- /// <param name="parser"></param>
- /// <param name="channel"></param>
- /// <returns></returns>
- private async Task HandleStdtSchoolRecsAsync(ProtocolParser parser, IChannel channel)
- {
- _logger.LogInformation($"Received STDT_SCHOOL_RECS successfully: {parser.Data}.");
- ProtocolWrapper stdtSchoolRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
- await SendToTcpClientAsync(stdtSchoolRecsWrapper, channel);
-
- var deviceId = parser.Data.Substring(0, 18).TrimEnd();
- var cardId = parser.Data.Substring(18, 18).TrimEnd();
- var studentId = parser.Data.Substring(36, 18).TrimEnd();
- var startTime = parser.Data.Substring(54, 14).TrimEnd();
- var optType = parser.Data.Substring(68, 1).TrimEnd();
- #region IC卡转换为IMEI
- var config = await _deviceConfigApiClient.GetFirstAsync(new GeneralParam
- {
- Filters = new List<QueryFilterCondition>
- {
- new QueryFilterCondition
- {
- Key=nameof(GpsDeviceConfig.IdNumber),
- Value=cardId,
- ValueType=QueryValueTypeEnum.String,
- Operator=QueryOperatorEnum.Equal
- }
- },
- OrderBys = new List<OrderByCondition>
- {
- new OrderByCondition
- {
- IsDesc=true,
- Key=nameof(GpsDeviceConfig.LastUpdate),
- }
- }
- }, new RequestHeader { RequestId = parser.SeqNo }).ConfigureAwait(false);
-
- #endregion
- if (config != null)
- {
- //var url = "https://midplat.xinhualeyu.com/dev-api/user/electronicCardAttendance/receiveTbAttendanceRecord";
- var url = _configService.XinHuaLeYuUrl;
- var data = new
- {
- attendanceStatus = int.TryParse(optType, out int type) ? type : 0,
- attendanceTime = DateTime.ParseExact(startTime, "yyyyMMddHHmmss", null).ToString("yyyy-MM-dd HH:mm:ss"),
- imei = config.Imei
- };
- var res = await _httpHelper.HttpToPostAsync(url, data);
- _logger.LogInformation($"{nameof(HandleStdtSchoolRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}");
- }
- else
- {
- _logger.LogInformation("找不到IC卡转换为IMEI的对应关系");
- }
- }
- }
- }
|