PlcData.cs 5.6 KB

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