终端一体化运控平台
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.
 
 
 

457 lines
16 KiB

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