ProtocolProxyBase.cs 5.1 KB

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