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
}
}