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.

307 lines
11 KiB

8 months ago
  1. using Mirle.Component.MPLC.DataBlocks.DeviceRange.Interfaces;
  2. using System;
  3. using System.Collections;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.IO.MemoryMappedFiles;
  7. namespace Mirle.Component.MPLC.DataBlocks
  8. {
  9. /// <summary>
  10. /// SM 資料區塊 (Int32)
  11. /// </summary>
  12. public class SMDataBlockInt32 : SMDataBlock
  13. {
  14. /// <summary>
  15. /// 建構式
  16. /// </summary>
  17. /// <param name="deviceRange">設備範圍介面</param>
  18. /// <param name="sharedMemoryName">共享記憶體名稱</param>
  19. public SMDataBlockInt32(ITypeDeviceRange deviceRange, string sharedMemoryName) : base(deviceRange, sharedMemoryName) { }
  20. /// <summary>
  21. /// 起始偏移量
  22. /// </summary>
  23. private readonly int _startOffset = 4;
  24. /// <summary>
  25. /// 初始化
  26. /// </summary>
  27. protected override void Initial()
  28. {
  29. _mmfLength = DeviceRange.ByteArrayLength;
  30. #if NET5_0 || NET6_0
  31. if (OperatingSystem.IsWindows())
  32. {
  33. _mmf = MemoryMappedFile.CreateOrOpen(_mmfName, _startOffset + (_mmfLength * 2));
  34. }
  35. else
  36. {
  37. _mmf = MemoryMappedFile.CreateFromFile(_mmfName);
  38. }
  39. #elif NETFRAMEWORK
  40. _mmf = MemoryMappedFile.CreateOrOpen(_mmfName, _startOffset + (_mmfLength * 2));
  41. #else
  42. _mmf = MemoryMappedFile.CreateFromFile(_mmfName);
  43. #endif
  44. }
  45. /// <summary>
  46. /// 設置原始資料
  47. /// </summary>
  48. /// <param name="newRawData">原始資料</param>
  49. public override void SetRawData(byte[] newRawData)
  50. {
  51. try
  52. {
  53. _rwLock.EnterWriteLock();
  54. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  55. using BinaryWriter writer = new BinaryWriter(stream);
  56. stream.Seek(_startOffset, SeekOrigin.Begin);
  57. for (int i = 0; i < Math.Min(newRawData.Length, _mmfLength); i += 2)
  58. {
  59. writer.Write(newRawData[i]);
  60. writer.Write(newRawData[i + 1]);
  61. stream.Seek(2, SeekOrigin.Current);
  62. }
  63. }
  64. finally
  65. {
  66. _rwLock.ExitWriteLock();
  67. }
  68. }
  69. /// <summary>
  70. /// 取得原始資料
  71. /// </summary>
  72. /// <returns>原始資料</returns>
  73. public override byte[] GetRawData()
  74. {
  75. byte[] data = new byte[_mmfLength];
  76. try
  77. {
  78. _rwLock.EnterReadLock();
  79. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  80. using BinaryReader reader = new BinaryReader(stream);
  81. stream.Seek(_startOffset, SeekOrigin.Begin);
  82. for (int i = 0; i < _mmfLength; i += 2)
  83. {
  84. data[i] = reader.ReadByte();
  85. data[i + 1] = reader.ReadByte();
  86. stream.Seek(2, SeekOrigin.Current);
  87. }
  88. }
  89. finally
  90. {
  91. _rwLock.ExitReadLock();
  92. }
  93. return data;
  94. }
  95. /// <summary>
  96. /// 取得位元
  97. /// </summary>
  98. /// <param name="address">位置</param>
  99. /// <param name="value">是否成功取得</param>
  100. /// <returns>True/False</returns>
  101. public override bool TryGetBit(string address, out bool value)
  102. {
  103. value = false;
  104. try
  105. {
  106. _rwLock.EnterReadLock();
  107. if (DeviceRange.TryGetByteArrayOffset(address, out int offset) && DeviceRange.TryGetByteArrayBitIndex(address, out int index))
  108. {
  109. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  110. using BinaryReader reader = new BinaryReader(stream);
  111. stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
  112. ushort word = reader.ReadUInt16();
  113. BitArray bitArray = new BitArray(BitConverter.GetBytes(word));
  114. value = bitArray.Get(index);
  115. return true;
  116. }
  117. }
  118. catch (Exception ex)
  119. {
  120. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  121. }
  122. finally
  123. {
  124. _rwLock.ExitReadLock();
  125. }
  126. return false;
  127. }
  128. /// <summary>
  129. /// 設置位元
  130. /// </summary>
  131. /// <param name="address">位置</param>
  132. /// <param name="IsOn">是否開啟</param>
  133. /// <returns>True/False</returns>
  134. protected override bool SetBit(string address, bool IsOn)
  135. {
  136. try
  137. {
  138. _rwLock.EnterWriteLock();
  139. if (DeviceRange.TryGetByteArrayOffset(address, out int offset) && DeviceRange.TryGetByteArrayBitIndex(address, out int index))
  140. {
  141. int startOffset = _startOffset + offset * 2;
  142. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  143. using BinaryReader reader = new BinaryReader(stream);
  144. stream.Seek(startOffset, SeekOrigin.Begin);
  145. ushort word = reader.ReadUInt16();
  146. BitArray bitArray = new BitArray(BitConverter.GetBytes(word));
  147. bitArray.Set(index, IsOn);
  148. byte[] tmpBytes = new byte[2];
  149. bitArray.CopyTo(tmpBytes, 0);
  150. stream = _mmf.CreateViewStream();
  151. using BinaryWriter writer = new BinaryWriter(stream);
  152. stream.Seek(startOffset, SeekOrigin.Begin);
  153. writer.Write(tmpBytes[0]);
  154. writer.Write(tmpBytes[1]);
  155. return true;
  156. }
  157. }
  158. catch (Exception ex)
  159. {
  160. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  161. }
  162. finally
  163. {
  164. _rwLock.ExitWriteLock();
  165. }
  166. return false;
  167. }
  168. /// <summary>
  169. /// 取得字元
  170. /// </summary>
  171. /// <param name="address">位置</param>
  172. /// <param name="value">值</param>
  173. /// <returns>True/False</returns>
  174. public override bool TryGetWord(string address, out int value)
  175. {
  176. value = 0;
  177. try
  178. {
  179. _rwLock.EnterReadLock();
  180. if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
  181. {
  182. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  183. using BinaryReader reader = new BinaryReader(stream);
  184. stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
  185. value = reader.ReadUInt16();
  186. return true;
  187. }
  188. }
  189. catch (Exception ex)
  190. {
  191. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  192. }
  193. finally
  194. {
  195. _rwLock.ExitReadLock();
  196. }
  197. return false;
  198. }
  199. /// <summary>
  200. /// 設置字元
  201. /// </summary>
  202. /// <param name="address">位置</param>
  203. /// <param name="value">值</param>
  204. /// <returns>True/False</returns>
  205. public override bool TrySetWord(string address, int value)
  206. {
  207. try
  208. {
  209. _rwLock.EnterWriteLock();
  210. if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
  211. {
  212. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  213. using var writer = new BinaryWriter(stream);
  214. stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
  215. byte[] tmpBytes = BitConverter.GetBytes(value);
  216. writer.Write(tmpBytes[0]);
  217. writer.Write(tmpBytes[1]);
  218. return true;
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  224. }
  225. finally
  226. {
  227. _rwLock.ExitWriteLock();
  228. }
  229. return false;
  230. }
  231. /// <summary>
  232. /// 取得多個字元
  233. /// </summary>
  234. /// <param name="address">位置</param>
  235. /// <param name="data">資料及</param>
  236. /// <param name="length">長度</param>
  237. /// <returns>True/False</returns>
  238. public override bool TryGetWords(string address, out int[] data, int length)
  239. {
  240. data = new int[length];
  241. try
  242. {
  243. _rwLock.EnterReadLock();
  244. if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
  245. {
  246. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  247. using BinaryReader reader = new BinaryReader(stream);
  248. stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
  249. for (int i = 0; i < length; i++)
  250. {
  251. data[i] = reader.ReadUInt16();
  252. stream.Seek(2, SeekOrigin.Current);
  253. }
  254. return true;
  255. }
  256. }
  257. catch (Exception ex)
  258. {
  259. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  260. }
  261. finally
  262. {
  263. _rwLock.ExitReadLock();
  264. }
  265. return false;
  266. }
  267. /// <summary>
  268. /// 設置多個字元
  269. /// </summary>
  270. /// <param name="address">位置</param>
  271. /// <param name="data">資料集</param>
  272. /// <returns>True/False</returns>
  273. public override bool TrySetWords(string address, int[] data)
  274. {
  275. try
  276. {
  277. _rwLock.EnterWriteLock();
  278. if (DeviceRange.TryGetByteArrayOffset(address, out int offset))
  279. {
  280. MemoryMappedViewStream stream = _mmf.CreateViewStream();
  281. using BinaryWriter writer = new BinaryWriter(stream);
  282. stream.Seek(_startOffset + offset * 2, SeekOrigin.Begin);
  283. for (int i = 0; i < data.Length; i++)
  284. {
  285. byte[] tmpBytes = BitConverter.GetBytes(data[i]);
  286. writer.Write(tmpBytes[0]);
  287. writer.Write(tmpBytes[1]);
  288. stream.Seek(2, SeekOrigin.Current);
  289. }
  290. return true;
  291. }
  292. }
  293. catch (Exception ex)
  294. {
  295. Debug.WriteLine($"{ex.Message}-{ex.StackTrace}");
  296. }
  297. finally
  298. {
  299. _rwLock.ExitWriteLock();
  300. }
  301. return false;
  302. }
  303. }
  304. }