Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

145 řádky
5.5 KiB

  1. using Microsoft.Extensions.Logging;
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using JT808.DotNetty.Abstractions;
  7. using JT808.DotNetty.Core.Metadata;
  8. using DotNetty.Transport.Channels;
  9. namespace JT808.DotNetty.Core
  10. {
  11. /// <summary>
  12. /// JT808 udp会话管理
  13. /// 估计要轮询下
  14. /// </summary>
  15. public class JT808UdpSessionManager
  16. {
  17. private readonly ILogger<JT808UdpSessionManager> logger;
  18. private readonly IJT808SessionPublishing jT808SessionPublishing;
  19. public JT808UdpSessionManager(
  20. IJT808SessionPublishing jT808SessionPublishing,
  21. ILoggerFactory loggerFactory)
  22. {
  23. this.jT808SessionPublishing = jT808SessionPublishing;
  24. logger = loggerFactory.CreateLogger<JT808UdpSessionManager>();
  25. }
  26. private ConcurrentDictionary<string, JT808UdpSession> SessionIdDict = new ConcurrentDictionary<string, JT808UdpSession>(StringComparer.OrdinalIgnoreCase);
  27. public int SessionCount
  28. {
  29. get
  30. {
  31. return SessionIdDict.Count;
  32. }
  33. }
  34. public JT808UdpSession GetSession(string terminalPhoneNo)
  35. {
  36. if (string.IsNullOrEmpty(terminalPhoneNo))
  37. return default;
  38. if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT808UdpSession targetSession))
  39. {
  40. return targetSession;
  41. }
  42. else
  43. {
  44. return default;
  45. }
  46. }
  47. public void TryAdd(JT808UdpSession appSession)
  48. {
  49. //1.先判断是否在缓存里面
  50. if(SessionIdDict.TryGetValue(appSession.TerminalPhoneNo,out JT808UdpSession jT808UdpSession))
  51. {
  52. //处理缓存
  53. //判断设备的终结点是否相同
  54. if (jT808UdpSession.Sender.Equals(appSession.Sender))
  55. {
  56. //相同 更新最后上线时间
  57. //每次使用最新的通道
  58. //将设备第一次上线时间赋值给当前上线的时间
  59. appSession.StartTime = jT808UdpSession.StartTime;
  60. SessionIdDict.TryUpdate(appSession.TerminalPhoneNo, appSession, appSession);
  61. }
  62. else
  63. {
  64. //不同 算成新设备上来并且推送通知
  65. SessionIdDict.TryUpdate(appSession.TerminalPhoneNo, appSession, appSession);
  66. jT808SessionPublishing.PublishAsync(JT808Constants.SessionOnline, appSession.TerminalPhoneNo);
  67. }
  68. }
  69. else
  70. {
  71. //添加缓存
  72. if (SessionIdDict.TryAdd(appSession.TerminalPhoneNo, appSession))
  73. {
  74. //使用场景:
  75. //部标的超长待机设备,不会像正常的设备一样一直连着,可能10几分钟连上了,然后发完就关闭连接,
  76. //这时候想下发数据需要知道设备什么时候上线,在这边做通知最好不过了。
  77. //有设备关联上来可以进行通知 例如:使用Redis发布订阅
  78. jT808SessionPublishing.PublishAsync(JT808Constants.SessionOnline, appSession.TerminalPhoneNo);
  79. }
  80. }
  81. }
  82. public void Heartbeat(string terminalPhoneNo)
  83. {
  84. if (string.IsNullOrEmpty(terminalPhoneNo)) return;
  85. if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT808UdpSession oldjT808Session))
  86. {
  87. oldjT808Session.LastActiveTime = DateTime.Now;
  88. SessionIdDict.TryUpdate(terminalPhoneNo, oldjT808Session, oldjT808Session);
  89. }
  90. }
  91. public JT808UdpSession RemoveSession(string terminalPhoneNo)
  92. {
  93. //设备离线可以进行通知
  94. //使用Redis 发布订阅
  95. if (string.IsNullOrEmpty(terminalPhoneNo)) return default;
  96. if (!SessionIdDict.TryGetValue(terminalPhoneNo, out JT808UdpSession jT808Session))
  97. {
  98. return default;
  99. }
  100. if (SessionIdDict.TryRemove(terminalPhoneNo, out JT808UdpSession jT808SessionRemove))
  101. {
  102. logger.LogInformation($">>>{terminalPhoneNo} Session Remove.");
  103. jT808SessionPublishing.PublishAsync(JT808Constants.SessionOffline,terminalPhoneNo);
  104. return jT808SessionRemove;
  105. }
  106. else
  107. {
  108. return default;
  109. }
  110. }
  111. public void RemoveSessionByChannel(IChannel channel)
  112. {
  113. //设备离线可以进行通知
  114. //使用Redis 发布订阅
  115. var terminalPhoneNos = SessionIdDict.Where(w => w.Value.Channel.Id == channel.Id).Select(s => s.Key).ToList();
  116. if (terminalPhoneNos.Count > 0)
  117. {
  118. foreach (var key in terminalPhoneNos)
  119. {
  120. SessionIdDict.TryRemove(key, out JT808UdpSession jT808SessionRemove);
  121. }
  122. string nos = string.Join(",", terminalPhoneNos);
  123. logger.LogInformation($">>>{nos} Channel Remove.");
  124. jT808SessionPublishing.PublishAsync(JT808Constants.SessionOffline, nos);
  125. }
  126. }
  127. public IEnumerable<JT808UdpSession> GetAll()
  128. {
  129. return SessionIdDict.Select(s => s.Value).ToList();
  130. }
  131. }
  132. }