接口文档汇总 - 3.PLC通信管理

0 阅读5分钟

C# WPF PLC通信管理标准化接口设计文档

1. 引言

本文档定义了一套用于WPF应用程序的PLC通信管理标准化接口。该设计旨在统一多种PLC通信方式(串口、TCP/IP)及常见协议(Modbus RTU/ASCII/TCP、三菱MC协议),为上层应用提供一致的编程模型,简化PLC数据读写和状态管理。通过标准化接口,开发人员可以灵活替换底层协议实现,同时保持业务代码不变。

2. 通信状态枚举

表示PLC连接的当前状态。

/// <summary>
/// 表示PLC通信连接的状态。
/// </summary>
public enum PlcConnectionState
{
    /// <summary>初始状态,未连接。</summary>
    Disconnected,

    /// <summary>正在建立连接。</summary>
    Connecting,

    /// <summary>已成功连接。</summary>
    Connected,

    /// <summary>连接发生错误,无法通信。</summary>
    Error,

    /// <summary>正在断开连接。</summary>
    Disconnecting
}

3. 通信参数配置接口 IPlcConnectionConfig

用于封装不同协议和传输方式所需的连接参数。

/// <summary>
/// PLC连接配置的基接口。
/// </summary>
public interface IPlcConnectionConfig
{
    /// <summary>
    /// 获取通信超时时间(毫秒)。
    /// </summary>
    int Timeout { get; }

    /// <summary>
    /// 获取重试次数。
    /// </summary>
    int RetryCount { get; }
}

/// <summary>
/// 串口通信配置。
/// </summary>
public interface ISerialPortConfig : IPlcConnectionConfig
{
    string PortName { get; }
    int BaudRate { get; }
    int DataBits { get; }
    System.IO.Ports.Parity Parity { get; }
    System.IO.Ports.StopBits StopBits { get; }
}

/// <summary>
/// 以太网通信配置。
/// </summary>
public interface IEthernetConfig : IPlcConnectionConfig
{
    string IpAddress { get; }
    int Port { get; }
}

/// <summary>
/// Modbus协议特定配置(可选)。
/// </summary>
public interface IModbusConfig : IPlcConnectionConfig
{
    byte StationId { get; }  // 从站地址
    // 可扩展 Modbus 相关参数
}

/// <summary>
/// 三菱MC协议配置。
/// </summary>
public interface IMcProtocolConfig : IPlcConnectionConfig
{
    /// <summary>网络编号(通常为0)</summary>
    byte NetworkNumber { get; }

    /// <summary>PC编号(通常为0xFF)</summary>
    byte PcNumber { get; }

    /// <summary>目标模块IO编号(通常为0x03FF)</summary>
    ushort DestinationModuleIoNumber { get; }

    /// <summary>目标模块站号(通常为0)</summary>
    byte DestinationModuleStationNumber { get; }

    /// <summary>CPU定时器(秒)</summary>
    ushort CpuTimer { get; }
}

4. 核心PLC通信接口 IPlcCommunicator

定义统一的PLC通信操作方法,支持异步读写。

/// <summary>
/// PLC通信器接口,提供连接管理和数据读写功能。
/// </summary>
public interface IPlcCommunicator : IDisposable
{
    /// <summary>
    /// 当前连接状态。
    /// </summary>
    PlcConnectionState State { get; }

    /// <summary>
    /// 连接配置。
    /// </summary>
    IPlcConnectionConfig Config { get; }

    /// <summary>
    /// 连接状态变化事件。
    /// </summary>
    event EventHandler<PlcConnectionStateChangedEventArgs> StateChanged;

    /// <summary>
    /// 建立连接(异步)。
    /// </summary>
    Task ConnectAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 断开连接(异步)。
    /// </summary>
    Task DisconnectAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取单个位(线圈/触点)。
    /// </summary>
    /// <param name="address">地址,如 "M100"、"Q0.0" 等。</param>
    Task<bool> ReadBoolAsync(string address, CancellationToken cancellationToken = default);

