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; namespace NearCardAttendance.Service.TcpServer.Handler { public class RegisterHandler : ChannelHandlerAdapter { private readonly ILogger _logger; private readonly HttpHelper _httpHelper = default!; private readonly IDisposable _loggerScope = default!; private readonly ServiceConfig _configService; //private readonly TcpClientsManager _managerTcpClients; //private readonly ScheduleResendManager _managerScheduleResend; public RegisterHandler(ILogger logger,HttpHelper httpHelper, IOptions configService) { _logger = logger; _httpHelper = httpHelper; _configService = configService.Value; } public override void ChannelActive(IChannelHandlerContext context) { base.ChannelActive(context); // Pass the event to the next handler } public override async void ChannelInactive(IChannelHandlerContext context) { try { } 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 { ["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}"); } } } /// /// 发送到TCP客户端 /// /// /// 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}"); }); } /// /// 认证业务 /// /// /// /// 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)); } /// /// 认证业务成功 /// /// /// /// private async Task HandleAuthenticationSuccessAsync(ProtocolParser parser, IChannel channel) { _logger.LogInformation($"认证成功: func_no:{parser.FuncNo},seq_no{parser.SeqNo},data:{parser.Data}."); await Task.CompletedTask; } /// /// CONNECT_STATUS 网络连接状态查询[取值:05] (心跳业务) /// /// /// /// private async Task SendHeartbeatAsync(ProtocolParser parser, IChannel channel) { ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo, ""); await SendToTcpClientAsync(stdtSignRecsWrapper, channel); } /// /// STDT_SIGN_RECS 学生签到记录[取值:04] /// /// /// /// 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"; var url = _configService.XinHuaLeYuUrl; var data = new { attendanceStatus = 2, //考勤状态: 0.进 1.出 2.未知 attendanceTime = DateTime.TryParse(startTime, out DateTime time) ? time.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), imei = deviceId }; var res=await _httpHelper.HttpToPostAsync(url, data); _logger.LogInformation($"{nameof(HandleSignRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}"); } /// /// STDT_SCHOOL_RECS 学生进校离校记录[取值:08] /// /// /// /// 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(); //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.TryParse(startTime, out DateTime time) ? time.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), imei = deviceId }; var res = await _httpHelper.HttpToPostAsync(url, data); _logger.LogInformation($"{nameof(HandleStdtSchoolRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}"); } } }