Files
SamplePreSystem-CS/SamplePre.Communication/Communication/S7PlcCommunicatorBack.cs
2026-04-30 11:34:41 +08:00

425 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}