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

744 lines
27 KiB

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