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.
 
 

410 lines
14 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Sockets;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using NModbus;
  8. using HBLConsole.Service;
  9. using System.Threading;
  10. using HBLConsole.Model;
  11. namespace HBLConsole.Communication
  12. {
  13. public class ModbusTcpHelper
  14. {
  15. private volatile static ModbusTcpHelper _Instance;
  16. public static ModbusTcpHelper GetInstance => _Instance ?? (_Instance = new ModbusTcpHelper());
  17. private ModbusTcpHelper() { }
  18. private ModbusFactory modbusFactory;
  19. private IModbusMaster master;
  20. private TcpClient tcpClient;
  21. private string IPAdress;
  22. private int Port;
  23. //public Action ConnectOk { get; set; }
  24. /// <summary>
  25. /// 判断是否连接成功
  26. /// </summary>
  27. public bool Connected => tcpClient == null ? false : tcpClient.Connected;
  28. /// <summary>
  29. /// ModbusTcp 连接设备
  30. /// </summary>
  31. /// <param name="ip">ip 地址</param>
  32. /// <param name="port">端口号,默认502</param>
  33. public void ModbusTcpConnect(string ip, int port = 502)
  34. {
  35. IPAdress = ip;
  36. Port = port;
  37. modbusFactory = new ModbusFactory();
  38. Connect();
  39. master.Transport.ReadTimeout = 2000;//读取超时时间
  40. master.Transport.WriteTimeout = 2000;//写入超时时间
  41. master.Transport.Retries = 10;//重试次数
  42. ActionManagerment.GetInstance.Send("ConnectOk");
  43. }
  44. private void Connect()
  45. {
  46. bool ErrorFlag = false;
  47. while (!Connected)
  48. {
  49. try
  50. {
  51. tcpClient = new TcpClient(IPAdress, Port);
  52. master = modbusFactory.CreateMaster(tcpClient);
  53. }
  54. catch (Exception ex)
  55. {
  56. if (!ErrorFlag)
  57. {
  58. MessageLog.GetInstance.Show($"ModbusTcp 连接失败,IP = {IPAdress},Port = {Port}");
  59. MessageLog.GetInstance.Show(ex.ToString());
  60. ErrorFlag = true;
  61. }
  62. Thread.Sleep(3000);
  63. }
  64. }
  65. MessageLog.GetInstance.Show("ModbusTcp 连接成功!");
  66. }
  67. public object Read(ushort startAddress, ReadType readType, ushort num = 1, byte slaveAddress = 1)
  68. {
  69. object result = new object();
  70. if (tcpClient == null) return result;
  71. if (num <= 0) return result;
  72. try
  73. {
  74. switch (readType)
  75. {
  76. case ReadType.Coils:
  77. result = master.ReadCoils(slaveAddress, startAddress, num);
  78. break;
  79. case ReadType.Inputs:
  80. result = master.ReadInputs(slaveAddress, startAddress, num);
  81. break;
  82. case ReadType.HoldingRegisters:
  83. result = master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  84. break;
  85. case ReadType.InputRegisters:
  86. result = master.ReadInputRegisters(slaveAddress, startAddress, num);
  87. break;
  88. default:
  89. break;
  90. }
  91. if (result == null) return new object();
  92. if (result is bool[] bools)
  93. {
  94. if (bools.Length == 1)
  95. return bools[0];
  96. else
  97. return bools;
  98. }
  99. if (result is ushort[] ushorts)
  100. {
  101. if (ushorts.Length == 1)
  102. return ushorts[0];
  103. else
  104. return ushorts;
  105. }
  106. }
  107. catch (Exception ex)
  108. {
  109. MessageLog.GetInstance.Show(ex.ToString());
  110. if (ex.InnerException is SocketException)
  111. {
  112. tcpClient = null;
  113. Connect();
  114. }
  115. }
  116. return result;
  117. }
  118. public bool Write(ushort startAddress, WriteType writeType, object InputValue, byte slaveAddress = 1)
  119. {
  120. bool result = false;
  121. if (tcpClient == null) return result;
  122. if (!(InputValue is bool || InputValue is bool[] || InputValue is ushort || InputValue is ushort[])) return result;
  123. try
  124. {
  125. switch (writeType)
  126. {
  127. case WriteType.Coils:
  128. if (InputValue is bool boolValue)
  129. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  130. if (InputValue is bool[] boolsValue)
  131. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  132. break;
  133. case WriteType.HoldingRegisters:
  134. if (InputValue is ushort ushortValue)
  135. master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
  136. if (InputValue is ushort[] ushortsValue)
  137. {
  138. int len = 100;
  139. if (ushortsValue.Length > len)
  140. {
  141. List<ushort[]> ushortLists = new List<ushort[]>();
  142. for (int i = 0; i < ushortsValue.Length / len; i++)
  143. {
  144. ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
  145. }
  146. int y = ushortsValue.Length % len;
  147. if (y > 0)
  148. {
  149. ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
  150. }
  151. foreach (var item in ushortLists)
  152. {
  153. master.WriteMultipleRegisters(slaveAddress, startAddress, item);
  154. startAddress += (ushort)item.Length;
  155. }
  156. }
  157. else
  158. {
  159. master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
  160. }
  161. }
  162. break;
  163. default:
  164. break;
  165. }
  166. }
  167. catch (Exception ex)
  168. {
  169. MessageLog.GetInstance.Show(ex.ToString());
  170. if (ex.InnerException is SocketException)
  171. {
  172. tcpClient = null;
  173. Connect();
  174. }
  175. return false;
  176. }
  177. return true;
  178. }
  179. #region 批量数据读取
  180. /// <summary>
  181. /// 读取多个线圈
  182. /// </summary>
  183. /// <param name="startAddress"></param>
  184. /// <param name="num"></param>
  185. /// <param name="slaveAddress"></param>
  186. /// <returns></returns>
  187. public bool[] ReadCoils(ushort startAddress, ushort num, byte slaveAddress = 1)
  188. {
  189. return master.ReadCoils(slaveAddress, startAddress, num);
  190. }
  191. /// <summary>
  192. /// 读取多个输入线圈
  193. /// </summary>
  194. /// <param name="startAddress"></param>
  195. /// <param name="num"></param>
  196. /// <param name="slaveAddress"></param>
  197. /// <returns></returns>
  198. public bool[] ReadInputs(ushort startAddress, ushort num, byte slaveAddress = 1)
  199. {
  200. return master.ReadInputs(slaveAddress, startAddress, num);
  201. }
  202. /// <summary>
  203. /// 读取多个保持寄存器
  204. /// </summary>
  205. /// <param name="startAddress"></param>
  206. /// <param name="num"></param>
  207. /// <param name="slaveAddress"></param>
  208. /// <returns></returns>
  209. public ushort[] ReadHoldingRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  210. {
  211. return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  212. }
  213. /// <summary>
  214. /// 读取多个输入寄存器
  215. /// </summary>
  216. /// <param name="startAddress"></param>
  217. /// <param name="num"></param>
  218. /// <param name="slaveAddress"></param>
  219. /// <returns></returns>
  220. public ushort[] ReadInputRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  221. {
  222. return master.ReadInputRegisters(slaveAddress, startAddress, num);
  223. }
  224. #endregion
  225. #region 批量数据写入
  226. /// <summary>
  227. /// 写入多个线圈
  228. /// </summary>
  229. /// <param name="startAddress"></param>
  230. /// <param name="value"></param>
  231. /// <param name="slaveAddress"></param>
  232. public void WriteMultipleCoils(ushort startAddress, bool[] value, byte slaveAddress = 1)
  233. {
  234. master.WriteMultipleCoils(slaveAddress, startAddress, value);
  235. }
  236. /// <summary>
  237. /// 写入多个寄存器
  238. /// </summary>
  239. /// <param name="startAddress"></param>
  240. /// <param name="value"></param>
  241. /// <param name="slaveAddress"></param>
  242. public void WriteMultipleRegisters(ushort startAddress, ushort[] value, byte slaveAddress = 1)
  243. {
  244. master.WriteMultipleRegisters(slaveAddress, startAddress, value);
  245. }
  246. #endregion
  247. #region 单个数据读取
  248. /// <summary>
  249. /// 读取单个线圈
  250. /// </summary>
  251. /// <param name="startAddress"></param>
  252. /// <param name="slaveAddress"></param>
  253. /// <returns></returns>
  254. public bool ReadCoils(ushort startAddress, byte slaveAddress = 1)
  255. {
  256. var result = master.ReadCoils(slaveAddress, startAddress, 1);
  257. if (result == null) return false;
  258. if (result.Length == 1) return result[0];
  259. return false;
  260. //return master.ReadCoils(slaveAddress, startAddress, 1)[0];
  261. }
  262. /// <summary>
  263. /// 读取单个输入线圈
  264. /// </summary>
  265. /// <param name="startAddress"></param>
  266. /// <param name="slaveAddress"></param>
  267. /// <returns></returns>
  268. public bool ReadInputs(ushort startAddress, byte slaveAddress = 1)
  269. {
  270. var result = master.ReadInputs(slaveAddress, startAddress, 1);
  271. if (result == null) return false;
  272. if (result.Length == 1) return result[0];
  273. return false;
  274. //return master.ReadInputs(slaveAddress, startAddress, 1)[0];
  275. }
  276. /// <summary>
  277. /// 读取单个保持寄存器
  278. /// </summary>
  279. /// <param name="startAddress"></param>
  280. /// <param name="slaveAddress"></param>
  281. /// <returns></returns>
  282. public ushort ReadHoldingRegisters(ushort startAddress, byte slaveAddress = 1)
  283. {
  284. if (tcpClient == null) return 0;
  285. ushort[] result = null;
  286. try
  287. {
  288. result = master.ReadHoldingRegisters(slaveAddress, startAddress, 1);
  289. }
  290. catch (Exception ex)
  291. {
  292. MessageLog.GetInstance.Show(ex.ToString());
  293. tcpClient = null;
  294. Connect();
  295. }
  296. if (result == null) return 0;
  297. if (result.Length == 1) return result[0];
  298. return 0;
  299. //return master.ReadHoldingRegisters(slaveAddress, startAddress, 1)[0];
  300. }
  301. /// <summary>
  302. /// 读取单个输入寄存器
  303. /// </summary>
  304. /// <param name="startAddress"></param>
  305. /// <param name="slaveAddress"></param>
  306. /// <returns></returns>
  307. public ushort ReadInputRegisters(ushort startAddress, byte slaveAddress = 1)
  308. {
  309. var result = master.ReadInputRegisters(slaveAddress, startAddress, 1);
  310. if (result == null) return 0;
  311. if (result.Length == 1) return result[0];
  312. return 0;
  313. //return master.ReadInputRegisters(slaveAddress, startAddress, 1)[0];
  314. }
  315. #endregion
  316. #region 单个数据写入
  317. /// <summary>
  318. /// 写入单个线圈
  319. /// </summary>
  320. /// <param name="startAddress"></param>
  321. /// <param name="value"></param>
  322. /// <param name="slaveAddress"></param>
  323. public void WriteSingleCoil(ushort startAddress, bool value, byte slaveAddress = 1)
  324. {
  325. master.WriteSingleCoil(slaveAddress, startAddress, value);
  326. }
  327. /// <summary>
  328. /// 写入单个寄存器
  329. /// </summary>
  330. /// <param name="startAddress"></param>
  331. /// <param name="value"></param>
  332. /// <param name="slaveAddress"></param>
  333. public void WriteSingleRegister(ushort startAddress, ushort value, byte slaveAddress = 1)
  334. {
  335. master.WriteSingleRegister(slaveAddress, startAddress, value);
  336. }
  337. #endregion
  338. }
  339. public enum ReadType
  340. {
  341. /// <summary>
  342. /// 读线圈
  343. /// </summary>
  344. Coils,
  345. /// <summary>
  346. /// 读输入线圈
  347. /// </summary>
  348. Inputs,
  349. /// <summary>
  350. /// 读保持寄存器
  351. /// </summary>
  352. HoldingRegisters,
  353. /// <summary>
  354. /// 读输入寄存器
  355. /// </summary>
  356. InputRegisters,
  357. }
  358. public enum WriteType
  359. {
  360. /// <summary>
  361. /// 写线圈
  362. /// </summary>
  363. Coils,
  364. /// <summary>
  365. /// 写保持寄存器
  366. /// </summary>
  367. HoldingRegisters,
  368. }
  369. }