ProtocolProxyBase.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. using System.ComponentModel.DataAnnotations;
  2. using System.Reflection;
  3. using System.Runtime.InteropServices;
  4. namespace WCS.Core;
  5. public abstract class ProtocolProxyBase : IProtocolProxy
  6. {
  7. public DateTime ChangedTime;
  8. private byte[] Data = new byte[0];
  9. public DateTime Frame;
  10. private readonly string Id = Guid.NewGuid().ToString();
  11. public Dictionary<string, PlcItem> Items = new();
  12. public Type ProtocolType, ProtocolDataType;
  13. public ProtocolProxyBase(Device dev, ProtocolInfo info, Type protocolType, World world)
  14. {
  15. World = world;
  16. Frame = world.Frame;
  17. ChangedTime = world.Frame;
  18. Device = dev;
  19. Info = info;
  20. Db = info.DBInfo.Ex(world);
  21. Db.DbChanged += Db_DbChanged;
  22. ProtocolType = protocolType;
  23. var bitStart = info.Position * 8; //偏移量,按位算
  24. //this.Start = start;
  25. //PlcDB db = new PlcDB(null, 50, 100);
  26. var lst = GetType().GetInterfaces().ToList();
  27. var ps = lst.SelectMany(v => v.GetProperties()).ToArray();
  28. foreach (var p in ps)
  29. {
  30. if (p.GetIndexParameters().Length > 0) continue;
  31. if (typeof(ProtocolProxyBase).GetProperty(p.Name,
  32. BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null) continue;
  33. #region 计算偏移量
  34. var modeNum = 0;
  35. var t = p.PropertyType;
  36. if (t.IsEnum)
  37. t = t.GetEnumUnderlyingType();
  38. if (t == typeof(bool)) //bit类型,db块中无须补齐16位
  39. modeNum = 1;
  40. else if (t.IsPrimitive && Marshal.SizeOf(t) == 1) //byte char 等单字节类型,db块中无须补齐16位
  41. modeNum = 8;
  42. else //其他类型,db块中必须补齐16位
  43. modeNum = 16;
  44. var mod = bitStart % modeNum;
  45. if (mod > 0) bitStart += modeNum - mod;
  46. #endregion 计算偏移量
  47. byte arrlen = 0;
  48. byte strLen = 0;
  49. if (t.IsArray)
  50. {
  51. var attr =
  52. p.GetCustomAttributes(typeof(MaxLengthAttribute), true).FirstOrDefault() as MaxLengthAttribute;
  53. if (attr != null)
  54. arrlen = (byte)attr.Length;
  55. }
  56. else if (p.PropertyType == typeof(string))
  57. {
  58. var attr =
  59. p.GetCustomAttributes(typeof(StringLengthAttribute), true)
  60. .FirstOrDefault() as StringLengthAttribute;
  61. strLen = (byte)attr.MaximumLength;
  62. }
  63. var m = typeof(DataBlock).GetMethod("Regist");
  64. m = m.MakeGenericMethod(p.PropertyType);
  65. var item = m.Invoke(Db, new object[] { this, Id, p.Name, bitStart, arrlen, strLen }) as PlcItem;
  66. Items.Add(p.Name, item);
  67. bitStart += item.DataSizeOfBits;
  68. BytesCount += item.DataSize;
  69. }
  70. ProtocolDataType = ProtocolType.Assembly.GetTypes().Where(v => v.IsClass || v.IsValueType)
  71. .First(v => v.GetInterface(ProtocolType.Name) != null && v != GetType());
  72. }
  73. public ProtocolInfo Info { get; }
  74. public int BytesCount { get; }
  75. public Device Device { get; }
  76. public World World { get; }
  77. public DataBlock Db { get; }
  78. public string Code => Device.Code;
  79. private void Db_DbChanged(byte[] data)
  80. {
  81. var pos = Info.Position - Db.Start;
  82. var bytes = data.Skip(pos).Take(BytesCount).ToArray();
  83. if (Data.SequenceEqual(bytes))
  84. return;
  85. Frame = World.Frame;
  86. ChangedTime = World.Frame;
  87. Data = bytes;
  88. DataChanged();
  89. }
  90. protected abstract void DataChanged();
  91. #region
  92. public void AddEvent(string eventName, Delegate delgate)
  93. {
  94. throw new NotImplementedException();
  95. }
  96. public void RemoveEvent(string eventName, Delegate delgate)
  97. {
  98. throw new NotImplementedException();
  99. }
  100. public T CallReturn<T>(string methodName, params object[] args)
  101. {
  102. throw new NotImplementedException();
  103. }
  104. public void CallVoid(string methodName, params object[] args)
  105. {
  106. throw new NotImplementedException();
  107. }
  108. public T Get<T>(string propertyName)
  109. {
  110. var item = Items[propertyName] as PlcItem<T>;
  111. var res = item.Value;
  112. var channel = Ltc.GetChannel();
  113. return res;
  114. }
  115. public void Set<T>(string propertyName, T value)
  116. {
  117. var item = Items[propertyName] as PlcItem<T>;
  118. item.Value = value;
  119. var channel = Ltc.GetChannel();
  120. if (channel != null)World.OnInternalLog(channel, $"设置值:设置{Device.Code}.{ProtocolType.Name}.{propertyName} 值:{value}");
  121. Frame = World.Frame;
  122. ChangedTime = World.Frame;
  123. DataChanged();
  124. }
  125. #endregion
  126. }