PlcData.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using FreeRedis;
  2. using Newtonsoft.Json;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using WCS.Redis;
  6. namespace WCS.Virtual_PLC
  7. {
  8. /// <summary>
  9. /// plc数据
  10. /// </summary>
  11. public class PlcData
  12. {
  13. private static string RedisKey = "Virtual_PLC";
  14. private static RedisClient Redis;
  15. /// <summary>
  16. /// 数据结构缓存
  17. /// </summary>
  18. private static List<PLCData> PLCDatas { get; set; } = new List<PLCData>();
  19. /// <summary>
  20. /// redis 链接字符串
  21. /// </summary>
  22. /// <param name="redisClient">Redis链接字符串</param>
  23. public PlcData(string redisClient)
  24. {
  25. Redis = RedisHelper.CreateContext(redisClient, RedisKey);
  26. }
  27. /// <summary>
  28. /// redis 链接字符串
  29. /// </summary>
  30. /// <param name="redisClient"></param>
  31. /// <returns></returns>
  32. public static PlcData Init(string redisClient)
  33. {
  34. return new PlcData(redisClient);
  35. }
  36. /// <summary>
  37. /// 初始化PLC数据
  38. /// </summary>
  39. /// <param name="pLCData">一个PLC</param>
  40. private void InitPlcData(PLCData pLCData)
  41. {
  42. if (!PLCDatas.Contains(pLCData))
  43. {
  44. PLCDatas.Add(pLCData);
  45. }
  46. //用总长度除以数据长度,再以每断数据的起始位置、IP、DB组成Key
  47. var mun = pLCData.Length / pLCData.DataLength;
  48. int addstart = 0;
  49. for (int i = 0; i < mun; i++)
  50. {
  51. var key = $"{pLCData.IP}:{pLCData.DB}:{addstart}";
  52. if (Redis.Exists(key)) continue;
  53. Redis.Set(key, new byte[pLCData.DataLength]);
  54. addstart = addstart + pLCData.DataLength;
  55. }
  56. }
  57. /// <summary>
  58. /// 初始化PLC数据
  59. /// </summary>
  60. /// <param name="pLCDatas">多个PLC</param>
  61. public void InitPlcData(List<PLCData> pLCDatas)
  62. {
  63. string key = "PLCDataList";
  64. if (Redis.Exists(key))
  65. {
  66. //判断值是否相等,值相等代表已经有过数据生成了,并且没有任何变化
  67. var RedisPlcData = Redis.Get(key);
  68. if (JsonConvert.SerializeObject(pLCDatas) == RedisPlcData)
  69. {
  70. PLCDatas = pLCDatas;
  71. return;
  72. }
  73. }
  74. pLCDatas.ForEach(v =>
  75. {
  76. InitPlcData(v);
  77. });
  78. Redis.Set(key, JsonConvert.SerializeObject(pLCDatas));
  79. }
  80. /// <summary>
  81. /// 按照DB读取
  82. /// </summary>
  83. /// <param name="pLCData"></param>
  84. /// <returns></returns>
  85. public static byte[] Read(PLCData pLCData)
  86. {
  87. byte[] data = new byte[pLCData.Length];
  88. //用总长度除以数据长度,再以每断数据的起始位置、IP、DB组成Key
  89. var mun = pLCData.Length / pLCData.DataLength;
  90. int addstart = 0;
  91. for (int i = 0; i < mun; i++)
  92. {
  93. var a = Redis.Get<byte[]>($"{pLCData.IP}:{pLCData.DB}:{addstart}");
  94. a.CopyTo(data, addstart);
  95. addstart = addstart + pLCData.DataLength;
  96. }
  97. return data;
  98. }
  99. /// <summary>
  100. /// 按照长度读取
  101. /// </summary>
  102. /// <param name="pLCData"></param>
  103. /// <param name="startLength">起始长度</param>
  104. /// <returns></returns>
  105. public static byte[] Read(PLCData pLCData, int startLength)
  106. {
  107. return System.Text.Encoding.Default.GetBytes(Redis.Get($"{pLCData.IP}:{pLCData.DB}:{startLength}"));
  108. }
  109. /// <summary>
  110. /// 写入数据
  111. /// </summary>
  112. /// <param name="pLCData"></param>
  113. /// <param name="startLength"></param>
  114. /// <param name="value"></param>
  115. public static void Write(PLCData pLCData, int startLength, byte[] value)
  116. {
  117. var data = PLCDatas.Find(v => v.IP == pLCData.IP && v.DB == pLCData.DB);
  118. int start = 0;
  119. if (data.DataLength == data.Length) //数据长度与总长度相等时计算
  120. {
  121. start = startLength < data.DataLength ? 0 : (data.DataLength - startLength) + startLength;
  122. }
  123. else //不等
  124. {
  125. int addstart = 0;
  126. var mun = data.Length / data.DataLength;
  127. var a = new List<int>();
  128. for (int i = 0; i < mun; i++)
  129. {
  130. a.Add(addstart);
  131. addstart = addstart + data.DataLength;
  132. }
  133. start = a.Where(v => v <= startLength).OrderByDescending(v => v).FirstOrDefault();
  134. startLength = startLength - start;
  135. }
  136. var bytes = System.Text.Encoding.Default.GetBytes(Redis.Get($"{pLCData.IP}:{pLCData.DB}:{start}")); //获取原有数据
  137. value.CopyTo(bytes, startLength); //将变更的数据,更新到redis字节组中
  138. Redis.Set($"{pLCData.IP}:{pLCData.DB}:{start}", bytes);
  139. }
  140. }
  141. /// <summary>
  142. /// PLC数据结构
  143. /// </summary>
  144. public class PLCData
  145. {
  146. /// <summary>
  147. /// IP
  148. /// </summary>
  149. public string IP { get; set; }
  150. /// <summary>
  151. /// DB
  152. /// </summary>
  153. public int DB { get; set; }
  154. /// <summary>
  155. /// 总长度
  156. /// </summary>
  157. public int Length { get; set; }
  158. /// <summary>
  159. /// 数据长度
  160. /// </summary>
  161. public int DataLength { get; set; }
  162. }
  163. }