using S7.Net;
using System.Text.RegularExpressions;
using static xxxx.Enums.EnumType;
namespace Camera3D.Helper.PLC
{
public class SIEMENS_PLCHelper
{
/// <summary>
///
/// </summary>
public static SIEMENS_PLCHelper? Instance;
// private MitsubishiClient? client;
private Plc plc;
/// <summary>
/// 实例
/// </summary>
/// <returns></returns>
public static SIEMENS_PLCHelper GetInstance()
{
if (Instance == null)
{
Instance = new SIEMENS_PLCHelper();
}
return Instance;
}
/// <summary>
/// 连接PLC
/// </summary>
/// <returns></returns>
public bool Connected()
{
// Log.Logger.Debug($"PLC Connected = {client.Connected}");
return plc.IsConnected;//.Connected;
}
/// <summary>
/// 连接PLC
/// </summary>
/// <returns></returns>
public void ConnectToPlc()
{
//SystemParams.PLC.SIEMENS_IP
string PLCIP = SystemParams.PLC.SIEMENS_IP;// AppSettingsHelper.Configuration["PLC:IP"];
bool isIPOK = xxxx.Utils.Utils.IsIpAddressValid(PLCIP);
if (isIPOK)
{
plc = new Plc(CpuType.S71500, PLCIP, 0, 1);
try
{
plc.Open();
string jsonLog = JsonConvert.SerializeObject(new
{
Msg = $"PLC 连接 {PLCIP} {(Connected() ? "成功" : "失败")}",
IP = SystemParams.PLC.SIEMENS_IP,
Port = SystemParams.PLC.SIEMENS_Port,
Connected = plc.IsConnected
});
if (Connected())
{
Log.Logger.Debug($"{jsonLog}");
}
else
{
Log.Logger.Error($"{jsonLog}");
}
}
catch (Exception ex)
{
Log.Logger.Error($"{ex.Message}");
}
}
else
{
Log.Logger.Error($"PLC IP =[{PLCIP}] 不合法");
}
}
public async Task< string> PLCRead(string ValueType, string TagName, byte bitAdr = 0,int StrLength=1)
{
var TagNameResult = ParseDbAddress(TagName);
//if (plc == null || !IsConnected)
//{
// Connect();
//}
string Result = "";
switch (ValueType.ToUpper())
{
case "BOOL":
Result = ((bool)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.Bit, 1, bitAdr)).ToString();
break;
//case "BYTE":
// Result = ((byte)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.Byte, 1)).ToString();
// break;
case "INT16":
Result = (plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.Int, 1)).ToString();
break;
case "INT32":
Result = ((Int32)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.DInt, 1)).ToString();
break;
case "REAL":
Result = ((double)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.Real, 1)).ToString();
break;
case "DOUBLE":
Result = ((double)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, VarType.LReal, 1)).ToString();
break;
case "STRING":
//Result = (string)plc.Read(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset + 2, VarType.String, StrLength);
先读取前2字节获取元数据
byte[] header = plc.ReadBytes(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, 2);
int maxLength = header[0];
int currentLength = header[1];
// 读取完整字符串内容
byte[] buffer = plc.ReadBytes(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset + 2, currentLength);
Result = Encoding.ASCII.GetString(buffer);
break;
}
return Result;
}
public async Task<PLCRWResult> PLCWrite(string ValueType, string TagName, string value)
{
//if (plc == null || !IsConnected)
//{
// Connect();
//}
PLCRWResult Result = xxxx.Enums.EnumType.PLCRWResult.Empty;
var TagNameResult = ParseDbAddress(TagName);
await Task.Delay(1);
// string Result = "";
try
{
switch (ValueType.ToUpper())
{
case "BOOL":
plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, bool.Parse(value));
break;
//case "BYTE":
// plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, bitAdr);
// break;
case "INT16":
plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, short.Parse(value));
break;
case "INt32":
plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, int.Parse(value));
break;
case "REAL":
plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, float.Parse(value));
break;
case "DOUBLE":
plc.Write(S7.Net.DataType.DataBlock, TagNameResult.DbNumber, TagNameResult.Offset, double.Parse(value));
break;
}
Result = xxxx.Enums.EnumType.PLCRWResult.OK;
}
catch (Exception ex)
{
Log.Logger.Error($" PLC 写入 ValueType = {ValueType} 异常 TagName = {TagName} {ex.Message}");
Result = xxxx.Enums.EnumType.PLCRWResult.Error;
}
return Result;
}
/// <summary>
/// 解析 DB 地址格式(支持 DBXXXX.Y.Z 或 DBXXXX.Y)
/// </summary>
public static (int DbNumber, int Offset) ParseDbAddress(string address)
{
// 正则匹配:DB开头 + 数字 + . + 数字 + . + 数字
var match = Regex.Match(
address,
@"^DB(\d+)\.(\d+)(?:\.\d+)?$",
RegexOptions.IgnoreCase
);
if (!match.Success)
throw new ArgumentException("无效的地址格式: " + address);
// 提取数值
if (!int.TryParse(match.Groups[1].Value, out int dbNumber))
throw new ArgumentException("无效的DB编号: " + match.Groups[1].Value);
if (!int.TryParse(match.Groups[2].Value, out int offset))
throw new ArgumentException("无效的偏移量: " + match.Groups[2].Value);
return (dbNumber, offset);
}
}
}
示例
TagName ="DB400.0.0" 由于电气工程师只给这个格式,所以
result = await SIEMENS_PLCHelper.GetInstance().PLCRead("STRING",TagName,0,Length);