PLC.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System.Collections.Concurrent;
  2. using System.Net.NetworkInformation;
  3. namespace WCS.Core;
  4. public class PLC : EntityEx<PLCInfo>
  5. {
  6. public PLC(PLCInfo ent, World world) : base(ent)
  7. {
  8. if (Configs.PLCAccessorCreater != null) Accessor = Configs.PLCAccessorCreater.Create(ent);
  9. else throw new Exception("Configs.PLCAccessorCreater未赋值");
  10. IPDetection.AddIP(Entity.IP);
  11. }
  12. public bool Ping { get => IPDetection.GetIpStatus(Entity.IP); }
  13. public IPLCAccessor Accessor { get; private set; }
  14. }
  15. public class IPDetection
  16. {
  17. /// <summary>
  18. /// 需要检测的IP组,使用线程安全的字典
  19. /// </summary>
  20. private static ConcurrentDictionary<string, bool> _ipDetection = new ConcurrentDictionary<string, bool>();
  21. /// <summary>
  22. /// 是否启动检测器
  23. /// </summary>
  24. private static bool isStart = false;
  25. /// <summary>
  26. /// 取消标记,用于停止检测任务
  27. /// </summary>
  28. private static CancellationTokenSource cancellationTokenSource;
  29. /// <summary>
  30. /// 添加IP进行检测
  31. /// </summary>
  32. /// <param name="ip"></param>
  33. public static void AddIP(string ip)
  34. {
  35. if (!_ipDetection.ContainsKey(ip))
  36. {
  37. _ipDetection[ip] = false; // 默认为不在线
  38. }
  39. if (!isStart)
  40. {
  41. isStart = true;
  42. Start();
  43. }
  44. }
  45. /// <summary>
  46. /// 获取指定IP的状态
  47. /// </summary>
  48. /// <param name="ip"></param>
  49. /// <returns></returns>
  50. public static bool GetIpStatus(string ip)
  51. {
  52. return _ipDetection.ContainsKey(ip) && _ipDetection[ip];
  53. }
  54. /// <summary>
  55. /// 启动IP检测任务
  56. /// </summary>
  57. private static void Start()
  58. {
  59. cancellationTokenSource = new CancellationTokenSource();
  60. Task.Run(async () =>
  61. {
  62. while (!cancellationTokenSource.Token.IsCancellationRequested)
  63. {
  64. await CheckIpsAsync();
  65. await Task.Delay(1000); // 等待 1 秒
  66. }
  67. }, cancellationTokenSource.Token);
  68. }
  69. /// <summary>
  70. /// 停止IP检测任务
  71. /// </summary>
  72. public static void Stop()
  73. {
  74. cancellationTokenSource?.Cancel();
  75. isStart = false;
  76. }
  77. /// <summary>
  78. /// 检测所有IP的状态
  79. /// </summary>
  80. /// <returns></returns>
  81. private static async Task CheckIpsAsync()
  82. {
  83. var tasks = new List<Task>();
  84. foreach (var ip in _ipDetection.Keys.ToList()) // 使用 ToList 防止遍历时修改字典
  85. {
  86. tasks.Add(Task.Run(async () =>
  87. {
  88. bool isOnline = await PingAsync(ip);
  89. _ipDetection[ip] = isOnline;
  90. }));
  91. }
  92. await Task.WhenAll(tasks);
  93. }
  94. /// <summary>
  95. /// pingIp
  96. /// </summary>
  97. /// <param name="ip"></param>
  98. /// <returns></returns>
  99. private static async Task<bool> PingAsync(string ip)
  100. {
  101. try
  102. {
  103. if (ip == "1") return false;
  104. Ping ping = new Ping();
  105. PingReply reply = await ping.SendPingAsync(ip, 300); // 设置超时时间为300毫秒
  106. return reply.Status == IPStatus.Success;
  107. }
  108. catch
  109. {
  110. // 如果出现异常,认为该IP不可用
  111. return false;
  112. }
  113. }
  114. }
  115. public interface IPLCAccessorCreater
  116. {
  117. IPLCAccessor Create(PLCInfo data);
  118. }
  119. public interface IPLCAccessor
  120. {
  121. void WriteBytes(ushort db, ushort address, byte[] data);
  122. byte[] ReadBytes(ushort db, ushort address, ushort length);
  123. }