PlcItem.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. using System.Collections;
  2. using System.Runtime.InteropServices;
  3. namespace WCS.Core
  4. {
  5. public delegate void ValueChangedHandler<T>(PlcItem<T> sender, T value);
  6. public delegate void ValueChangedHandler(PlcItem sender, object value);
  7. public abstract class PlcItem
  8. {
  9. protected DataBlock Db;
  10. public int Start;//按位计算 如,第2个字节,Start=8
  11. public byte ArrayLength, StringLength;
  12. public string Id;
  13. public string Name;
  14. public string IP;
  15. public ushort DB;
  16. public Type DataType { get; private set; }
  17. /// <summary>
  18. /// 数据类型所占的字节数
  19. /// </summary>
  20. public byte DataSize { get; private set; }
  21. public int DataSizeOfBits { get; private set; }
  22. public PlcItem(string id, string name, DataBlock db, Type type, int start, byte arrLen = 1, byte strLength = 0)
  23. {
  24. this.Id = id;
  25. this.Name = name;
  26. this.Db = db;
  27. this.DataType = type;
  28. //this.Db.DBChanged += Db_DBChanged;
  29. this.Start = start;
  30. this.ArrayLength = arrLen;
  31. this.StringLength = strLength;
  32. DataSize = (byte)GetTypeLen(DataType);
  33. DataSizeOfBits = _getBitLen(DataType);
  34. }
  35. private int GetTypeLen(Type type)
  36. {
  37. var bitLen = _getBitLen(type);
  38. var mod = bitLen % 8;
  39. if (mod > 0)
  40. bitLen += 8 - mod;
  41. return bitLen / 8;
  42. }
  43. private int _getBitLen(Type type)
  44. {
  45. if (type.IsArray) return _getBitLen(type.GetElementType()) * ArrayLength;
  46. if (type == typeof(bool)) return 1;
  47. if (type.IsEnum) return Marshal.SizeOf(type.GetEnumUnderlyingType()) * 8;
  48. if (type == typeof(string)) return (StringLength) * 8;
  49. if (typeof(IList).IsAssignableFrom(type)) return 0;
  50. return Marshal.SizeOf(type) * 8;
  51. }
  52. public object Value
  53. {
  54. get => getValue();
  55. set => setValue(value);
  56. }
  57. protected abstract void setValue(object value);
  58. protected abstract object getValue();
  59. private object lastValue;
  60. private bool ValueEquals(object obj1, object obj2)
  61. {
  62. if (obj1.GetType().IsArray)
  63. {
  64. var arr1 = obj1 as Array;
  65. if (obj2 is Array arr2)
  66. {
  67. return !arr1.Cast<object>().Where((t, i) => !arr1.GetValue(i).Equals(arr2.GetValue(2))).Any();
  68. }
  69. return true;
  70. }
  71. else
  72. {
  73. return obj1.Equals(obj2);
  74. }
  75. }
  76. }
  77. public class PlcItem<T> : PlcItem
  78. {
  79. public PlcItem(string id, string name, DataBlock db, int start, byte arrLen = 1, byte strLen = 0) : base(id, name, db, typeof(T), start, arrLen, strLen)
  80. {
  81. }
  82. public new T Value
  83. {
  84. get => (T)base.Value;
  85. set => base.Value = value;
  86. }
  87. protected override void setValue(object value)
  88. {
  89. var i = 0;
  90. while (true)
  91. {
  92. try
  93. {
  94. Db.Write<T>(Start, (T)value, StringLength, ArrayLength);
  95. return;
  96. }
  97. catch (Exception ex)
  98. {
  99. if (i >= 3) throw new Exception($"写入出错{ex.Message}--{Start}--{(T)value}--{StringLength}--{ArrayLength}--{Db.Entity.No}");
  100. i++;
  101. Thread.Sleep(100);
  102. }
  103. }
  104. }
  105. protected override object getValue()
  106. {
  107. return Db.Read<T>(Start, StringLength, ArrayLength);
  108. }
  109. }
  110. }