S7PlcCommunicate.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. using DefaultEdit.Core;
  2. using DefaultEdit.Log4xml;
  3. using Sharp7;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using Prism.Mvvm;
  11. using TouchSocket.Sockets;
  12. using System.Xml;
  13. using NextTreatMesDemo.Utils;
  14. using System.Data;
  15. namespace DefaultEdit.Communication
  16. {
  17. public class S7PlcCommunicate : BindableBase
  18. {
  19. private S7Client client = new S7Client();
  20. private bool _IsConnected=false;
  21. private string IP;
  22. public S7Client Client { get => client; set => client = value; }
  23. public bool IsConnected { get => _IsConnected; set { SetProperty(ref _IsConnected, value); } }
  24. public event Action<string> ConnectedEvent;
  25. public event Action<string> DisconnectedEvent;
  26. public event Action<string> ReceivedEvent;
  27. public event Action<string> SendEvent;
  28. public S7PlcCommunicate(string ip)
  29. {
  30. IP = ip;
  31. }
  32. public async Task OpenPlc()
  33. {
  34. var res = Client.ConnectTo(IP, 0, 1);//连接PLC的IP地址
  35. if ( res == 0 )
  36. {
  37. ConnectedEvent += S7PlcCommunicate_ConnectedEvent;
  38. DisconnectedEvent += S7PlcCommunicate_DisconnectedEvent;
  39. ReceivedEvent += S7PlcCommunicate_ReceivedEvent;
  40. IsConnected = true;
  41. LogHelper.Info($"Plc {IP}:连接成功");
  42. }
  43. else
  44. {
  45. IsConnected = false;
  46. LogHelper.Info($"Plc{IP}:连接失败");
  47. }
  48. }
  49. public async Task ReconnectedPlc()
  50. {
  51. while ( !Client.Connected )
  52. {
  53. try
  54. {
  55. var res = Client.ConnectTo(IP, 0, 1);//连接PLC的IP地址
  56. if ( res == 0 )
  57. {
  58. LogHelper.Info($"Plc {IP}:重连成功");
  59. break;
  60. }
  61. else
  62. {
  63. LogHelper.Info($"Plc {IP}:重连失败");
  64. }
  65. }
  66. catch ( Exception ex )
  67. {
  68. LogHelper.Error("重连plc出错" + ex.Message);
  69. }
  70. Thread.Sleep(200);
  71. }
  72. IsConnected = true;
  73. }
  74. public void StopPlc()
  75. {
  76. Client.Disconnect();
  77. }
  78. private void S7PlcCommunicate_ReceivedEvent(string arg2)
  79. {
  80. }
  81. private void S7PlcCommunicate_DisconnectedEvent(string arg2)
  82. {
  83. IsConnected = false;
  84. ReconnectedPlc();
  85. }
  86. private void S7PlcCommunicate_ConnectedEvent(string arg2)
  87. {
  88. LogHelper.Info("PLC已连接");
  89. }
  90. public bool ReadBool(int ReadONDBNumber, int ReadStart,int bitStart)
  91. {
  92. try
  93. {
  94. if ( client.Connected )
  95. {
  96. byte[]buffs=new byte[1];
  97. Client.DBRead(ReadONDBNumber, ReadStart, 1, buffs);
  98. return buffs.GetBitAt(0, bitStart);
  99. }
  100. }
  101. catch ( Exception e )
  102. {
  103. LogHelper.Error("plc读取bool异常" + e.Message);
  104. throw new TimeoutException‌("PLC读取异常");
  105. }
  106. throw new InvalidOperationException‌("PLC未连接");
  107. }
  108. public byte[] ReadByte(int ReadONDBNumber, int ReadStart, int byteSize)
  109. {
  110. try
  111. {
  112. if ( client.Connected )
  113. {
  114. byte[]buffs=new byte[byteSize];
  115. Client.DBRead(ReadONDBNumber, ReadStart, byteSize, buffs);
  116. return buffs;
  117. }
  118. }
  119. catch ( Exception e )
  120. {
  121. LogHelper.Error("plc读取bool异常" + e.Message);
  122. throw new TimeoutException‌("PLC读取异常");
  123. }
  124. throw new InvalidOperationException‌("PLC未连接");
  125. }
  126. public bool[] ReadBools(int ReadONDBNumber, int ReadStart,int bitStart,int bitSize)
  127. {
  128. try
  129. {
  130. if ( client.Connected )
  131. {
  132. int bytesToRead = CalculateBytesToRead(ReadStart, bitStart, bitSize); // 返回3
  133. byte[]buffs=new byte[bytesToRead];
  134. Client.DBRead(ReadONDBNumber, ReadStart, bytesToRead, buffs);
  135. return ParseBoolArray(buffs, bitStart, bitSize);
  136. }
  137. }
  138. catch ( Exception e )
  139. {
  140. LogHelper.Error("plc读取bool数组异常" + e.Message);
  141. throw new TimeoutException‌("PLC读取异常");
  142. }
  143. throw new InvalidOperationException‌("PLC未连接");
  144. }
  145. /// <summary>
  146. /// 两位
  147. /// </summary>
  148. /// <param name="ReadONDBNumber"></param>
  149. /// <param name="ReadStart"></param>
  150. /// <returns></returns>
  151. /// <exception cref="TimeoutException‌"></exception>
  152. /// <exception cref="InvalidOperationException‌"></exception>
  153. public short Readshort(int ReadONDBNumber, int ReadStart)
  154. {
  155. try
  156. {
  157. if ( client.Connected )
  158. {
  159. byte[]buffs=new byte[2];
  160. Client.DBRead(ReadONDBNumber, ReadStart, 2, buffs);
  161. return buffs.GetIntAt(0);
  162. }
  163. }
  164. catch ( Exception e )
  165. {
  166. LogHelper.Error("plc读取Ushort异常" + e.Message);
  167. throw new TimeoutException‌("PLC读取异常");
  168. }
  169. throw new InvalidOperationException‌("PLC未连接");
  170. }
  171. /// <summary>
  172. /// 四位
  173. /// </summary>
  174. /// <param name="ReadONDBNumber"></param>
  175. /// <param name="ReadStart"></param>
  176. /// <returns></returns>
  177. /// <exception cref="TimeoutException‌"></exception>
  178. /// <exception cref="InvalidOperationException‌"></exception>
  179. public int ReadInt(int ReadONDBNumber, int ReadStart)
  180. {
  181. try
  182. {
  183. if ( client.Connected )
  184. {
  185. byte[]buffs=new byte[4];
  186. Client.DBRead(ReadONDBNumber, ReadStart, 4, buffs);
  187. return buffs.GetDIntAt(0);
  188. }
  189. }
  190. catch ( Exception e )
  191. {
  192. LogHelper.Error("plc读取Ushort异常" + e.Message);
  193. throw new TimeoutException‌("PLC读取异常");
  194. }
  195. throw new InvalidOperationException‌("PLC未连接");
  196. }
  197. public float Readfloat(int ReadONDBNumber, int ReadStart)
  198. {
  199. try
  200. {
  201. if ( client.Connected )
  202. {
  203. byte[]buffs=new byte[4];
  204. Client.DBRead(ReadONDBNumber, ReadStart, 4, buffs);
  205. return buffs.GetRealAt(0);
  206. }
  207. }
  208. catch ( Exception e )
  209. {
  210. LogHelper.Error("plc读取Float异常" + e.Message);
  211. throw new TimeoutException‌("PLC读取异常");
  212. }
  213. throw new InvalidOperationException‌("PLC未连接");
  214. }
  215. public TimeSpan ReadTime(int ReadONDBNumber, int ReadStart)
  216. {
  217. try
  218. {
  219. if ( client.Connected )
  220. {
  221. byte[]buffs=new byte[4];
  222. Client.DBRead(ReadONDBNumber, ReadStart, 4, buffs);
  223. return buffs.GetS7TimespanAt(0);
  224. }
  225. }
  226. catch ( Exception e )
  227. {
  228. LogHelper.Error("plc读取Float异常" + e.Message);
  229. throw new TimeoutException‌("PLC读取异常");
  230. }
  231. throw new InvalidOperationException‌("PLC未连接");
  232. }
  233. public string ReadString(int ReadONDBNumber, int ReadStart, int ReadSize = 1)
  234. {
  235. try
  236. {
  237. if ( client.Connected )
  238. {
  239. byte []buffs = new byte[ReadSize];
  240. //读取数据
  241. Client.DBRead(ReadONDBNumber, ReadStart, ReadSize, buffs);
  242. byte[] buffsT = new byte[ buffs[ 1 ] ];
  243. Array.Copy(buffs, 2, buffsT, 0, buffs[ 1 ]);
  244. string str=(Encoding.ASCII.GetString(buffsT)).Trim().TrimEnd('\0') ;
  245. return str;
  246. }
  247. }
  248. catch ( Exception e )
  249. {
  250. LogHelper.Error("plc读取String异常" + e.Message);
  251. }
  252. return null;
  253. }
  254. public void WriteBool(int WriteONDBNumber, int WriteStart,int bitStart, bool value)
  255. {
  256. try
  257. {
  258. if ( client.Connected )
  259. {
  260. byte[] res = new byte[1];
  261. client.DBRead(WriteONDBNumber, WriteStart, 1, res);
  262. res.SetBitAt(0, bitStart, value);
  263. client.DBWrite(WriteONDBNumber, WriteStart, 1, res);
  264. }
  265. }
  266. catch ( Exception e )
  267. {
  268. LogHelper.Error("plc写入bool异常" + e.Message);
  269. }
  270. }
  271. public void Writeshort(int WriteONDBNumber, int WriteStart, short value)
  272. {
  273. try
  274. {
  275. if ( client.Connected )
  276. {
  277. byte[] res = new byte[2];
  278. res.SetIntAt(0, value);
  279. client.DBWrite(WriteONDBNumber, WriteStart, 2, res);
  280. }
  281. }
  282. catch ( Exception e )
  283. {
  284. LogHelper.Error("plc写入Ushort异常" + e.Message);
  285. }
  286. }
  287. public void Writefloat(int WriteONDBNumber, int WriteStart, float value)
  288. {
  289. try
  290. {
  291. if ( client.Connected )
  292. {
  293. byte[] res = new byte[4];
  294. res.SetRealAt(0, value);
  295. client.DBWrite(WriteONDBNumber, WriteStart, 4, res);
  296. }
  297. }
  298. catch ( Exception e )
  299. {
  300. LogHelper.Error("plc写入Float异常" + e.Message);
  301. }
  302. }
  303. public void WriteTime(int WriteONDBNumber, int WriteStart, TimeSpan value)
  304. {
  305. try
  306. {
  307. if ( client.Connected )
  308. {
  309. byte[] res = new byte[4];
  310. res.SetS7TimespanAt(0, value);
  311. client.DBWrite(WriteONDBNumber, WriteStart, 4, res);
  312. }
  313. }
  314. catch ( Exception e )
  315. {
  316. LogHelper.Error("plc写入Float异常" + e.Message);
  317. }
  318. }
  319. public bool GetBitAt(byte[] buffs, int byteStart, int bitStart)
  320. {
  321. try
  322. {
  323. return buffs.GetBitAt(byteStart, bitStart);
  324. }
  325. catch ( Exception e )
  326. {
  327. LogHelper.Error("提取bool异常" + e.Message);
  328. throw new TimeoutException‌("PLC读取异常");
  329. }
  330. }
  331. public float GetRealAt(byte[] buffs, int byteStart)
  332. {
  333. try
  334. {
  335. return buffs.GetRealAt(byteStart);
  336. }
  337. catch ( Exception e )
  338. {
  339. LogHelper.Error("提取float异常" + e.Message);
  340. throw new TimeoutException‌("PLC读取异常");
  341. }
  342. }
  343. public short GetShortAt(byte[] buffs, int byteStart)
  344. {
  345. try
  346. {
  347. return buffs.GetIntAt(byteStart);
  348. }
  349. catch ( Exception e )
  350. {
  351. LogHelper.Error("提取short异常" + e.Message);
  352. throw new TimeoutException‌("PLC读取异常");
  353. }
  354. }
  355. public string GetStringAt(byte[] buffs, int byteStart)
  356. {
  357. try
  358. {
  359. return buffs.GetStringAt(byteStart);
  360. }
  361. catch ( Exception e )
  362. {
  363. LogHelper.Error("提取float异常" + e.Message);
  364. throw new TimeoutException‌("PLC读取异常");
  365. }
  366. }
  367. public TimeSpan GetTimeSpanAt(byte[] buffs, int byteStart)
  368. {
  369. try
  370. {
  371. return buffs.GetS7TimespanAt(byteStart);
  372. }
  373. catch ( Exception e )
  374. {
  375. LogHelper.Error("提取TimeSpan异常" + e.Message);
  376. throw new TimeoutException‌("PLC读取异常");
  377. }
  378. }
  379. // 参数说明:startByte-起始字节, startBit-起始位(0-7), bitCount-读取位数
  380. int CalculateBytesToRead(int startByte, int startBit, int bitCount)
  381. {
  382. int totalBits = startByte * 8 + startBit + bitCount; // 全局结束位索引
  383. int endByte = (totalBits - 1) / 8; // 结束字节索引(整数除法)
  384. return endByte - startByte + 1; // 需要读取的字节数
  385. }
  386. bool[] ParseBoolArray(byte[] buffer, int startBit, int bitCount)
  387. {
  388. bool[] results = new bool[bitCount];
  389. for ( int i = 0; i < bitCount; i++ )
  390. {
  391. int globalBit = startBit + i; // 目标位全局偏移
  392. int byteIndex = globalBit / 8; // 字节在buffer中的索引
  393. int bitIndex = globalBit % 8; // 位在字节中的索引
  394. results[ i ] = S7.GetBitAt(buffer, byteIndex, bitIndex); // 提取位值
  395. }
  396. return results;
  397. }
  398. }
  399. }