您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

460 行
16 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. MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接中。。。。");
  36. IPAdress = ip;
  37. Port = port;
  38. modbusFactory = new ModbusFactory();
  39. Connect();
  40. master.Transport.ReadTimeout = 2000;//读取超时时间
  41. master.Transport.WriteTimeout = 2000;//写入超时时间
  42. master.Transport.Retries = 10;//重试次数
  43. //ActionManage.GetInstance.Send("ConnectOk");
  44. //ActionManage.GetInstance.Send($"{GVL.GeneralConfig.DeviceType.ToString()}/ConnectOk");
  45. MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功");
  46. }
  47. private void Connect()
  48. {
  49. bool ErrorFlag = false;
  50. while (!Connected)
  51. {
  52. try
  53. {
  54. tcpClient = new TcpClient(IPAdress, Port);
  55. master = modbusFactory.CreateMaster(tcpClient);
  56. }
  57. catch (Exception ex)
  58. {
  59. if (!ErrorFlag)
  60. {
  61. MessageLog.GetInstance.ShowEx($"ModbusTcp 连接失败,IP = {IPAdress},Port = {Port}");
  62. MessageLog.GetInstance.ShowEx(ex.ToString());
  63. ErrorFlag = true;
  64. }
  65. Thread.Sleep(3000);
  66. }
  67. }
  68. MessageLog.GetInstance.Show("ModbusTcp 连接成功!");
  69. }
  70. public int GetBoolAddress(string address)
  71. {
  72. if (address != null && address.Length >= 4)
  73. {
  74. var res = address.Substring(1).Split('.');
  75. if (res != null && res.Length == 2)
  76. {
  77. if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
  78. {
  79. if (ExitAddress >= 0 && ExitAddress <= 7)
  80. {
  81. return (firstAddress * 8) + 320 + ExitAddress;
  82. }
  83. }
  84. }
  85. }
  86. return -1;
  87. }
  88. public int GetWordAddress(string address)
  89. {
  90. if (address != null && address.Length > 3)
  91. {
  92. var res = address.Substring(2);
  93. if (res != null && int.TryParse(res, out int tempAddress))
  94. {
  95. return (tempAddress / 2) + 100;
  96. }
  97. }
  98. return -1;
  99. }
  100. public void Readbool(ushort startAddress, ushort len, Action<bool[]> action)
  101. {
  102. object result;
  103. result = Read(startAddress, ReadType.Coils, len);
  104. if (result != null)
  105. {
  106. if (result is bool[] bools)
  107. {
  108. if (bools.Length == len)
  109. {
  110. action(bools);
  111. }
  112. }
  113. }
  114. }
  115. public object Read(ushort startAddress, ReadType readType, ushort num = 1, byte slaveAddress = 1)
  116. {
  117. object result = new object();
  118. if (tcpClient == null) return result;
  119. if (num <= 0) return result;
  120. try
  121. {
  122. switch (readType)
  123. {
  124. case ReadType.Coils:
  125. result = master.ReadCoils(slaveAddress, startAddress, num);
  126. break;
  127. case ReadType.Inputs:
  128. result = master.ReadInputs(slaveAddress, startAddress, num);
  129. break;
  130. case ReadType.HoldingRegisters:
  131. result = master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  132. break;
  133. case ReadType.InputRegisters:
  134. result = master.ReadInputRegisters(slaveAddress, startAddress, num);
  135. break;
  136. default:
  137. break;
  138. }
  139. if (result == null) return new object();
  140. if (result is bool[] bools)
  141. {
  142. if (bools.Length == 1)
  143. return bools[0];
  144. else
  145. return bools;
  146. }
  147. if (result is ushort[] ushorts)
  148. {
  149. if (ushorts.Length == 1)
  150. return ushorts[0];
  151. else
  152. return ushorts;
  153. }
  154. }
  155. catch (Exception ex)
  156. {
  157. MessageLog.GetInstance.ShowEx(ex.ToString());
  158. if (ex.InnerException is SocketException)
  159. {
  160. tcpClient = null;
  161. Connect();
  162. }
  163. }
  164. return result;
  165. }
  166. public bool Write(ushort startAddress, WriteType writeType, object InputValue, byte slaveAddress = 1)
  167. {
  168. bool result = false;
  169. if (tcpClient == null) return result;
  170. if (!(InputValue is bool || InputValue is bool[] || InputValue is ushort || InputValue is ushort[])) return result;
  171. try
  172. {
  173. switch (writeType)
  174. {
  175. case WriteType.Coils:
  176. if (InputValue is bool boolValue)
  177. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  178. if (InputValue is bool[] boolsValue)
  179. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  180. break;
  181. case WriteType.HoldingRegisters:
  182. if (InputValue is ushort ushortValue)
  183. master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
  184. if (InputValue is ushort[] ushortsValue)
  185. {
  186. int len = 100;
  187. if (ushortsValue.Length > len)
  188. {
  189. List<ushort[]> ushortLists = new List<ushort[]>();
  190. for (int i = 0; i < ushortsValue.Length / len; i++)
  191. {
  192. ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
  193. }
  194. int y = ushortsValue.Length % len;
  195. if (y > 0)
  196. {
  197. ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
  198. }
  199. foreach (var item in ushortLists)
  200. {
  201. master.WriteMultipleRegisters(slaveAddress, startAddress, item);
  202. startAddress += (ushort)item.Length;
  203. }
  204. }
  205. else
  206. {
  207. master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
  208. }
  209. }
  210. break;
  211. default:
  212. break;
  213. }
  214. }
  215. catch (Exception ex)
  216. {
  217. MessageLog.GetInstance.ShowEx(ex.ToString());
  218. if (ex.InnerException is SocketException)
  219. {
  220. tcpClient = null;
  221. Connect();
  222. }
  223. return false;
  224. }
  225. return true;
  226. }
  227. #region 批量数据读取
  228. /// <summary>
  229. /// 读取多个线圈
  230. /// </summary>
  231. /// <param name="startAddress"></param>
  232. /// <param name="num"></param>
  233. /// <param name="slaveAddress"></param>
  234. /// <returns></returns>
  235. public bool[] ReadCoils(ushort startAddress, ushort num, byte slaveAddress = 1)
  236. {
  237. return master.ReadCoils(slaveAddress, startAddress, num);
  238. }
  239. /// <summary>
  240. /// 读取多个输入线圈
  241. /// </summary>
  242. /// <param name="startAddress"></param>
  243. /// <param name="num"></param>
  244. /// <param name="slaveAddress"></param>
  245. /// <returns></returns>
  246. public bool[] ReadInputs(ushort startAddress, ushort num, byte slaveAddress = 1)
  247. {
  248. return master.ReadInputs(slaveAddress, startAddress, num);
  249. }
  250. /// <summary>
  251. /// 读取多个保持寄存器
  252. /// </summary>
  253. /// <param name="startAddress"></param>
  254. /// <param name="num"></param>
  255. /// <param name="slaveAddress"></param>
  256. /// <returns></returns>
  257. public ushort[] ReadHoldingRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  258. {
  259. return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  260. }
  261. /// <summary>
  262. /// 读取多个输入寄存器
  263. /// </summary>
  264. /// <param name="startAddress"></param>
  265. /// <param name="num"></param>
  266. /// <param name="slaveAddress"></param>
  267. /// <returns></returns>
  268. public ushort[] ReadInputRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  269. {
  270. return master.ReadInputRegisters(slaveAddress, startAddress, num);
  271. }
  272. #endregion
  273. #region 批量数据写入
  274. /// <summary>
  275. /// 写入多个线圈
  276. /// </summary>
  277. /// <param name="startAddress"></param>
  278. /// <param name="value"></param>
  279. /// <param name="slaveAddress"></param>
  280. public void WriteMultipleCoils(ushort startAddress, bool[] value, byte slaveAddress = 1)
  281. {
  282. master.WriteMultipleCoils(slaveAddress, startAddress, value);
  283. }
  284. /// <summary>
  285. /// 写入多个寄存器
  286. /// </summary>
  287. /// <param name="startAddress"></param>
  288. /// <param name="value"></param>
  289. /// <param name="slaveAddress"></param>
  290. public void WriteMultipleRegisters(ushort startAddress, ushort[] value, byte slaveAddress = 1)
  291. {
  292. master.WriteMultipleRegisters(slaveAddress, startAddress, value);
  293. }
  294. #endregion
  295. #region 单个数据读取
  296. /// <summary>
  297. /// 读取单个线圈
  298. /// </summary>
  299. /// <param name="startAddress"></param>
  300. /// <param name="slaveAddress"></param>
  301. /// <returns></returns>
  302. public bool ReadCoils(ushort startAddress, byte slaveAddress = 1)
  303. {
  304. var result = master.ReadCoils(slaveAddress, startAddress, 1);
  305. if (result == null) return false;
  306. if (result.Length == 1) return result[0];
  307. return false;
  308. //return master.ReadCoils(slaveAddress, startAddress, 1)[0];
  309. }
  310. /// <summary>
  311. /// 读取单个输入线圈
  312. /// </summary>
  313. /// <param name="startAddress"></param>
  314. /// <param name="slaveAddress"></param>
  315. /// <returns></returns>
  316. public bool ReadInputs(ushort startAddress, byte slaveAddress = 1)
  317. {
  318. var result = master.ReadInputs(slaveAddress, startAddress, 1);
  319. if (result == null) return false;
  320. if (result.Length == 1) return result[0];
  321. return false;
  322. //return master.ReadInputs(slaveAddress, startAddress, 1)[0];
  323. }
  324. /// <summary>
  325. /// 读取单个保持寄存器
  326. /// </summary>
  327. /// <param name="startAddress"></param>
  328. /// <param name="slaveAddress"></param>
  329. /// <returns></returns>
  330. public ushort ReadHoldingRegisters(ushort startAddress, byte slaveAddress = 1)
  331. {
  332. if (tcpClient == null) return 0;
  333. ushort[] result = null;
  334. try
  335. {
  336. result = master.ReadHoldingRegisters(slaveAddress, startAddress, 1);
  337. }
  338. catch (Exception ex)
  339. {
  340. MessageLog.GetInstance.Show(ex.ToString());
  341. tcpClient = null;
  342. Connect();
  343. }
  344. if (result == null) return 0;
  345. if (result.Length == 1) return result[0];
  346. return 0;
  347. //return master.ReadHoldingRegisters(slaveAddress, startAddress, 1)[0];
  348. }
  349. /// <summary>
  350. /// 读取单个输入寄存器
  351. /// </summary>
  352. /// <param name="startAddress"></param>
  353. /// <param name="slaveAddress"></param>
  354. /// <returns></returns>
  355. public ushort ReadInputRegisters(ushort startAddress, byte slaveAddress = 1)
  356. {
  357. var result = master.ReadInputRegisters(slaveAddress, startAddress, 1);
  358. if (result == null) return 0;
  359. if (result.Length == 1) return result[0];
  360. return 0;
  361. //return master.ReadInputRegisters(slaveAddress, startAddress, 1)[0];
  362. }
  363. #endregion
  364. #region 单个数据写入
  365. /// <summary>
  366. /// 写入单个线圈
  367. /// </summary>
  368. /// <param name="startAddress"></param>
  369. /// <param name="value"></param>
  370. /// <param name="slaveAddress"></param>
  371. public void WriteSingleCoil(ushort startAddress, bool value, byte slaveAddress = 1)
  372. {
  373. master.WriteSingleCoil(slaveAddress, startAddress, value);
  374. }
  375. /// <summary>
  376. /// 写入单个寄存器
  377. /// </summary>
  378. /// <param name="startAddress"></param>
  379. /// <param name="value"></param>
  380. /// <param name="slaveAddress"></param>
  381. public void WriteSingleRegister(ushort startAddress, ushort value, byte slaveAddress = 1)
  382. {
  383. master.WriteSingleRegister(slaveAddress, startAddress, value);
  384. }
  385. #endregion
  386. }
  387. public enum ReadType
  388. {
  389. /// <summary>
  390. /// 读线圈
  391. /// </summary>
  392. Coils,
  393. /// <summary>
  394. /// 读输入线圈
  395. /// </summary>
  396. Inputs,
  397. /// <summary>
  398. /// 读保持寄存器
  399. /// </summary>
  400. HoldingRegisters,
  401. /// <summary>
  402. /// 读输入寄存器
  403. /// </summary>
  404. InputRegisters,
  405. }
  406. public enum WriteType
  407. {
  408. /// <summary>
  409. /// 写线圈
  410. /// </summary>
  411. Coils,
  412. /// <summary>
  413. /// 写保持寄存器
  414. /// </summary>
  415. HoldingRegisters,
  416. }
  417. }