    /// <summary>
    /// 写入单个位。
    /// </summary>
    Task WriteBoolAsync(string address, bool value, CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取16位整数。
    /// </summary>
    Task<short> ReadInt16Async(string address, CancellationToken cancellationToken = default);

    /// <summary>
    /// 写入16位整数。
    /// </summary>
    Task WriteInt16Async(string address, short value, CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取32位整数。
    /// </summary>
    Task<int> ReadInt32Async(string address, CancellationToken cancellationToken = default);

    /// <summary>
    /// 写入32位整数。
    /// </summary>
    Task WriteInt32Async(string address, int value, CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取浮点数(32位)。
    /// </summary>
    Task<float> ReadFloatAsync(string address, CancellationToken cancellationToken = default);

    /// <summary>
    /// 写入浮点数。
    /// </summary>
    Task WriteFloatAsync(string address, float value, CancellationToken cancellationToken = default);

    /// <summary>
    /// 读取字符串(指定长度)。
    /// </summary>
    Task<string> ReadStringAsync(string address, ushort length, CancellationToken cancellationToken = default);

    /// <summary>
    /// 写入字符串。
    /// </summary>
    Task WriteStringAsync(string address, string value, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量读取字节数组(适用于任意数据块)。
    /// </summary>
    Task<byte[]> ReadBytesAsync(string address, ushort length, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量写入字节数组。
    /// </summary>
    Task WriteBytesAsync(string address, byte[] data, CancellationToken cancellationToken = default);
}

设计说明:地址字符串格式由具体实现解释,例如 "D100""M0""40001" 等,推荐采用协议相关的标准表示。

5. 通信结果封装(可选)

为了提供更丰富的返回值(包含错误信息等),可以定义结果类。

/// <summary>
/// 表示PLC读写操作的结果。
/// </summary>
/// <typeparam name="T">数据类型。</typeparam>
public class PlcResult<T>
{
    public bool IsSuccess { get; set; }
    public T Value { get; set; }
    public string ErrorMessage { get; set; }
    public Exception Exception { get; set; }

    public static PlcResult<T> Success(T value) => new PlcResult<T> { IsSuccess = true, Value = value };
    public static PlcResult<T> Failure(string error, Exception ex = null) => new PlcResult<T> { IsSuccess = false, ErrorMessage = error, Exception = ex };
}

6. 通信事件参数

/// <summary>
/// PLC连接状态变化事件参数。
/// </summary>
public class PlcConnectionStateChangedEventArgs : EventArgs
{
    public PlcConnectionState OldState { get; }
    public PlcConnectionState NewState { get; }
    public string Message { get; }

    public PlcConnectionStateChangedEventArgs(PlcConnectionState oldState, PlcConnectionState newState, string message = "")
    {
        OldState = oldState;
        NewState = newState;
        Message = message;
    }
}

/// <summary>
/// PLC数据接收事件参数(适用于订阅特定地址变化)。
/// </summary>
public class PlcDataReceivedEventArgs : EventArgs
{
    public string Address { get; }
    public object Value { get; }
    public DateTime Timestamp { get; }

    public PlcDataReceivedEventArgs(string address, object value)
    {
        Address = address;
        Value = value;
        Timestamp = DateTime.Now;
    }
}

7. 协议特定接口(可选扩展)

对于某些协议可能需要特殊方法,可定义子接口。

7.1 Modbus专用接口

public interface IModbusCommunicator : IPlcCommunicator
{
    /// <summary>读取线圈(功能码01)。</summary>
    Task<bool[]> ReadCoilsAsync(ushort startAddress, ushort quantity, CancellationToken cancellationToken = default);

    /// <summary>读取离散输入(功能码02)。</summary>
    Task<bool[]> ReadDiscreteInputsAsync(ushort startAddress, ushort quantity, CancellationToken cancellationToken = default);

    /// <summary>读取保持寄存器(功能码03)。</summary>
    Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort quantity, CancellationToken cancellationToken = default);

    /// <summary>读取输入寄存器(功能码04)。</summary>
    Task<ushort[]> ReadInputRegistersAsync(ushort startAddress, ushort quantity, CancellationToken cancellationToken = default);

    /// <summary>写入单个线圈(功能码05)。</summary>
    Task WriteSingleCoilAsync(ushort address, bool value, CancellationToken cancellationToken = default);

    /// <summary>写入单个寄存器(功能码06)。</summary>
    Task WriteSingleRegisterAsync(ushort address, ushort value, CancellationToken cancellationToken = default);

    /// <summary>写入多个线圈(功能码15)。</summary>
    Task WriteMultipleCoilsAsync(ushort startAddress, bool[] values, CancellationToken cancellationToken = default);

    /// <summary>写入多个寄存器(功能码16)。</summary>
    Task WriteMultipleRegistersAsync(ushort startAddress, ushort[] values, CancellationToken cancellationToken = default);
}

7.2 三菱MC协议专用接口

public interface IMcProtocolCommunicator : IPlcCommunicator
{
    /// <summary>批量读取软元件(字/双字)。</summary>
    Task<byte[]> ReadDeviceBlockAsync(string device, ushort size, CancellationToken cancellationToken = default);

    /// <summary>批量写入软元件。</summary>
    Task WriteDeviceBlockAsync(string device, byte[] data, CancellationToken cancellationToken = default);

    /// <summary>随机读取多个软元件。</summary>
    Task<byte[]> ReadRandomAsync(string[] devices, CancellationToken cancellationToken = default);

    /// <summary>远程运行/停止PLC。</summary>
    Task RemoteOperationAsync(PlcRemoteOperation operation, CancellationToken cancellationToken = default);
}

public enum PlcRemoteOperation
{
    Run,
    Stop,
    Reset
}

8. 通信管理器接口 IPlcCommunicationManager

用于管理多个PLC连接实例,提供统一的创建、获取、移除等功能。

/// <summary>
/// PLC通信管理器,负责创建和管理多个PLC通信器实例。
/// </summary>
public interface IPlcCommunicationManager : IDisposable
{
    /// <summary>
    /// 根据配置创建新的PLC通信器。
    /// </summary>
    /// <param name="config">连接配置。</param>
    /// <param name="id">可选标识符,若未提供则自动生成。</param>
    /// <returns>创建的PLC通信器实例。</returns>
    IPlcCommunicator CreateCommunicator(IPlcConnectionConfig config, string id = null);

    /// <summary>
    /// 根据标识符获取已创建的PLC通信器。
    /// </summary>
    IPlcCommunicator GetCommunicator(string id);

    /// <summary>
    /// 移除并释放指定PLC通信器。
    /// </summary>
    bool RemoveCommunicator(string id);

    /// <summary>
    /// 获取所有已创建的PLC通信器。
    /// </summary>
    IReadOnlyList<IPlcCommunicator> GetAllCommunicators();

    /// <summary>
    /// 当任何PLC通信器的状态发生变化时触发。
    /// </summary>
    event EventHandler<PlcConnectionStateChangedEventArgs> CommunicatorStateChanged;
}

9. 总结

本文档定义了一套标准化的PLC通信管理接口,涵盖了从连接配置、核心通信方法到高级管理器的完整层次。该设计支持串口、以太网等传输方式,并针对Modbus和三菱MC协议提供了扩展接口。通过统一的 IPlcCommunicator 接口,上层应用可以以相同的方式操作不同品牌的PLC,极大地提升了代码的可维护性和可扩展性。在WPF项目中,可结合MVVM模式轻松实现PLC状态的实时监控和交互。