You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.2 KiB

8 months ago
  1. using Mirle.Component.MPLC.DataBlocks.DeviceRange.Interfaces;
  2. using System;
  3. using System.Diagnostics;
  4. using System.Globalization;
  5. namespace Mirle.Component.MPLC.DataBlocks.DeviceRange
  6. {
  7. /// <summary>
  8. /// B 設備範圍
  9. /// </summary>
  10. public class BDeviceRange : ITypeDeviceRange
  11. {
  12. /// <summary>
  13. /// 建構式
  14. /// </summary>
  15. /// <param name="startAddress">起始位置</param>
  16. /// <param name="endAddress">結束位置</param>
  17. /// <exception cref="ArgumentException"></exception>
  18. public BDeviceRange(string startAddress, string endAddress)
  19. {
  20. StartAddress = startAddress;
  21. EndAddress = endAddress;
  22. if (!startAddress.StartsWith(_type) || !endAddress.StartsWith(_type))
  23. throw new ArgumentException("Wrong Type!!");
  24. try
  25. {
  26. _startOffset = int.Parse(startAddress[1..], NumberStyles.HexNumber); //Hexadecimal
  27. _endOffset = int.Parse(endAddress[1..], NumberStyles.HexNumber); //Hexadecimal
  28. }
  29. catch (Exception ex)
  30. {
  31. Debug.WriteLine($"{ex}");
  32. throw new ArgumentException("Wrong Address!!");
  33. }
  34. if (_startOffset > _endOffset)
  35. throw new ArgumentException("Wrong Address Range!!");
  36. int length = _endOffset - _startOffset + 1;
  37. WordLength = length % 16 == 0 ? length / 16 : length / 16 + 1;
  38. }
  39. /// <summary>
  40. /// 設備類別
  41. /// </summary>
  42. private const string _type = nameof(DeviceType.B);
  43. /// <summary>
  44. /// 起始偏移量
  45. /// </summary>
  46. private readonly int _startOffset;
  47. /// <summary>
  48. /// 結束偏移量
  49. /// </summary>
  50. private readonly int _endOffset;
  51. /// <summary>
  52. /// 起始位置
  53. /// </summary>
  54. public string StartAddress { get; }
  55. /// <summary>
  56. /// 結束位置
  57. /// </summary>
  58. public string EndAddress { get; }
  59. /// <summary>
  60. /// 字元長度
  61. /// </summary>
  62. public int WordLength { get; }
  63. /// <summary>
  64. /// 位元組陣列長度
  65. /// </summary>
  66. /// <value>WordLength * 2</value>
  67. public int ByteArrayLength => WordLength * 2;
  68. /// <summary>
  69. /// 是否為同樣設備範圍
  70. /// </summary>
  71. /// <param name="address">起始位置</param>
  72. /// <returns>True/False</returns>
  73. public bool IsSameRange(string address)
  74. {
  75. return TryGetIndex(address, out _);
  76. }
  77. /// <summary>
  78. /// 是否為同樣設備類別
  79. /// </summary>
  80. /// <param name="address">位置</param>
  81. /// <returns>True/False</returns>
  82. private static bool IsSameType(string address)
  83. {
  84. return address.ToUpper().StartsWith(_type);
  85. }
  86. /// <summary>
  87. /// 取得索引
  88. /// </summary>
  89. /// <param name="address">位置</param>
  90. /// <param name="index">索引</param>
  91. /// <returns>True/False</returns>
  92. public bool TryGetIndex(string address, out int index)
  93. {
  94. if (!IsSameType(address))
  95. {
  96. index = -1;
  97. return false;
  98. }
  99. address = address[1..];
  100. address = address.Split('.')[0];
  101. index = int.Parse(address, NumberStyles.HexNumber);
  102. if (index >= _startOffset && index <= _endOffset)
  103. return true;
  104. index = -1;
  105. return false;
  106. }
  107. /// <summary>
  108. /// 取得偏移量
  109. /// </summary>
  110. /// <param name="address">位置</param>
  111. /// <param name="offset">偏移量</param>
  112. /// <returns>True/False</returns>
  113. public bool TryGetOffset(string address, out int offset)
  114. {
  115. if (TryGetIndex(address, out int index))
  116. {
  117. offset = index - _startOffset;
  118. return true;
  119. }
  120. offset = -1;
  121. return false;
  122. }
  123. /// <summary>
  124. /// 取得位元組陣列偏移量
  125. /// </summary>
  126. /// <param name="address">位置</param>
  127. /// <param name="offset">偏移量</param>
  128. /// <returns>True/False</returns>
  129. public bool TryGetByteArrayOffset(string address, out int offset)
  130. {
  131. if (TryGetIndex(address, out int index))
  132. {
  133. offset = (index - _startOffset) / 16 * 2;
  134. return true;
  135. }
  136. offset = -1;
  137. return false;
  138. }
  139. /// <summary>
  140. /// 取得位元組陣列位元索引
  141. /// </summary>
  142. /// <param name="address">位置</param>
  143. /// <param name="index">索引</param>
  144. /// <returns>True/False</returns>
  145. public bool TryGetByteArrayBitIndex(string address, out int index)
  146. {
  147. if (TryGetIndex(address, out int bitIndex))
  148. {
  149. index = (bitIndex - _startOffset) % 16;
  150. return true;
  151. }
  152. index = -1;
  153. return false;
  154. }
  155. }
  156. }