425 lines
11 KiB
C#
425 lines
11 KiB
C#
|
|
|
|||
|
|
using S7.Net;
|
|||
|
|
using S7.Net.Types;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Net;
|
|||
|
|
using System.Runtime.InteropServices;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
namespace SamplePre.Communication
|
|||
|
|
{
|
|||
|
|
public class S7PlcCommunicatorBack : IDisposable
|
|||
|
|
{
|
|||
|
|
public Plc _plc;
|
|||
|
|
private readonly string _ipAddress;
|
|||
|
|
private readonly int _rack;
|
|||
|
|
private readonly int _slot;
|
|||
|
|
private readonly CpuType _cpuType;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否连接
|
|||
|
|
/// </summary>
|
|||
|
|
public bool IsConnected => _plc?.IsConnected ?? false;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 连接状态变化事件
|
|||
|
|
/// </summary>
|
|||
|
|
public event Action<bool> ConnectionStatusChanged;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 构造函数
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="cpuType">PLC型号</param>
|
|||
|
|
/// <param name="ipAddress">IP地址</param>
|
|||
|
|
/// <param name="rack">机架号</param>
|
|||
|
|
/// <param name="slot">插槽号</param>
|
|||
|
|
public S7PlcCommunicatorBack(CpuType cpuType, string ipAddress, int rack = 0, int slot = 1)
|
|||
|
|
{
|
|||
|
|
_cpuType = cpuType;
|
|||
|
|
_ipAddress = ipAddress;
|
|||
|
|
_rack = rack;
|
|||
|
|
_slot = slot;
|
|||
|
|
_plc = new Plc(cpuType, ipAddress, (short)rack, (short)slot);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 连接PLC
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>是否连接成功</returns>
|
|||
|
|
public bool Connect()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (IsConnected)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine("已经处于连接状态");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果之前的连接对象已释放,创建新的
|
|||
|
|
if (_plc == null)
|
|||
|
|
{
|
|||
|
|
_plc = new Plc(_cpuType, _ipAddress, (short)_rack, (short)_slot);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_plc.Open();
|
|||
|
|
bool connected = _plc.IsConnected;
|
|||
|
|
Console.WriteLine(connected ? "PLC连接成功" : "PLC连接失败");
|
|||
|
|
ConnectionStatusChanged?.Invoke(connected);
|
|||
|
|
return connected;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"连接PLC失败: {ex.Message}");
|
|||
|
|
ConnectionStatusChanged?.Invoke(false);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 断开连接
|
|||
|
|
/// </summary>
|
|||
|
|
public void Disconnect()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (IsConnected)
|
|||
|
|
{
|
|||
|
|
_plc.Close();
|
|||
|
|
Console.WriteLine("PLC连接已断开");
|
|||
|
|
ConnectionStatusChanged?.Invoke(false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"断开PLC连接失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="address">地址(如"M0.0", "DB1.DBW2")</param>
|
|||
|
|
/// <returns>读取的值</returns>
|
|||
|
|
public object ReadData(string address)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
object value = _plc.Read(address);
|
|||
|
|
Console.WriteLine($"a读取 {address} 成功: {value}");
|
|||
|
|
return value;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"读取 {address} 失败: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="address">地址(如"M0.0", "DB1.DBW2")</param>
|
|||
|
|
/// <param name="value">要写入的值</param>
|
|||
|
|
/// <returns>是否写入成功</returns>
|
|||
|
|
public bool WriteData(string address, object value)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_plc.Write(address, value);
|
|||
|
|
Console.WriteLine($"写入 {address} 成功: {value}");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"写入 {address} 失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 批量读取数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="addresses">地址数组</param>
|
|||
|
|
/// <returns>值数组,与地址数组顺序对应</returns>
|
|||
|
|
public object[] ReadMultipleData(string[] addresses)
|
|||
|
|
{
|
|||
|
|
if (addresses == null || addresses.Length == 0)
|
|||
|
|
return new object[0];
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var values = new object[addresses.Length];
|
|||
|
|
for (int i = 0; i < addresses.Length; i++)
|
|||
|
|
{
|
|||
|
|
values[i] = _plc.Read(addresses[i]);
|
|||
|
|
}
|
|||
|
|
Console.WriteLine($"批量读取 {addresses.Length} 个地址成功");
|
|||
|
|
return values;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"批量读取失败: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入数组数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="Dbno"></param>
|
|||
|
|
/// <param name="start"></param>
|
|||
|
|
/// <param name="bytes"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool WriteArraysBtye(int Dbno, int start, byte[] bytes)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
_plc.WriteBytes(DataType.DataBlock, Dbno, start, bytes);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"写入数组: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取数组
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public ushort[] ReadArraysShort(int Dbno,int start,int lenth)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
|
|||
|
|
ushort[] datas = _plc.Read(DataType.DataBlock, Dbno, start, VarType.Word, lenth) as ushort[];
|
|||
|
|
return datas;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"读取数组: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读结构体
|
|||
|
|
/// </summary>
|
|||
|
|
public T ReadStruct<T>(int dbno, int start)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
T t;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return default(T);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
t = (T)_plc.ReadStruct(typeof(T), dbno, start);
|
|||
|
|
return t;
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
Console.WriteLine($"读结构体失败!");
|
|||
|
|
return default(T);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写结构体
|
|||
|
|
/// </summary>
|
|||
|
|
public bool WriteStruct<T>(T t,int dbno,int start)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_plc.WriteStruct(t, dbno, start);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
Console.WriteLine($"写入失败!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取字符串
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="DBno"></param>
|
|||
|
|
/// <param name="startNo"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public string ReadString(int DBno, int startNo)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int totalLenth = (byte)_plc.Read(S7.Net.DataType.DataBlock, DBno, startNo, VarType.Byte, 1);
|
|||
|
|
int len = (byte)_plc.Read(S7.Net.DataType.DataBlock, DBno, startNo + 1, VarType.Byte, 1);
|
|||
|
|
byte[] bytes = _plc.ReadBytes(S7.Net.DataType.DataBlock, DBno, startNo + 2, len);
|
|||
|
|
string mesg = Encoding.ASCII.GetString(bytes);
|
|||
|
|
|
|||
|
|
|
|||
|
|
return mesg;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"读取字符串失败!");
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入字符串
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="DBno"></param>
|
|||
|
|
/// <param name="startNo"></param>
|
|||
|
|
/// <param name="contextStr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool WriteString(int DBno,int startNo, string contextStr)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_plc.Write(S7.Net.DataType.DataBlock, DBno, startNo + 1, (byte)contextStr.Length);
|
|||
|
|
_plc.Write(S7.Net.DataType.DataBlock, DBno, startNo + 2, contextStr);
|
|||
|
|
|
|||
|
|
Console.WriteLine($"写入字符串成功!");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"写入字符串失败!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入bool
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="DBno"></param>
|
|||
|
|
/// <param name="startNo"></param>
|
|||
|
|
/// <param name="contextStr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool WriteBoolen(int DBno, int startByteAdr, int bitAdr, bool val)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnected && !Connect())
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_plc.WriteBit(DataType.DataBlock, DBno, startByteAdr, bitAdr, val);
|
|||
|
|
|
|||
|
|
|
|||
|
|
Console.WriteLine($"写入成功!");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine($"写入失败!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 释放资源
|
|||
|
|
/// </summary>
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
Disconnect();
|
|||
|
|
//_plc?.Dispose();
|
|||
|
|
_plc = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
struct TestA
|
|||
|
|
{
|
|||
|
|
public ushort value1;
|
|||
|
|
public ushort value2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|