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.

287 lines
9.4 KiB

8 months ago
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Mirle.Component.MPLC.MCProtocol
  4. {
  5. /// <summary>
  6. /// Frame3E
  7. /// </summary>
  8. public class Frame3E
  9. {
  10. /// <summary>
  11. /// 建構式
  12. /// </summary>
  13. public Frame3E()
  14. {
  15. _networkNo = 0;
  16. _stationNo = 0;
  17. }
  18. /// <summary>
  19. /// 建構式
  20. /// </summary>
  21. /// <param name="networkNo">網路編號</param>
  22. /// <param name="stationNo">站點編號</param>
  23. public Frame3E(int networkNo, int stationNo)
  24. {
  25. _networkNo = (byte)networkNo;
  26. _stationNo = (byte)stationNo;
  27. }
  28. /// <summary>
  29. /// 完成碼
  30. /// </summary>
  31. private struct CompleteCode
  32. {
  33. /// <summary>
  34. /// 沒有資料
  35. /// </summary>
  36. public const int NoData = 0xF000;
  37. /// <summary>
  38. /// 有效資料
  39. /// </summary>
  40. public const int InvalidData = 0xF001;
  41. }
  42. /// <summary>
  43. ///
  44. /// </summary>
  45. private const byte _PCNo = 0xff;
  46. /// <summary>
  47. ///
  48. /// </summary>
  49. private const byte _IONo_L = 0xff; //0x03ff
  50. /// <summary>
  51. ///
  52. /// </summary>
  53. private const byte _IONo_H = 0x03; //0x03ff
  54. /// <summary>
  55. ///
  56. /// </summary>
  57. private const byte _CPUTimer_L = 0x10; //0x0010
  58. /// <summary>
  59. ///
  60. /// </summary>
  61. private const byte _CPUTimer_H = 0x00;
  62. /// <summary>
  63. ///
  64. /// </summary>
  65. private const int _receiceDataMinimumBytes = 11;
  66. /// <summary>
  67. ///
  68. /// </summary>
  69. private readonly byte _networkNo = 0x00;
  70. /// <summary>
  71. ///
  72. /// </summary>
  73. private readonly byte _stationNo = 0x00;
  74. /// <summary>
  75. ///
  76. /// </summary>
  77. public readonly int MaximumWords = 960;
  78. /// <summary>
  79. ///
  80. /// </summary>
  81. /// <param name="mainCmd"></param>
  82. /// <param name="subCmd"></param>
  83. /// <param name="address"></param>
  84. /// <param name="deviceCode"></param>
  85. /// <param name="size"></param>
  86. /// <param name="data"></param>
  87. /// <returns></returns>
  88. private byte[] CreateFrame(int mainCmd, int subCmd, int address, byte deviceCode, int size, IReadOnlyCollection<byte> data)
  89. {
  90. int dataLength = 12 + data.Count;
  91. var frame = new List<byte>()
  92. {
  93. 0x50, 0x00, //3E Frame
  94. _networkNo,
  95. _PCNo,
  96. _IONo_L, _IONo_H,
  97. _stationNo,
  98. (byte)(dataLength % 256), (byte)(dataLength / 256),
  99. _CPUTimer_L , _CPUTimer_H,
  100. (byte)mainCmd, (byte)(mainCmd >> 8),
  101. (byte)subCmd, (byte)(subCmd >> 8),
  102. (byte)address, (byte)(address >> 8),
  103. (byte)(address >> 16),
  104. deviceCode,
  105. (byte)size, (byte)(size >> 8),
  106. };
  107. frame.AddRange(data);
  108. return frame.ToArray();
  109. }
  110. /// <summary>
  111. ///
  112. /// </summary>
  113. /// <param name="device"></param>
  114. /// <param name="length"></param>
  115. /// <returns></returns>
  116. public byte[] CreateReadWordsFrame(MCDevice device, int length)
  117. {
  118. if (device == null && length < 1)
  119. {
  120. return null;
  121. }
  122. if (length > MaximumWords)
  123. {
  124. length = MaximumWords;
  125. }
  126. int mainCmd = 0x0401;
  127. int subCmd = 0x0000;
  128. int address = device.Address;
  129. byte deviceCode = device.BinaryDeviceCode;
  130. int size = length;
  131. return CreateFrame(mainCmd, subCmd, address, deviceCode, size, new List<byte>());
  132. }
  133. /// <summary>
  134. ///
  135. /// </summary>
  136. /// <param name="device"></param>
  137. /// <param name="data"></param>
  138. /// <returns></returns>
  139. public byte[] CreateWriteWordsFrame(MCDevice device, int[] data)
  140. {
  141. if (device == null && data == null)
  142. {
  143. return null;
  144. }
  145. int mainCmd = 0x1401;
  146. int subCmd = 0x0000;
  147. int address = device.Address;
  148. byte deviceCode = device.BinaryDeviceCode;
  149. int size = Math.Min(data.Length, MaximumWords);
  150. var byteData = new List<byte>();
  151. for (int i = 0; i < Math.Min(data.Length, MaximumWords); i++)
  152. {
  153. byteData.Add((byte)data[i]);
  154. byteData.Add((byte)(data[i] >> 8));
  155. }
  156. return CreateFrame(mainCmd, subCmd, address, deviceCode, size, byteData);
  157. }
  158. /// <summary>
  159. ///
  160. /// </summary>
  161. /// <param name="device"></param>
  162. /// <returns></returns>
  163. public byte[] CreateReadBitFrame(MCDevice device)
  164. {
  165. if (device == null)
  166. {
  167. return null;
  168. }
  169. int mainCmd = 0x0401;
  170. int subCmd = 0x0001;
  171. int address = device.Address;
  172. byte deviceCode = device.BinaryDeviceCode;
  173. int size = 1;
  174. return CreateFrame(mainCmd, subCmd, address, deviceCode, size, new List<byte>());
  175. }
  176. /// <summary>
  177. ///
  178. /// </summary>
  179. /// <param name="device"></param>
  180. /// <param name="isOn"></param>
  181. /// <returns></returns>
  182. public byte[] CreateWriteBitFrame(MCDevice device, bool isOn)
  183. {
  184. if (device == null)
  185. {
  186. return null;
  187. }
  188. int mainCmd = 0x1401;
  189. int subCmd = 0x0001;
  190. int address = device.Address;
  191. byte deviceCode = device.BinaryDeviceCode;
  192. int size = 1;
  193. var byteData = new List<byte>();
  194. byteData.Add((byte)(isOn ? 0x10 : 0x00));
  195. return CreateFrame(mainCmd, subCmd, address, deviceCode, size, byteData);
  196. }
  197. /// <summary>
  198. ///
  199. /// </summary>
  200. /// <param name="receiveData"></param>
  201. /// <param name="value"></param>
  202. /// <returns></returns>
  203. public int ResolveReadBitReturnFrame(byte[] receiveData, out bool value)
  204. {
  205. if (receiveData == null || receiveData.Length < _receiceDataMinimumBytes)
  206. {
  207. value = false;
  208. return CompleteCode.NoData;
  209. }
  210. ushort dataBytesLength = BitConverter.ToUInt16(receiveData, 7); //+ CompleteCode 2Bytes
  211. ushort completeCode = BitConverter.ToUInt16(receiveData, 9);
  212. if (receiveData.Length != 9 + dataBytesLength)
  213. {
  214. value = false;
  215. return CompleteCode.InvalidData;
  216. }
  217. value = receiveData[11] == 0x10;
  218. return completeCode;
  219. }
  220. /// <summary>
  221. ///
  222. /// </summary>
  223. /// <param name="receiveData"></param>
  224. /// <returns></returns>
  225. public int ResolveWriteBitReturnFrame(byte[] receiveData)
  226. {
  227. if (receiveData == null || receiveData.Length < _receiceDataMinimumBytes)
  228. {
  229. return CompleteCode.NoData;
  230. }
  231. ushort dataBytesLength = BitConverter.ToUInt16(receiveData, 7); //+ CompleteCode 2Bytes
  232. ushort completeCode = BitConverter.ToUInt16(receiveData, 9);
  233. if (receiveData.Length != 9 + dataBytesLength)
  234. {
  235. return CompleteCode.InvalidData;
  236. }
  237. return completeCode;
  238. }
  239. /// <summary>
  240. ///
  241. /// </summary>
  242. /// <param name="receiveData"></param>
  243. /// <param name="data"></param>
  244. /// <returns></returns>
  245. public int ResolveReadWordsReturnFrame(byte[] receiveData, out int[] data)
  246. {
  247. if (receiveData == null || receiveData.Length < _receiceDataMinimumBytes)
  248. {
  249. data = null;
  250. return CompleteCode.NoData;
  251. }
  252. ushort dataBytesLength = BitConverter.ToUInt16(receiveData, 7); //+ CompleteCode 2Bytes
  253. ushort completeCode = BitConverter.ToUInt16(receiveData, 9);
  254. if (receiveData.Length != 9 + dataBytesLength)
  255. {
  256. data = null;
  257. return CompleteCode.InvalidData;
  258. }
  259. data = new int[(dataBytesLength - 2) / 2];
  260. for (int i = 0; i < data.Length; i++)
  261. {
  262. data[i] = BitConverter.ToUInt16(receiveData, _receiceDataMinimumBytes + i * 2);
  263. }
  264. return completeCode;
  265. }
  266. /// <summary>
  267. ///
  268. /// </summary>
  269. /// <param name="receiveData"></param>
  270. /// <returns></returns>
  271. public int ResolveWriteWordsReturnFrame(byte[] receiveData)
  272. {
  273. if (receiveData == null || receiveData.Length < _receiceDataMinimumBytes)
  274. {
  275. return CompleteCode.NoData;
  276. }
  277. ushort dataBytesLength = BitConverter.ToUInt16(receiveData, 7); //+ CompleteCode 2Bytes
  278. ushort completeCode = BitConverter.ToUInt16(receiveData, 9);
  279. if (receiveData.Length != 9 + dataBytesLength)
  280. {
  281. return CompleteCode.InvalidData;
  282. }
  283. return completeCode;
  284. }
  285. }
  286. }