PlcItem.cs 3.3 KB

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