TCP和UDP协议:
TCP(传输控制协议)和UDP(用户数据报协议)是TCP/IP协议簇中的两种核心协议。它们在传输层上提供数据传输服务,但具有不同的特性和功能。
TCP协议是一种提供可靠、面向连接的字节流服务的传输协议。在数据传输前,发送方和接收方必须先建立TCP连接,然后才能进行数据传输。它通过超时重发、丢弃重复数据、数据检验等功能,确保数据能从一端传输到另一端。
UDP协议则是一种简单的面向数据报的传输层协议,它提供的是非面向连接、不可靠的数据流传输服务。由于UDP在传输数据报前不需要在客户和服务器之间建立连接,也没有超时重发等机制,因此其传输速度相对较快。但这也意味着它不能提供数据传输的可靠性保障。
总的来说,TCP和UDP各有其优点和使用场景。TCP主要应用于可靠性要求高的应用,如网页浏览、文件传输等;而UDP则更适合于可靠性要求低、对传输速度和经济性有一定需求的应用,如视频流、游戏等。
RS-232和RS-475通信接口标准及Modbus协议:
RS-232是一种常见的串行通信接口标准,由美国电子工业协会(EIA)联合贝尔系统公司、调制解调器厂家及计算机终端生产厂家于1970年共同制定。其全名为“数据终端设备(DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准”。它通常被应用于计算机、调制解调器和各种电子设备之间的通信连接。
RS-475是一种由美国电子工业协会(EIA)制定的半双工通信接口标准,它通常被应用于电子设备之间的数据传输。它采用平衡驱动和差分接收,因此具有较好的抗干扰能力,同时传输距离较远,可以达到数百米甚至千米级别。与RS-232不同的是,RS-475通常采用9针D型连接器,并且其引脚定义也与RS-232有所不同。RS-475主要用于工业、科学和医疗等领域的设备间通信,但由于其半双工的限制,应用场景不如RS-232和RS-485广泛。
Modbus是一种串行通信协议,最初由Modicon公司(现在的施耐德电气 Schneider Electric)于1979年开发,用于可编程逻辑控制器(PLC)之间的通信。此协议已经成为工业领域通信协议的业界标准,并且现在是工业电子设备之间常用的连接方式。西门子的S1200和S1500用的就是Modbus协议
Modbus协议定义了一个控制器能够识别的消息结构,不管它们是经过何种网络进行通信的。它描述了控制器请求访问其他设备的过程,如果回应来自其他设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。当在Modbus网络上通信时,此协议决定了每个控制器需要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。总的来说,Modbus是一种应用于电子控制器之间的通用语言,通过它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。
一、使用HslCommunication程序集,官网:胡工科技。
- using Newtonsoft.Json.Linq;
- using System;
- using System.Collections.Generic;
- using System.Net;
- using System.Threading;
- using HslCommunication;
- using HslCommunication.Profinet.Siemens;
- using HslCommunication.Profinet.Omron;
- using HslCommunication.Profinet.Keyence;
-
- namespace PLC.Class
- {
- public class PLCHelper
- {
- #region 连接西门子PLC--SiemensS7Net
- /// <summary>
- /// 连接西门子PLC--SiemensS7Net
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <returns></returns>
- private bool ConnectSiemens(SiemensS7Net siemens, string ip, int port)
- {
- try
- {
- IPAddress ipaddress;
- bool flag = !IPAddress.TryParse(ip, out ipaddress);
- if (flag)
- {
- return false;
- }
- else
- {
- siemens.IpAddress = ip;
- siemens.Port = port;
- OperateResult operateResult = siemens.ConnectServer();
- bool isSuccess = operateResult.IsSuccess;
- if (isSuccess)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- /// <summary>
- /// 给西门子PLC点位写信号
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="flag">给点位传入的值</param>
- /// <returns></returns>
- public bool WriteFlagBySiemens(SiemensS7Net siemens, string ip, int port, string point, short flag)
- {
- if (ConnectSiemens(siemens, ip, port))
- {
- OperateResult result = siemens.Write(point, flag);
- siemens.ConnectClose();
- return result.IsSuccess;
- }
- else
- {
- return false;
- }
- }
-
- /// <summary>
- /// 读取西门子PLC的状态
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <returns></returns>
- public bool ReadBoolBySiemens(SiemensS7Net siemens, string ip, int port, string point)
- {
- if (ConnectSiemens(siemens, ip, port))
- {
- OperateResult<bool> value = siemens.ReadBool(point);
- siemens.ConnectClose();
- return value.Content;
- }
- else
- {
- return false;
- }
- }
-
- /// <summary>
- /// 读取西门子PLC的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="length">读取长度</param>
- /// <returns></returns>
- public string ReadStringBySiemens(SiemensS7Net siemens, string ip, int port, string point, ushort length)
- {
- if (ConnectSiemens(siemens, ip, port))
- {
- OperateResult<string> result = new OperateResult<string>();
- result = siemens.ReadString(point, length);
- string source = string.Empty;
-
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- }
- else
- {
- for (int i = 0; i < 3; i++)
- {
- Thread.Sleep(10);
- result = siemens.ReadString(point, length);
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- break;
- }
- }
- if (string.IsNullOrEmpty(result.Content))
- {
- return "未读取到PLC信息";
- }
- }
- siemens.ConnectClose();
- return source;
- }
- else
- {
- return "false";
- }
- }
-
- /// <summary>
- /// 清空西门子PLC点位中的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- /// <param name="point"></param>
- /// <param name="length">写入的长度</param>
- /// <returns></returns>
- public bool ClearPlcPocketBySiemens(SiemensS7Net siemens, string ip, int port, string point, int length, string flag = " ")
- {
- if (ConnectSiemens(siemens, ip, port))
- {
- OperateResult result = siemens.Write(point, flag, length);
- siemens.ConnectClose();
- return result.IsSuccess;
- }
- else
- {
- return false;
- }
- }
- #endregion
-
- #region 连接欧姆龙PLC--OmronFinsNet
- /// <summary>
- /// 连接欧姆龙PLC--OmronFinsNet
- /// </summary>
- /// <param name="omron"></param>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- /// <returns></returns>
- private bool ConnectOmron(OmronFinsNet omron, string ip, int port)
- {
- //OmronFinsUdp
- try
- {
- IPAddress ipaddress;
- bool flag = !IPAddress.TryParse(ip, out ipaddress);
- if (flag)
- {
- return false;
- }
- else
- {
- omron.IpAddress = ip;
- omron.Port = port;
- omron.SA1 = 239;
- //if (ip240.Contains(ip))
- //{
- // omron.SA1 = 240;
- //}
- //else
- //{
- // omron.SA1 = 239;
- //}
- //omron.DA1 = 24;
- OperateResult operateResult = omron.ConnectServer();
- if (!operateResult.IsSuccess)
- {
- for (int i = 0;i < 3;i++)
- {
- operateResult = omron.ConnectServer();
- if (operateResult.IsSuccess)
- {
- break;
- //return true;
- }
- }
- //SA1使用239连接不上,则采取240连接
- if (!operateResult.IsSuccess)
- {
- omron.SA1 = 240;
- for (int i = 0; i < 3; i++)
- {
- operateResult = omron.ConnectServer();
- if (operateResult.IsSuccess)
- {
- break;
- //return true;
- }
- }
- }
- //if (!isSuccess)
- //{
- // return false;
- //}
- }
- return operateResult.IsSuccess;
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteErrLog(ex.ToString());
- return false;
- }
- }
-
- /// <summary>
- /// 给欧姆龙PLC点位写信号
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="flag">给点位传入的值</param>
- /// <returns></returns>
- public bool WriteShortByOmron(OmronFinsNet omron, string ip, int port, string point, short flag)
- {
- //if (ConnectOmron(omron, ip, port))
- //{
- OperateResult result = omron.Write(point, flag);
- if (!result.IsSuccess)
- {
- for (int i = 0;i < 3;i++)
- {
- result = omron.Write(point,flag);
- if (result.IsSuccess)
- {
- break;
- //return true;
- }
- }
- //if (!result.IsSuccess)
- //{
- // return false;
- //}
- }
- //omron.ConnectClose();
- return result.IsSuccess;
- //}
- //else
- //{
- // return false;
- //}
- }
-
- //写入float值
- public bool WriteFloatByOmron(OmronFinsNet omron, string ip, int port, string point, float flag)
- {
- //if (ConnectOmron(omron, ip, port))
- //{
- OperateResult result = omron.Write(point, flag);
- if (!result.IsSuccess)
- {
- for (int i = 0; i < 3; i++)
- {
- result = omron.Write(point, flag);
- if (result.IsSuccess)
- {
- break;
- //return true;
- }
- }
- //if (!result.IsSuccess)
- //{
- // return false;
- //}
- }
- //omron.ConnectClose();
- return result.IsSuccess;
- //}
- //else
- //{
- // return false;
- //}
- }
-
- public string WritePointByOmron(OmronFinsNet omron, string ip, int port, List<string> pointlst, List<string> dataTypelst, List<string> valuelst,string type,List<string> filedlst)
- {
- //int sucNum = 0;
- string errorFileds = "";
- try
- {
- if (type == "EDIT")
- {
- //return 0;
- return "";
- }
- //调用时以下6个点位不写入
- List<string> addNotWritePoint = new List<string>() { "D200", "D202", "D210", "D212", "D0", "D469" };
- if (ConnectOmron(omron, ip, port))
- {
- for (int i = 0; i < pointlst.Count; i++)
- {
- if (addNotWritePoint.Contains(pointlst[i]))
- {
- continue;
- }
-
- if (dataTypelst[i] == "FLOAT" && !string.IsNullOrEmpty(valuelst[i]))
- {
- float flag = Convert.ToSingle(valuelst[i]);
- bool result = WriteFloatByOmron(omron, ip, port, pointlst[i], flag);
- if (result)
- {
- //sucNum++;
- }
- else
- {
- if (errorFileds.Length > 0)
- {
- errorFileds += ",";
- }
- errorFileds += filedlst[i];
- LogHelper.WriteErrLog($"IP:{ip},端口:{port},点位:{pointlst[i]},值:{valuelst[i]}写入失败!");
- }
- }
- else if (dataTypelst[i] == "SHORT" && !string.IsNullOrEmpty(valuelst[i]))
- {
- short flag = Convert.ToInt16(valuelst[i]);
- bool result = WriteShortByOmron(omron, ip, port, pointlst[i], flag);
- if (result)
- {
- //sucNum++;
- }
- else
- {
- if (errorFileds.Length > 0)
- {
- errorFileds += ",";
- }
- errorFileds += filedlst[i];
- LogHelper.WriteErrLog($"IP:{ip},端口:{port},点位:{pointlst[i]},值:{valuelst[i]}写入失败!");
- }
- }
- }
- //return sucNum;
- }
- //else
- //{
- // return sucNum;
- //}
- }
- catch (Exception ex)
- {
- LogHelper.WriteErrLog(ex.ToString());
- }
- finally
- {
- omron.ConnectClose();
- }
- //return sucNum;
- return errorFileds;
- }
-
- /// <summary>
- /// 读取欧姆龙PLC的状态
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <returns></returns>
- public bool ReadBoolByOmron1(OmronFinsNet omron, string ip, int port, string point)
- {
- if (ConnectOmron(omron, ip, port))
- {
- OperateResult<bool> value = omron.ReadBool(point);
- omron.ConnectClose();
- return value.Content;
- }
- else
- {
- return false;
- }
- }
-
- //读取float型数据
- public float ReadFloatByOmron(OmronFinsNet omron, string ip, int port, string point)
- {
- //if (ConnectOmron(omron, ip, port))
- //{
- OperateResult<float> value = omron.ReadFloat(point);
- if (!value.IsSuccess)
- {
- for (int i = 0;i < 3;i++)
- {
- value = omron.ReadFloat(point);
- if (value.IsSuccess)
- {
- break;
- //return value.Content;
- }
- }
- //if (!value.IsSuccess)
- //{
- // return 0;
- //}
- }
- //omron.ConnectClose();
- if (value.IsSuccess)
- {
- return value.Content;
- }
- else
- {
- return 0;
- }
- //}
- //else
- //{
- // return 0;
- //}
- }
-
- //读取short型数据
- public short ReadShortByOmron(OmronFinsNet omron, string ip, int port, string point)
- {
- //if (ConnectOmron(omron, ip, port))
- //{
- OperateResult<short> value = omron.ReadInt16(point);
- if (!value.IsSuccess)
- {
- for (int i = 0; i < 3; i++)
- {
- value = omron.ReadInt16(point);
- if (value.IsSuccess)
- {
- break;
- //return value.Content;
- }
- }
- //if (!value.IsSuccess)
- //{
- // return 0;
- //}
- }
- //omron.ConnectClose();
- if (value.IsSuccess)
- {
- return value.Content;
- }
- else
- {
- return 0;
- }
- //}
- //else
- //{
- // return 0;
- //}
- }
-
- //读取Bool类型数据
- public bool ReadBoolByOmron(OmronFinsNet omron, string ip, int port, string point)
- {
- OperateResult<bool> value = omron.ReadBool(point);
- if (!value.IsSuccess)
- {
- for (int i = 0; i < 3; i++)
- {
- value = omron.ReadBool(point);
- if (value.IsSuccess)
- {
- break;
- }
- }
- }
- if (value.IsSuccess)
- {
- return value.Content;
- }
- else
- {
- return false;
- }
- }
-
- public string ReadPointByOmron(OmronFinsNet omron, string ip, int port, List<string> filedlst, List<string> pointlst, List<string> datatypelst)
- {
- string result = "0";
- JObject jObj = new JObject();
-
- try
- {
- if (ConnectOmron(omron, ip, port))
- {
- for (int i = 0; i < pointlst.Count; i++)
- {
- if (datatypelst[i] == "FLOAT")
- {
- result = ReadFloatByOmron(omron, ip, port, pointlst[i]).ToString();
- }
- else if (datatypelst[i] == "SHORT")
- {
- result = ReadShortByOmron(omron, ip, port, pointlst[i]).ToString();
- }
- else if (datatypelst[i] == "BOOL" && pointlst[i] == "H10")
- {
- //涂布单双面3个点位细分—00:单面,01:双面,01;02:连续
- bool res = false;
- List<string> H10s = new List<string>() { "H10.00", "H10.01", "H10.02" };
- foreach (string h10 in H10s)
- {
- res = ReadBoolByOmron(omron, ip, port, h10);
- if (res)
- {
- result = h10.Substring(h10.Length - 1,1);
- break;
- }
- }
- }
-
- jObj.Add(new JProperty(filedlst[i], result));
- }
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteErrLog(ex.ToString());
- }
- finally
- {
- omron.ConnectClose();
- }
-
- return jObj.ToString();
- }
-
- /// <summary>
- /// 读取欧姆龙PLC的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="length">读取长度</param>
- /// <returns></returns>
- public string ReadStringByOmron(OmronFinsNet omron, string ip, int port, string point, ushort length)
- {
- if (ConnectOmron(omron, ip, port))
- {
- OperateResult<string> result = new OperateResult<string>();
- result = omron.ReadString(point, length);
- string source = string.Empty;
-
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- }
- else
- {
- for (int i = 0; i < 3; i++)
- {
- Thread.Sleep(10);
- result = omron.ReadString(point, length);
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- break;
- }
- }
- if (string.IsNullOrEmpty(result.Content))
- {
- return "未读取到PLC信息";
- }
- }
- omron.ConnectClose();
- return source;
- }
- else
- {
- return "false";
- }
- }
-
- /// <summary>
- /// 清空欧姆龙PLC点位中的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- /// <param name="point"></param>
- /// <param name="length">写入的长度</param>
- /// <returns></returns>
- public bool ClearPlcPocketByOmron(OmronFinsNet omron, string ip, int port, string point, int length, string flag = " ")
- {
- if (ConnectOmron(omron, ip, port))
- {
- OperateResult result = omron.Write(point, flag, length);
- omron.ConnectClose();
- return result.IsSuccess;
- }
- else
- {
- return false;
- }
- }
- #endregion
-
- #region 连接基恩士PLC--KeyenceMcNet
- /// <summary>
- /// 连接基恩士PLC--KeyenceMcNet
- /// </summary>
- /// <param name="omron"></param>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- /// <returns></returns>
- private bool ConnectKeyence(KeyenceMcNet keyence, string ip, int port)
- {
- try
- {
- IPAddress ipaddress;
- bool flag = !IPAddress.TryParse(ip, out ipaddress);
- if (flag)
- {
- return false;
- }
- else
- {
- keyence.IpAddress = ip;
- keyence.Port = port;
- OperateResult operateResult = keyence.ConnectServer();
- bool isSuccess = operateResult.IsSuccess;
- if (isSuccess)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- /// <summary>
- /// 给基恩士PLC点位写信号
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="flag">给点位传入的值</param>
- /// <returns></returns>
- public bool WriteFlagByKeyence(KeyenceMcNet keyence, string ip, int port, string point, short flag)
- {
- if (ConnectKeyence(keyence, ip, port))
- {
- OperateResult result = keyence.Write(point, flag);
- keyence.ConnectClose();
- return result.IsSuccess;
- }
- else
- {
- return false;
- }
- }
-
- /// <summary>
- /// 读取基恩士PLC的状态
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <returns></returns>
- public bool ReadBoolByKeyence(KeyenceMcNet keyence, string ip, int port, string point)
- {
- if (ConnectKeyence(keyence, ip, port))
- {
- OperateResult<bool> value = keyence.ReadBool(point);
- keyence.ConnectClose();
- return value.Content;
- }
- else
- {
- return false;
- }
- }
-
- /// <summary>
- /// 读取基恩士PLC的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip">IP地址</param>
- /// <param name="port">端口</param>
- /// <param name="point">PLC点位</param>
- /// <param name="length">读取长度</param>
- /// <returns></returns>
- public string ReadStringByKeyence(KeyenceMcNet keyence, string ip, int port, string point, ushort length)
- {
- if (ConnectKeyence(keyence, ip, port))
- {
- OperateResult<string> result = new OperateResult<string>();
- result = keyence.ReadString(point, length);
- string source = string.Empty;
-
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- }
- else
- {
- for (int i = 0; i < 3; i++)
- {
- Thread.Sleep(10);
- result = keyence.ReadString(point, length);
- if (!string.IsNullOrEmpty(result.Content))
- {
- source = result.Content;
- break;
- }
- }
- if (string.IsNullOrEmpty(result.Content))
- {
- return "未读取到PLC信息";
- }
- }
- keyence.ConnectClose();
- return source;
- }
- else
- {
- return "false";
- }
- }
-
- /// <summary>
- /// 清空基恩士PLC点位中的值
- /// </summary>
- /// <param name="siemens"></param>
- /// <param name="ip"></param>
- /// <param name="port"></param>
- /// <param name="point"></param>
- /// <param name="length">写入的长度</param>
- /// <returns></returns>
- public bool ClearPlcPocketByKeyence(KeyenceMcNet keyence, string ip, int port, string point, int length, string flag = " ")
- {
- if (ConnectKeyence(keyence, ip, port))
- {
- OperateResult result = keyence.Write(point, flag, length);
- keyence.ConnectClose();
- return result.IsSuccess;
- }
- else
- {
- return false;
- }
- }
- #endregion
- }
- }