终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

ModbusTcp.cs 28 KiB

1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
1年前
1年前
1年前
2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. using NModbus;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Net.Sockets;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using BPA.Helper;
  11. namespace BPASmartClient.Modbus
  12. {
  13. public class ModbusTcp
  14. {
  15. //private volatile static ModbusTcp _Instance;
  16. //public static ModbusTcp GetInstance => _Instance ?? (_Instance = new ModbusTcp());
  17. //private ModbusTcp() { }
  18. private ModbusFactory modbusFactory;
  19. private IModbusMaster master;
  20. private TcpClient tcpClient;
  21. private ManualResetEvent mre = new ManualResetEvent(false);
  22. public string IPAdress;
  23. public int Port;
  24. public Action<string> Show { get; set; }
  25. public Action<string> ShowEx { get; set; }
  26. /// <summary>
  27. /// 连接plc 原料设备成功
  28. /// </summary>
  29. public Action ConnectOk { get; set; }
  30. public Action ConnectFail { get; set; }
  31. public Action Disconnect { get; set; }
  32. public bool IsReconnect { get; set; } = false; //true=启用重连,false=禁用重连
  33. /// <summary>
  34. /// 判断是否连接成功
  35. /// </summary>
  36. public bool Connected => tcpClient == null ? false : tcpClient.Connected;
  37. /// <summary>
  38. /// ModbusTcp 连接设备
  39. /// </summary>
  40. /// <param name="ip">ip 地址</param>
  41. /// <param name="port">端口号,默认502</param>
  42. public void ModbusTcpConnect(string ip, int port = 502)
  43. {
  44. Show?.Invoke($"设备【{ip}:{port}】连接中。。。。");
  45. IPAdress = ip;
  46. Port = port;
  47. modbusFactory = new ModbusFactory();
  48. Connect();
  49. if (Connected)
  50. {
  51. master.Transport.ReadTimeout = 3000;//读取超时时间
  52. master.Transport.WriteTimeout = 3000;//写入超时时间
  53. master.Transport.Retries = 10;//重试次数
  54. ConnectOk?.Invoke();
  55. Show?.Invoke($"设备【{ip}:{port}】连接成功");
  56. }
  57. else
  58. {
  59. ConnectFail?.Invoke();
  60. }
  61. }
  62. public void Dispose()
  63. {
  64. master.Dispose();
  65. Disconnect?.Invoke();
  66. }
  67. private void Connect()
  68. {
  69. bool ErrorFlag = false;
  70. while (!Connected)
  71. {
  72. try
  73. {
  74. tcpClient = new TcpClient(IPAdress, Port);
  75. //mre.Reset();
  76. //tcpClient.BeginConnect(IPAdress, Port, (res) => { mre.Set(); }, null);
  77. //if (!mre.WaitOne(1500, false)) break;
  78. master = modbusFactory.CreateMaster(tcpClient);
  79. }
  80. catch (Exception ex)
  81. {
  82. if (!ErrorFlag)
  83. {
  84. ShowEx?.Invoke($"ModbusTcp 连接失败,IP = {IPAdress},Port = {Port}");
  85. ShowEx?.Invoke(ex.ToString());
  86. ErrorFlag = true;
  87. }
  88. if (!IsReconnect) break;
  89. Thread.Sleep(3000);
  90. }
  91. }
  92. if (ErrorFlag && IsReconnect) Show?.Invoke("ModbusTcp 重连成功!");
  93. }
  94. /// <summary>
  95. /// 获取 M 区 和 VW 区的Modbus的地址
  96. /// </summary>
  97. /// <param name="address"></param>
  98. /// <returns></returns>
  99. public int GetAddress(string address)
  100. {
  101. if (address == null) return -1;
  102. if (address.Length > 0)
  103. {
  104. address = address.Trim();
  105. if (address.ToUpper().Contains("GM") && address.Length >= 3)
  106. {
  107. var res = address.Remove(0, 2);
  108. if (res != null && res.Length > 0)
  109. {
  110. return int.Parse(res) + 4096;
  111. }
  112. }
  113. else if (address.ToUpper().Contains("M") && address.Length >= 4)
  114. {
  115. var res = address.Substring(1).Split('.');
  116. if (res != null && res.Length == 2)
  117. {
  118. if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
  119. {
  120. if (ExitAddress >= 0 && ExitAddress <= 7)
  121. {
  122. return (firstAddress * 8) + 320 + ExitAddress;
  123. }
  124. }
  125. }
  126. }
  127. else if (address.ToUpper().Contains("I") && address.Length >= 2)
  128. {
  129. var res = address.Substring(1).Split('.');
  130. if (res != null && res.Length == 2)
  131. {
  132. if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress))
  133. {
  134. if (ExitAddress >= 0 && ExitAddress <= 7)
  135. {
  136. return (firstAddress * 8) + ExitAddress;
  137. }
  138. }
  139. }
  140. }
  141. else if (address.ToUpper().Contains("GI") && address.Length >= 3)
  142. {
  143. var res = address.Remove(0, 2);
  144. if (res != null && res.Length > 0)
  145. {
  146. return int.Parse(res);
  147. }
  148. }
  149. else if (address.ToUpper().Contains("LB") && address.Length >= 3)
  150. {
  151. var res = address.Substring(2);
  152. if (res != null && res.Length > 0)
  153. {
  154. if (int.TryParse(res, out int firstAddress))
  155. {
  156. return firstAddress;
  157. }
  158. }
  159. }
  160. else if ((address.ToUpper().Contains("VW") || address.ToUpper().Contains("VD")) && address.Length >= 3)
  161. {
  162. var res = address.Substring(2);
  163. if (res != null && int.TryParse(res, out int tempAddress))
  164. {
  165. return (tempAddress / 2) + 100;
  166. }
  167. }
  168. else if (address.ToUpper().Contains("LW") && address.Length >= 3)
  169. {
  170. var res = address.Substring(2);
  171. if (res != null && int.TryParse(res, out int LwAddress))
  172. {
  173. return LwAddress;
  174. }
  175. }
  176. else if (address.ToUpper().Contains("D") && address.Length == 5)
  177. {
  178. try
  179. {
  180. //D1001
  181. string head = (Convert.ToInt32(address.Substring(1, 1))).ToString();
  182. int num = Convert.ToInt32(address.Substring(2, 3));
  183. int len = num.ToString().Length;
  184. string tail = string.Empty;
  185. switch (len)
  186. {
  187. case 1:
  188. if ((Convert.ToInt32(address.Substring(4, 1))).ToString().Length > 1)
  189. {
  190. tail = "0" + (Convert.ToInt32(address.Substring(4, 1))).ToString();
  191. }
  192. else
  193. {
  194. tail = "00" + (Convert.ToInt32(address.Substring(4, 1))).ToString();
  195. }
  196. break;
  197. case 2:
  198. if ((Convert.ToInt32(address.Substring(3, 2))).ToString().Length > 2)
  199. {
  200. tail = (Convert.ToInt32(address.Substring(3, 2))).ToString();
  201. }
  202. else
  203. {
  204. tail = "0" + (Convert.ToInt32(address.Substring(3, 2))).ToString();
  205. }
  206. break;
  207. case 3:
  208. tail = (Convert.ToInt32(address.Substring(2, 3))).ToString();
  209. break;
  210. }
  211. address = head + tail;
  212. return Convert.ToInt32(address);
  213. }
  214. catch (Exception)
  215. {
  216. //打印日志
  217. }
  218. }
  219. }
  220. return -1;
  221. }
  222. private void ExceptionHandling(Exception ex)
  223. {
  224. if (ex.InnerException is SocketException)
  225. {
  226. if (IsReconnect)
  227. {
  228. tcpClient = null;
  229. Connect();
  230. }
  231. Disconnect?.Invoke();
  232. }
  233. }
  234. public short ReadShort(string address)
  235. {
  236. var res = Read(address);
  237. if (res != null && res is short[] shorts && shorts.Length == 1)
  238. {
  239. return shorts[0];
  240. }
  241. return 0;
  242. }
  243. public object Read(string address, ushort len = 1, byte slaveAddress = 1)
  244. {
  245. if (address == null || tcpClient == null) return default(object);
  246. ushort startAddress = (ushort)GetAddress(address);
  247. CommandType commandType = CommandType.Coils;
  248. try
  249. {
  250. if (address.ToUpper().Contains("M") || address.ToUpper().Contains("GM"))
  251. {
  252. commandType = CommandType.Coils;
  253. return master.ReadCoils(slaveAddress, startAddress, len);
  254. }
  255. else if (address.ToUpper().Contains("VD"))
  256. {
  257. commandType = CommandType.HoldingRegisters;
  258. var var1 = master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  259. var var2 = master.ReadHoldingRegisters(slaveAddress, (ushort)(startAddress + 1), len);
  260. int dest = 0;
  261. dest |= (var2[0] & 0x0000ffff);
  262. dest = (dest << 16) | (var1[0] & 0x0000ffff);
  263. return dest;
  264. }
  265. else if (address.ToUpper().Contains("VW") || address.ToUpper().Contains("LW") || address.ToUpper().Contains("D"))
  266. {
  267. commandType = CommandType.HoldingRegisters;
  268. return master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  269. }
  270. else if (address.ToUpper().Contains("VD"))
  271. {
  272. commandType = CommandType.HoldingRegisters;
  273. var var1 = master.ReadHoldingRegisters(slaveAddress, startAddress, len);
  274. var var2 = master.ReadHoldingRegisters(slaveAddress, (ushort)(startAddress + 2), len);
  275. int dest = 0;
  276. dest |= (var2[0] & 0x0000ffff);
  277. dest = (dest << 16) | (var1[0] & 0x0000ffff);
  278. return dest;
  279. }
  280. else if (address.ToUpper().Contains("I"))
  281. {
  282. commandType = CommandType.Inputs;
  283. return master.ReadInputs(slaveAddress, startAddress, len);
  284. }
  285. else if (address.ToUpper().Contains("LB"))
  286. {
  287. commandType = CommandType.Coils;
  288. return master.ReadCoils(slaveAddress, startAddress, len);
  289. }
  290. }
  291. catch (Exception ex)
  292. {
  293. ShowEx?.Invoke($"读取地址:【{address}:= {startAddress}】,读取类型:【{commandType.ToString()}】出错,{ex.ToString()}");
  294. ExceptionHandling(ex);
  295. }
  296. return default(object);
  297. }
  298. /// <summary>
  299. /// 写入数据
  300. /// </summary>
  301. /// <typeparam name="T"></typeparam>
  302. /// <param name="address">写入地址</param>
  303. /// <param name="value">写入值</param>
  304. /// <param name="Retries">重试次数</param>
  305. /// <param name="slaveAddress">从站地址</param>
  306. /// <returns></returns>
  307. public bool Write<T>(string address, T value, int Retries = 1, byte slaveAddress = 1)
  308. {
  309. int count = 0;
  310. if (Retries == 1 || Retries == 0)
  311. {
  312. return TempWrite(address, value, slaveAddress);
  313. }
  314. else if (Retries > 1)
  315. {
  316. bool isok = false;
  317. while (count < Retries)
  318. {
  319. count++;
  320. TempWrite(address, value, slaveAddress);
  321. var res = Read(address);
  322. if (res != null && res.ToString() == value.ToString())
  323. {
  324. isok = true;
  325. break;
  326. }
  327. }
  328. return isok;
  329. }
  330. return false;
  331. }
  332. private bool TempWrite<T>(string address, T value, byte slaveAddress = 1)
  333. {
  334. if (address == null || tcpClient == null)
  335. {
  336. //Show?.Invoke("写入失败,地址为空或断开连接");
  337. return false;
  338. }
  339. ushort startAddress = (ushort)GetAddress(address);
  340. CommandType commandType = CommandType.Coils;
  341. try
  342. {
  343. if (address.ToUpper().Contains("M"))
  344. {
  345. commandType = CommandType.Coils;
  346. if (value is bool boolValue)
  347. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  348. else if (value is bool[] boolsValue)
  349. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  350. else return false;
  351. }
  352. if (address.ToUpper().Contains("GM") && address.Length >= 3)
  353. {
  354. commandType = CommandType.Coils;
  355. if (value is bool boolValue)
  356. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  357. else if (value is bool[] boolsValue)
  358. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  359. else return false;
  360. }
  361. else if (address.ToUpper().Contains("LB"))
  362. {
  363. commandType = CommandType.Coils;
  364. if (value is bool boolValue)
  365. master.WriteSingleCoil(slaveAddress, startAddress, boolValue);
  366. else if (value is bool[] boolsValue)
  367. master.WriteMultipleCoils(slaveAddress, startAddress, boolsValue);
  368. else return false;
  369. }
  370. else if (address.ToUpper().Contains("VD"))
  371. {
  372. commandType = CommandType.HoldingRegisters;
  373. if (value is int intValue)
  374. {
  375. var val1 = (UInt16)intValue;
  376. var val2 = Convert.ToUInt16(intValue >> 16 & 0x0000ffff);
  377. master.WriteSingleRegister(slaveAddress, startAddress, val1);
  378. master.WriteSingleRegister(slaveAddress, (ushort)(startAddress + 1), val2);
  379. }
  380. else return false;
  381. }
  382. else if (address.ToUpper().Contains("VW") || address.ToUpper().Contains("LW") || address.ToUpper().Contains("D"))
  383. {
  384. commandType = CommandType.HoldingRegisters;
  385. if (value is ushort ushortValue)
  386. master.WriteSingleRegister(slaveAddress, startAddress, ushortValue);
  387. else if (value is ushort[] ushortsValue)
  388. {
  389. int len = 100;
  390. if (ushortsValue.Length > len)
  391. {
  392. List<ushort[]> ushortLists = new List<ushort[]>();
  393. for (int i = 0; i < ushortsValue.Length / len; i++)
  394. {
  395. ushortLists.Add(ushortsValue.Skip(0).Take(len).ToArray());
  396. }
  397. int y = ushortsValue.Length % len;
  398. if (y > 0)
  399. {
  400. ushortLists.Add(ushortsValue.Skip(ushortsValue.Length - y).Take(y).ToArray());
  401. }
  402. foreach (var item in ushortLists)
  403. {
  404. master.WriteMultipleRegisters(slaveAddress, startAddress, item);
  405. startAddress += (ushort)item.Length;
  406. }
  407. }
  408. else
  409. {
  410. master.WriteMultipleRegisters(slaveAddress, startAddress, ushortsValue);
  411. }
  412. }
  413. else return false;
  414. }
  415. else if (address.ToUpper().Contains("I"))
  416. {
  417. commandType = CommandType.Inputs;
  418. }
  419. //Show?.Invoke($"成功,地址:{address},值:{value}");
  420. return true;
  421. }
  422. catch (Exception ex)
  423. {
  424. ShowEx?.Invoke($"写入地址:【{address}:= {startAddress}】,写入类型:【{commandType.ToString()}】出错,{ex.ToString()}");
  425. ExceptionHandling(ex);
  426. return false;
  427. }
  428. }
  429. #region 字符串数据读写
  430. /// <summary>
  431. /// 赋值string
  432. /// </summary>
  433. /// <param name="StartAddress"></param>
  434. /// <param name="value"></param>
  435. /// <returns></returns>
  436. public void SetString(string StartAddress, string value)
  437. {
  438. //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
  439. //然后使用下面的代码就可以获取了
  440. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  441. var bytes = Encoding.GetEncoding("gb2312")?.GetBytes(value);
  442. Write(StartAddress, bytes.ToUshorts());
  443. }
  444. /// <summary>
  445. /// 获取string
  446. /// </summary>
  447. /// <param name="StartAddress"></param>
  448. /// <param name="len"></param>
  449. /// <returns></returns>
  450. public string GetString(string StartAddress, ushort len)
  451. {
  452. var res = Read(StartAddress, len);
  453. if (res != null && res is ushort[] ushorts)
  454. {
  455. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  456. return Encoding.GetEncoding("gb2312")?.GetString(ushorts.ToBytes()).Trim(new char[] { '\0' });
  457. }
  458. return String.Empty;
  459. }
  460. #endregion
  461. #region 浮点数数据读写
  462. /// <summary>
  463. /// 赋值Real类型数据
  464. /// </summary>
  465. /// <param name="StartAddress"></param>
  466. /// <param name="value"></param>
  467. public bool SetReal(string StartAddress, float value, int Retries = 1)
  468. {
  469. var bytes = BitConverter.GetBytes(value);
  470. return Write(StartAddress, bytes.ToUshorts(), Retries);
  471. }
  472. /// <summary>
  473. /// 获取float类型数据
  474. /// </summary>
  475. /// <param name="StartAddress"></param>
  476. /// <returns></returns>
  477. public float GetReal(string StartAddress)
  478. {
  479. var res = Read(StartAddress, 2);
  480. if (res != null && res is ushort[] ushorts)
  481. {
  482. return BitConverter.ToSingle(ushorts.ToBytes(), 0);
  483. }
  484. return 0;
  485. }
  486. #endregion
  487. #region 整数数据读写
  488. /// <summary>
  489. /// 赋值Real类型数据
  490. /// </summary>
  491. /// <param name="StartAddress"></param>
  492. /// <param name="value"></param>
  493. public void SetUint(string StartAddress, uint value)
  494. {
  495. var bytes = BitConverter.GetBytes(value);
  496. Write(StartAddress, bytes.ToUshorts());
  497. }
  498. /// <summary>
  499. /// 获取float类型数据
  500. /// </summary>
  501. /// <param name="StartAddress"></param>
  502. /// <returns></returns>
  503. public uint GetUint(string StartAddress)
  504. {
  505. var res = Read(StartAddress, 2);
  506. if (res != null && res is ushort[] ushorts)
  507. {
  508. return BitConverter.ToUInt32(ushorts.ToBytes(), 0);
  509. }
  510. return 0;
  511. }
  512. #endregion
  513. #region 批量数据读取
  514. /// <summary>
  515. /// 读取多个线圈
  516. /// </summary>
  517. /// <param name="startAddress"></param>
  518. /// <param name="num"></param>
  519. /// <param name="slaveAddress"></param>
  520. /// <returns></returns>
  521. public bool[] ReadCoils(ushort startAddress, ushort num, byte slaveAddress = 1)
  522. {
  523. return master.ReadCoils(slaveAddress, startAddress, num);
  524. }
  525. /// <summary>
  526. /// 读取多个输入线圈
  527. /// </summary>
  528. /// <param name="startAddress"></param>
  529. /// <param name="num"></param>
  530. /// <param name="slaveAddress"></param>
  531. /// <returns></returns>
  532. public bool[] ReadInputs(ushort startAddress, ushort num, byte slaveAddress = 1)
  533. {
  534. return master.ReadInputs(slaveAddress, startAddress, num);
  535. }
  536. /// <summary>
  537. /// 读取多个保持寄存器
  538. /// </summary>
  539. /// <param name="startAddress"></param>
  540. /// <param name="num"></param>
  541. /// <param name="slaveAddress"></param>
  542. /// <returns></returns>
  543. public ushort[] ReadHoldingRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  544. {
  545. return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
  546. }
  547. /// <summary>
  548. /// 读取多个输入寄存器
  549. /// </summary>
  550. /// <param name="startAddress"></param>
  551. /// <param name="num"></param>
  552. /// <param name="slaveAddress"></param>
  553. /// <returns></returns>
  554. public ushort[] ReadInputRegisters(ushort startAddress, ushort num, byte slaveAddress = 1)
  555. {
  556. return master.ReadInputRegisters(slaveAddress, startAddress, num);
  557. }
  558. #endregion
  559. #region 批量数据写入
  560. /// <summary>
  561. /// 写入多个线圈
  562. /// </summary>
  563. /// <param name="startAddress"></param>
  564. /// <param name="value"></param>
  565. /// <param name="slaveAddress"></param>
  566. public void WriteMultipleCoils(ushort startAddress, bool[] value, byte slaveAddress = 1)
  567. {
  568. master.WriteMultipleCoils(slaveAddress, startAddress, value);
  569. }
  570. /// <summary>
  571. /// 写入多个寄存器
  572. /// </summary>
  573. /// <param name="startAddress"></param>
  574. /// <param name="value"></param>
  575. /// <param name="slaveAddress"></param>
  576. public void WriteMultipleRegisters(ushort startAddress, ushort[] value, byte slaveAddress = 1)
  577. {
  578. master.WriteMultipleRegisters(slaveAddress, startAddress, value);
  579. }
  580. #endregion
  581. #region 单个数据读取
  582. /// <summary>
  583. /// 读取单个线圈
  584. /// </summary>
  585. /// <param name="startAddress"></param>
  586. /// <param name="slaveAddress"></param>
  587. /// <returns></returns>
  588. public bool ReadCoils(ushort startAddress, byte slaveAddress = 1)
  589. {
  590. var result = master.ReadCoils(slaveAddress, startAddress, 1);
  591. if (result == null) return false;
  592. if (result.Length == 1) return result[0];
  593. return false;
  594. //return master.ReadCoils(slaveAddress, startAddress, 1)[0];
  595. }
  596. /// <summary>
  597. /// 读取单个输入线圈
  598. /// </summary>
  599. /// <param name="startAddress"></param>
  600. /// <param name="slaveAddress"></param>
  601. /// <returns></returns>
  602. public bool ReadInputs(ushort startAddress, byte slaveAddress = 1)
  603. {
  604. var result = master.ReadInputs(slaveAddress, startAddress, 1);
  605. if (result == null) return false;
  606. if (result.Length == 1) return result[0];
  607. return false;
  608. //return master.ReadInputs(slaveAddress, startAddress, 1)[0];
  609. }
  610. /// <summary>
  611. /// 读取单个保持寄存器
  612. /// </summary>
  613. /// <param name="startAddress"></param>
  614. /// <param name="slaveAddress"></param>
  615. /// <returns></returns>
  616. public ushort ReadHoldingRegisters(ushort startAddress, byte slaveAddress = 1)
  617. {
  618. if (tcpClient == null) return 0;
  619. ushort[] result = null;
  620. try
  621. {
  622. result = master.ReadHoldingRegisters(slaveAddress, startAddress, 1);
  623. }
  624. catch (Exception ex)
  625. {
  626. ShowEx?.Invoke(ex.ToString());
  627. tcpClient = null;
  628. Connect();
  629. }
  630. if (result == null) return 0;
  631. if (result.Length == 1) return result[0];
  632. return 0;
  633. //return master.ReadHoldingRegisters(slaveAddress, startAddress, 1)[0];
  634. }
  635. /// <summary>
  636. /// 读取单个输入寄存器
  637. /// </summary>
  638. /// <param name="startAddress"></param>
  639. /// <param name="slaveAddress"></param>
  640. /// <returns></returns>
  641. public ushort ReadInputRegisters(ushort startAddress, byte slaveAddress = 1)
  642. {
  643. var result = master.ReadInputRegisters(slaveAddress, startAddress, 1);
  644. if (result == null) return 0;
  645. if (result.Length == 1) return result[0];
  646. return 0;
  647. //return master.ReadInputRegisters(slaveAddress, startAddress, 1)[0];
  648. }
  649. #endregion
  650. #region 单个数据写入
  651. /// <summary>
  652. /// 写入单个线圈
  653. /// </summary>
  654. /// <param name="startAddress"></param>
  655. /// <param name="value"></param>
  656. /// <param name="slaveAddress"></param>
  657. public void WriteSingleCoil(ushort startAddress, bool value, byte slaveAddress = 1)
  658. {
  659. master.WriteSingleCoil(slaveAddress, startAddress, value);
  660. }
  661. /// <summary>
  662. /// 写入单个寄存器
  663. /// </summary>
  664. /// <param name="startAddress"></param>
  665. /// <param name="value"></param>
  666. /// <param name="slaveAddress"></param>
  667. public void WriteSingleRegister(ushort startAddress, ushort value, byte slaveAddress = 1)
  668. {
  669. master.WriteSingleRegister(slaveAddress, startAddress, value);
  670. }
  671. #endregion
  672. }
  673. public enum CommandType
  674. {
  675. /// <summary>
  676. /// 线圈操作
  677. /// </summary>
  678. Coils,
  679. /// <summary>
  680. /// 输入线圈操作
  681. /// </summary>
  682. Inputs,
  683. /// <summary>
  684. /// 保持寄存器操作
  685. /// </summary>
  686. HoldingRegisters,
  687. /// <summary>
  688. /// 输入寄存器操作
  689. /// </summary>
  690. InputRegisters,
  691. }
  692. }