using FreeRedis; using Newtonsoft.Json; using ServiceCenter.Redis; namespace ServiceCenter.Virtual_PLC { /// /// plc数据 /// public class PlcData { private static string RedisKey = "Virtual_PLC"; private static RedisClient Redis; /// /// 数据结构缓存 /// private static List PLCDatas { get; set; } = new List(); /// /// redis 链接字符串 /// /// Redis链接字符串 public PlcData(string redisClient) { Redis = RedisHub.CreateContext(redisClient, RedisKey); } /// /// redis 链接字符串 /// /// /// public static PlcData Init(string redisClient) { return new PlcData(redisClient); } /// /// 初始化PLC数据 /// /// 一个PLC private void InitPlcData(PLCData pLCData) { if (!PLCDatas.Contains(pLCData)) { PLCDatas.Add(pLCData); } //用总长度除以数据长度,再以每断数据的起始位置、IP、DB组成Key var mun = pLCData.Length / pLCData.DataLength; int addstart = 0; for (int i = 0; i < mun; i++) { var key = $"{pLCData.IP}:{pLCData.DB}:{addstart}"; if (Redis.Exists(key)) continue; Redis.Set(key, new byte[pLCData.DataLength]); addstart = addstart + pLCData.DataLength; } } /// /// 初始化PLC数据 /// /// 多个PLC public void InitPlcData(List pLCDatas) { string key = "PLCDataList"; if (Redis.Exists(key)) { //判断值是否相等,值相等代表已经有过数据生成了,并且没有任何变化 var RedisPlcData = Redis.Get(key); if (JsonConvert.SerializeObject(pLCDatas) == RedisPlcData) { PLCDatas = pLCDatas; return; } } pLCDatas.ForEach(v => { InitPlcData(v); }); Redis.Set(key, JsonConvert.SerializeObject(pLCDatas)); } /// /// 按照DB读取 /// /// /// public static byte[] Read(PLCData pLCData) { byte[] data = new byte[pLCData.Length]; //用总长度除以数据长度,再以每断数据的起始位置、IP、DB组成Key var mun = pLCData.Length / pLCData.DataLength; int addstart = 0; for (int i = 0; i < mun; i++) { var a = Redis.Get($"{pLCData.IP}:{pLCData.DB}:{addstart}"); a.CopyTo(data, addstart); addstart = addstart + pLCData.DataLength; } return data; } /// /// 按照长度读取 /// /// /// 起始长度 /// public static byte[] Read(PLCData pLCData, int startLength) { return System.Text.Encoding.Default.GetBytes(Redis.Get($"{pLCData.IP}:{pLCData.DB}:{startLength}")); } /// /// 写入数据 /// /// /// /// public static void Write(PLCData pLCData, int startLength, byte[] value) { var data = PLCDatas.Find(v => v.IP == pLCData.IP && v.DB == pLCData.DB); int start = 0; if (data.DataLength == data.Length) //数据长度与总长度相等时计算 { start = startLength < data.DataLength ? 0 : data.DataLength - startLength + startLength; } else //不等 { int addstart = 0; var mun = data.Length / data.DataLength; var a = new List(); for (int i = 0; i < mun; i++) { a.Add(addstart); addstart = addstart + data.DataLength; } start = a.Where(v => v <= startLength).OrderByDescending(v => v).FirstOrDefault(); startLength = startLength - start; } var bytes = System.Text.Encoding.Default.GetBytes(Redis.Get($"{pLCData.IP}:{pLCData.DB}:{start}")); //获取原有数据 value.CopyTo(bytes, startLength); //将变更的数据,更新到redis字节组中 Redis.Set($"{pLCData.IP}:{pLCData.DB}:{start}", bytes); } } /// /// PLC数据结构 /// public class PLCData { /// /// IP /// public string IP { get; set; } /// /// DB /// public int DB { get; set; } /// /// 总长度 /// public int Length { get; set; } /// /// 数据长度 /// public int DataLength { get; set; } } }