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; }
}
}