ProtocolProxyBase.cs 5.6 KB

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