BgModbusTcpCommunicate.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. using Modbus.Data;
  2. using Modbus.Device;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using TeamAAS_VP.Models;
  13. using TeamAAS_VP;
  14. namespace TeamAAS_VP.Core
  15. {
  16. /// <summary>
  17. /// 后台Modbus TCP 通讯
  18. /// </summary>
  19. public class BgModbusTcpCommunicate
  20. {
  21. public TcpListener TcpListener { get;private set; }
  22. public ModbusSlave Slave { get; private set; }
  23. BgModbusTcp Config;
  24. public string IP { get => Config.IP; }
  25. public int Port { get => Config.Port; }
  26. public byte SlaveID { get => Config.SlaveID; }
  27. public bool IsEnabled { get => Config.IsEnabled; }
  28. public BgModbusTcpCommunicate(BgModbusTcp _Config)
  29. {
  30. Config = _Config;
  31. if (!Config.IsEnabled)
  32. {
  33. return;
  34. }
  35. if (TcpListener == null)
  36. {
  37. TcpListener = new TcpListener(IPAddress.Parse(Config.IP), Config.Port);
  38. TcpListener.Start();
  39. }
  40. Slave = ModbusTcpSlave.CreateTcp(Config.SlaveID, TcpListener);
  41. Slave.DataStore = Modbus.Data.DataStoreFactory.CreateDefaultDataStore();
  42. Slave.ModbusSlaveRequestReceived += Slave_ModbusSlaveRequestReceived;
  43. Slave.DataStore.DataStoreWrittenTo += DataStore_DataStoreWrittenTo;
  44. Slave.DataStore.DataStoreReadFrom += DataStore_DataStoreReadFrom;
  45. }
  46. public void Listen()
  47. {
  48. Slave.Listen();
  49. }
  50. private void Slave_ModbusSlaveRequestReceived(object sender, ModbusSlaveRequestEventArgs e)
  51. {
  52. try
  53. {
  54. switch (e.Message.FunctionCode)
  55. {
  56. case 2:
  57. break;
  58. case 4:
  59. break;
  60. default:
  61. break;
  62. }
  63. }
  64. catch (Exception ex)
  65. {
  66. LogHelper.WriteLogError($"后台Modbus tcp读取{e.Message.FunctionCode}", ex);
  67. }
  68. }
  69. /// <summary>
  70. /// 当通过Modbus命令读取数据存储时发生
  71. /// </summary>
  72. /// <param name="sender"></param>
  73. /// <param name="e"></param>
  74. private void DataStore_DataStoreReadFrom(object sender, Modbus.Data.DataStoreEventArgs e)
  75. {
  76. try
  77. {
  78. switch (e.ModbusDataType)
  79. {
  80. case ModbusDataType.HoldingRegister:
  81. break;
  82. case ModbusDataType.InputRegister:
  83. break;
  84. case ModbusDataType.Coil:
  85. break;
  86. case ModbusDataType.Input:
  87. break;
  88. default:
  89. break;
  90. }
  91. }
  92. catch (Exception ex)
  93. {
  94. LogHelper.WriteLogError($"后台Modbus tcp读取{e.ModbusDataType.ToString()}", ex);
  95. }
  96. }
  97. /// <summary>
  98. /// 当slave 收到 master 的命令 写入 DO 值或 AO 值到 DataStore 时触发事件。
  99. /// </summary>
  100. /// <param name="sender"></param>
  101. /// <param name="e"></param>
  102. private void DataStore_DataStoreWrittenTo(object sender, Modbus.Data.DataStoreEventArgs e)
  103. {
  104. switch (e.ModbusDataType)
  105. {
  106. case ModbusDataType.Coil: //code 5 //写入单个线圈
  107. //ModbusDataCollection<bool> discretes = slave.DataStore.CoilDiscretes; //获取线圈离散
  108. break;
  109. case ModbusDataType.HoldingRegister: //code 15
  110. //ModbusDataCollection<ushort> holdingRegisters = slave.DataStore.HoldingRegisters; //获取保存寄存器。
  111. break;
  112. }
  113. }
  114. /// <summary>
  115. /// 将接收到的ushort[]转换为float类型
  116. /// </summary>
  117. /// <param name="val"></param>
  118. /// <returns></returns>
  119. public float GetFloatFormUshortArray(ushort[] val)
  120. {
  121. if (val != null && val.Length == 2)
  122. {
  123. List<byte> result = new List<byte>();
  124. result.AddRange(BitConverter.GetBytes(val[0]));
  125. result.AddRange(BitConverter.GetBytes(val[1]));
  126. return BitConverter.ToSingle(result.ToArray(), 0);
  127. }
  128. else
  129. {
  130. return 0.0f;
  131. }
  132. }
  133. /// <summary>
  134. /// 将float类型分解成两个ushort类型
  135. /// </summary>
  136. /// <param name="value"></param>
  137. /// <returns></returns>
  138. public ushort[] GetUshortArrayFormFloat(float value)
  139. {
  140. ushort lowOrderValue = BitConverter.ToUInt16(BitConverter.GetBytes(value), 2);
  141. ushort highOrderValue = BitConverter.ToUInt16(BitConverter.GetBytes(value), 0);
  142. return new ushort[2] { lowOrderValue, highOrderValue };
  143. }
  144. /// <summary>
  145. /// 获取输入位状态
  146. /// </summary>
  147. /// <param name="index"></param>
  148. /// <returns></returns>
  149. public bool SW(int index)
  150. {
  151. try
  152. {
  153. return Slave.DataStore.CoilDiscretes[index];
  154. }
  155. catch (Exception ex)
  156. {
  157. LogHelper.WriteLogError($"获取输入位状态时出错", ex);
  158. return false;
  159. }
  160. }
  161. /// <summary>
  162. /// 获取输出位状态
  163. /// </summary>
  164. /// <param name="index"></param>
  165. /// <returns></returns>
  166. public bool Oport(int index)
  167. {
  168. try
  169. {
  170. return Slave.DataStore.InputDiscretes[index];
  171. }
  172. catch (Exception ex)
  173. {
  174. LogHelper.WriteLogError($"获取输出位状态时出错", ex);
  175. return false;
  176. }
  177. }
  178. /// <summary>
  179. /// 输出位操作
  180. /// </summary>
  181. /// <param name="index">地址</param>
  182. /// <param name="state">状态</param>
  183. /// <param name="time">脉冲时间</param>
  184. /// <param name="_async">是否异步执行</param>
  185. public void BitOperate(int index, bool state)
  186. {
  187. try
  188. {
  189. Slave.DataStore.InputDiscretes[index] = state;
  190. }
  191. catch (Exception ex)
  192. {
  193. LogHelper.WriteLogError($"输出位操作时出错", ex);
  194. }
  195. }
  196. /// <summary>
  197. /// 输出字操作
  198. /// </summary>
  199. /// <param name="index">字编号</param>
  200. /// <param name="value">输出值</param>
  201. /// <param name="time">脉冲时长</param>
  202. /// <param name="_async">是否异步</param>
  203. public void OutW(int index, ushort value)
  204. {
  205. try
  206. {
  207. Slave.DataStore.InputRegisters[index] = value;
  208. }
  209. catch (Exception ex)
  210. {
  211. LogHelper.WriteLogError($"输出字操作时出错", ex);
  212. }
  213. }
  214. /// <summary>
  215. /// 获取输出字值
  216. /// </summary>
  217. /// <param name="index"></param>
  218. /// <returns></returns>
  219. public ushort ReadOutW(int index)
  220. {
  221. try
  222. {
  223. return Slave.DataStore.InputRegisters[index];
  224. }
  225. catch (Exception ex)
  226. {
  227. LogHelper.WriteLogError($"获取输出字值时出错", ex);
  228. return 0;
  229. }
  230. }
  231. /// <summary>
  232. /// 获取输入字值
  233. /// </summary>
  234. /// <param name="index"></param>
  235. /// <returns></returns>
  236. public ushort InW(int index)
  237. {
  238. try
  239. {
  240. return Slave.DataStore.HoldingRegisters[index];
  241. }
  242. catch (Exception ex)
  243. {
  244. LogHelper.WriteLogError($"获取输入字值时出错", ex);
  245. return 0;
  246. }
  247. }
  248. /// <summary>
  249. /// 输出浮点数
  250. /// </summary>
  251. /// <param name="index">字编号</param>
  252. /// <param name="value">值</param>
  253. /// <param name="time">脉冲时长</param>
  254. /// <param name="_async">是否异步</param>
  255. public void OutReal(int index, float value)
  256. {
  257. try
  258. {
  259. ushort[] data = GetUshortArrayFormFloat(value);
  260. Slave.DataStore.InputRegisters[index] = data[0];
  261. Slave.DataStore.InputRegisters[index + 1] = data[1];
  262. }
  263. catch (Exception ex)
  264. {
  265. LogHelper.WriteLogError($"输出浮点数时出错", ex);
  266. }
  267. }
  268. /// <summary>
  269. /// 获取输出浮点数
  270. /// </summary>
  271. /// <param name="index"></param>
  272. /// <returns></returns>
  273. public float ReadOutReal(int index)
  274. {
  275. try
  276. {
  277. return GetFloatFormUshortArray(new ushort[] { Slave.DataStore.InputRegisters[index], Slave.DataStore.InputRegisters[index + 1] });
  278. }
  279. catch (Exception ex)
  280. {
  281. LogHelper.WriteLogError($"获取输出浮点数时出错", ex);
  282. return 0.0f;
  283. }
  284. }
  285. /// <summary>
  286. /// 获取输入浮点数
  287. /// </summary>
  288. /// <param name="index"></param>
  289. /// <returns></returns>
  290. public float InReal(int index)
  291. {
  292. try
  293. {
  294. return GetFloatFormUshortArray(new ushort[] { Slave.DataStore.HoldingRegisters[index + 1], Slave.DataStore.HoldingRegisters[index + 0] });
  295. }
  296. catch (Exception ex)
  297. {
  298. LogHelper.WriteLogError($"获取输入浮点数时出错", ex);
  299. return 0.0f;
  300. }
  301. }
  302. }
  303. }