您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

273 行
12KB

  1. using DotNetty.Buffers;
  2. using DotNetty.Transport.Channels;
  3. using Microsoft.Extensions.Logging;
  4. using NearCardAttendance.Common.helper;
  5. using NearCardAttendance.Service.TcpServer.Mapper;
  6. using NearCardAttendance.Service.TcpServer.Protocol;
  7. using Newtonsoft.Json;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Channels;
  13. using System.Threading.Tasks;
  14. namespace NearCardAttendance.Service.TcpServer.Handler
  15. {
  16. public class RegisterHandler : ChannelHandlerAdapter
  17. {
  18. private readonly ILogger<RegisterHandler> _logger;
  19. private readonly HttpHelper _httpHelper = default!;
  20. private readonly IDisposable _loggerScope = default!;
  21. private readonly TcpClientsManager _managerTcpClients;
  22. private readonly ScheduleResendManager _managerScheduleResend;
  23. public RegisterHandler(ILogger<RegisterHandler> logger,HttpHelper httpHelper)
  24. {
  25. _logger = logger;
  26. _httpHelper = httpHelper;
  27. }
  28. public override void ChannelActive(IChannelHandlerContext context)
  29. {
  30. base.ChannelActive(context); // Pass the event to the next handler
  31. }
  32. public override async void ChannelInactive(IChannelHandlerContext context)
  33. {
  34. try
  35. {
  36. }
  37. catch (Exception ex)
  38. {
  39. _logger.LogInformation($"{nameof(RegisterHandler)} --- {nameof(ChannelInactive)} 出错\n{ex.Message}\n{ex.StackTrace}");
  40. }
  41. }
  42. public override void HandlerRemoved(IChannelHandlerContext context)
  43. {
  44. base.HandlerRemoved(context);
  45. }
  46. public override async void ChannelRead(IChannelHandlerContext context, object message)
  47. {
  48. if (message is ProtocolParser parser)
  49. {
  50. try
  51. {
  52. using (_logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = parser.SeqNo }))
  53. {
  54. //认证
  55. //if (parser.FuncNo.Equals("10"))
  56. //{
  57. // #region 认证业务
  58. // // PHONE_AUTHEN
  59. // ProtocolWrapper phoneAuthWrapper = new(parser.FuncNo, parser.SeqNo, "1");
  60. // await SendToTcpClientAsync(phoneAuthWrapper, context.Channel);
  61. // // ABT_STATUS 延时3秒 给终端同步时间
  62. // await context.Channel.EventLoop.Schedule(async () =>
  63. // {
  64. // ProtocolWrapper abtStatusWrapper = new("82", parser.SeqNo, DateTime.Now.ToString("yyyyMMddHHmmss"));
  65. // await SendToTcpClientAsync(abtStatusWrapper, context.Channel);
  66. // },TimeSpan.FromSeconds(3));
  67. // #endregion
  68. //}
  69. //else if (parser.FuncNo.Equals("82"))
  70. //{
  71. // // 认证成功
  72. // _logger.LogInformation($"认证成功{parser.Data}.");
  73. //}
  74. //// 心跳
  75. //else if (parser.FuncNo.Equals("05"))
  76. //{
  77. // ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo,"");
  78. // await SendToTcpClientAsync(stdtSignRecsWrapper, context.Channel);
  79. //} // STDT_SIGN_RECS
  80. //else if (parser.FuncNo.Equals("04"))
  81. //{
  82. // // 回应设备
  83. // ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo,"1");
  84. // await SendToTcpClientAsync(stdtSignRecsWrapper, context.Channel);
  85. // // 刷卡考勤信息,需要推送给第三方平台
  86. // //var url = "";
  87. // //await _httpHelper.HttpToPostAsync(url, new object());
  88. //}
  89. //// STDT_SCHOOL_RECS
  90. //else if (parser.FuncNo.Equals("08"))
  91. //{
  92. // _logger.LogInformation($"接受STDT_SCHOOL_RECS 08 成功{parser.Data}.");
  93. // ProtocolWrapper stdtSchoolRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
  94. // await SendToTcpClientAsync(stdtSchoolRecsWrapper, context.Channel);
  95. //}
  96. //switch (parser.FuncNo)
  97. //{
  98. // case "10":
  99. // break;
  100. // case "82":
  101. // break;
  102. // default:
  103. // break;
  104. //}
  105. switch (parser.FuncNo)
  106. {
  107. case "10":
  108. await HandleAuthenticationAsync(parser, context.Channel);
  109. break;
  110. case "82":
  111. await HandleAuthenticationSuccessAsync(parser, context.Channel);
  112. break;
  113. case "05":
  114. await SendHeartbeatAsync(parser, context.Channel);
  115. break;
  116. case "04":
  117. await HandleSignRecsAsync(parser, context.Channel);
  118. break;
  119. case "08":
  120. await HandleStdtSchoolRecsAsync(parser, context.Channel);
  121. break;
  122. default:
  123. _logger.LogInformation($"未处理业务,func_no:{parser.FuncNo},seq_no{parser.SeqNo},data:{parser.Data}");
  124. break;
  125. }
  126. }
  127. }
  128. catch (Exception ex)
  129. {
  130. _logger.LogInformation($"{nameof(RegisterHandler)} --- {nameof(ChannelRead)} 处理消息 {parser.SeqNo} 出错\n{ex.Message}\n{ex.StackTrace}");
  131. }
  132. }
  133. }
  134. /// <summary>
  135. /// 发送到TCP客户端
  136. /// </summary>
  137. /// <param name="wrapper"></param>
  138. /// <param name="channel"></param>
  139. private async Task SendToTcpClientAsync(ProtocolWrapper wrapper, IChannel channel)
  140. {
  141. string protocolMsg = wrapper.GenerateProtocolString();
  142. // 发送protocolMsg到tcp客户端
  143. await channel
  144. .WriteAndFlushAsync(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(protocolMsg)))
  145. .ContinueWith(Action => {
  146. _logger.LogInformation($"{nameof(RegisterHandler)} -- {nameof(SendToTcpClientAsync)} -- 下发设备内容:\n{protocolMsg}");
  147. });
  148. }
  149. /// <summary>
  150. /// 认证业务
  151. /// </summary>
  152. /// <param name="parser"></param>
  153. /// <param name="channel"></param>
  154. /// <returns></returns>
  155. private async Task HandleAuthenticationAsync(ProtocolParser parser, IChannel channel)
  156. {
  157. ProtocolWrapper phoneAuthWrapper = new(parser.FuncNo, parser.SeqNo, "1");
  158. await SendToTcpClientAsync(phoneAuthWrapper, channel);
  159. await channel.EventLoop.Schedule(async () =>
  160. {
  161. ProtocolWrapper abtStatusWrapper = new("82", parser.SeqNo, DateTime.Now.ToString("yyyyMMddHHmmss"));
  162. await SendToTcpClientAsync(abtStatusWrapper, channel);
  163. }, TimeSpan.FromSeconds(3));
  164. }
  165. /// <summary>
  166. /// 认证业务成功
  167. /// </summary>
  168. /// <param name="parser"></param>
  169. /// <param name="channel"></param>
  170. /// <returns></returns>
  171. private async Task HandleAuthenticationSuccessAsync(ProtocolParser parser, IChannel channel)
  172. {
  173. _logger.LogInformation($"认证成功: func_no:{parser.FuncNo},seq_no{parser.SeqNo},data:{parser.Data}.");
  174. await Task.CompletedTask;
  175. }
  176. /// <summary>
  177. /// CONNECT_STATUS 网络连接状态查询[取值:05] (心跳业务)
  178. /// </summary>
  179. /// <param name="parser"></param>
  180. /// <param name="channel"></param>
  181. /// <returns></returns>
  182. private async Task SendHeartbeatAsync(ProtocolParser parser, IChannel channel)
  183. {
  184. ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo, "");
  185. await SendToTcpClientAsync(stdtSignRecsWrapper, channel);
  186. }
  187. /// <summary>
  188. /// STDT_SIGN_RECS 学生签到记录[取值:04]
  189. /// </summary>
  190. /// <param name="parser"></param>
  191. /// <param name="channel"></param>
  192. /// <returns></returns>
  193. private async Task HandleSignRecsAsync(ProtocolParser parser, IChannel channel)
  194. {
  195. ProtocolWrapper stdtSignRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
  196. await SendToTcpClientAsync(stdtSignRecsWrapper, channel);
  197. var deviceId = parser.Data.Substring(0, 18).TrimEnd();
  198. var cardId= parser.Data.Substring(18,18).TrimEnd();
  199. var studentId = parser.Data.Substring(36,18).TrimEnd();
  200. var startTime = parser.Data.Substring(54, 14).TrimEnd();
  201. // Push card attendance information to third-party platform
  202. var url = "https://midplat.xinhualeyu.com/dev-api/user/electronicCardAttendance/receiveTbAttendanceRecord";
  203. var data = new
  204. {
  205. attendanceStatus = 2, //考勤状态: 0.进 1.出 2.未知
  206. attendanceTime = DateTime.TryParse(startTime, out DateTime time) ? time.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  207. imei = deviceId
  208. };
  209. var res=await _httpHelper.HttpToPostAsync(url, data);
  210. _logger.LogInformation($"{nameof(HandleSignRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}");
  211. }
  212. /// <summary>
  213. /// STDT_SCHOOL_RECS 学生进校离校记录[取值:08]
  214. /// </summary>
  215. /// <param name="parser"></param>
  216. /// <param name="channel"></param>
  217. /// <returns></returns>
  218. private async Task HandleStdtSchoolRecsAsync(ProtocolParser parser, IChannel channel)
  219. {
  220. _logger.LogInformation($"Received STDT_SCHOOL_RECS successfully: {parser.Data}.");
  221. ProtocolWrapper stdtSchoolRecsWrapper = new(parser.FuncNo, parser.SeqNo, "1");
  222. await SendToTcpClientAsync(stdtSchoolRecsWrapper, channel);
  223. var deviceId = parser.Data.Substring(0, 18).TrimEnd();
  224. var cardId = parser.Data.Substring(18, 18).TrimEnd();
  225. var studentId = parser.Data.Substring(36, 18).TrimEnd();
  226. var startTime = parser.Data.Substring(54, 14).TrimEnd();
  227. var optType = parser.Data.Substring(68, 1).TrimEnd();
  228. var url = "https://midplat.xinhualeyu.com/dev-api/user/electronicCardAttendance/receiveTbAttendanceRecord";
  229. var data = new
  230. {
  231. attendanceStatus = int.TryParse(optType,out int type) ? type : 0,
  232. attendanceTime = DateTime.TryParse(startTime, out DateTime time) ? time.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  233. imei = deviceId
  234. };
  235. var res = await _httpHelper.HttpToPostAsync(url, data);
  236. _logger.LogInformation($"{nameof(HandleStdtSchoolRecsAsync)} 推送 {JsonConvert.SerializeObject(data)} 结果,{res}");
  237. }
  238. }
  239. }