KupaKuper_EthernetWrapper 2.2.5

dotnet add package KupaKuper_EthernetWrapper --version 2.2.5
                    
NuGet\Install-Package KupaKuper_EthernetWrapper -Version 2.2.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="KupaKuper_EthernetWrapper" Version="2.2.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="KupaKuper_EthernetWrapper" Version="2.2.5" />
                    
Directory.Packages.props
<PackageReference Include="KupaKuper_EthernetWrapper" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add KupaKuper_EthernetWrapper --version 2.2.5
                    
#r "nuget: KupaKuper_EthernetWrapper, 2.2.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package KupaKuper_EthernetWrapper@2.2.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=KupaKuper_EthernetWrapper&version=2.2.5
                    
Install as a Cake Addin
#tool nuget:?package=KupaKuper_EthernetWrapper&version=2.2.5
                    
Install as a Cake Tool

BaseEthernet 类使用文档

概述

BaseEthernet 是一个抽象类,为以太网通信提供基础功能,主要用于与 PLC 等设备进行连接、数据读写和心跳检测。该类定义了连接管理、数据读写的标准接口,子类需实现具体的通信协议(如 OPC UA、Modbus TCP 等)。

命名空间: KupaKuper_EthernetWrapper.Ethernet

功能特性

  • 连接管理: 自动重连机制、连接状态监控
  • 数据读写: 支持多种数据类型、批量读写操作
  • 心跳检测: 自动心跳检测确保连接稳定性
  • 线程安全: 内置锁机制防止并发冲突
  • 错误处理: 完善的异常处理和重试机制

类结构详解

连接管理

属性
Connected
public bool Connected { get; protected set; }
  • 描述: 获取当前连接状态,设置时触发 ConnectChanged 事件
  • 线程安全: 使用锁机制确保线程安全
  • 访问权限: 读/写(protected set)
ReconnectTime
public int ReconnectTime = 1000;
  • 描述: 重连间隔时间(毫秒),默认值为 1000
  • 类型: int
  • 访问权限: 读/写
方法
Reconnect()
public virtual async Task Reconnect()
  • 描述: 重新连接设备,包含锁定机制防止重复重连
  • 返回值: Task
  • 访问权限: public virtual
  • 实现逻辑:
    1. 检查是否正在重连,避免重复操作
    2. 关闭当前连接
    3. 建立新连接
    4. 重置重连状态
CloseAsync()
public abstract Task CloseAsync()
  • 描述: 关闭连接,子类必须实现
  • 返回值: Task
  • 访问权限: public abstract
ConnectAsync()
public abstract Task ConnectAsync()
  • 描述: 连接 PLC,子类必须实现
  • 返回值: Task
  • 访问权限: public abstract
事件
ConnectChanged
public Action<bool>? ConnectChanged { get; set; }
  • 描述: 连接状态改变时触发的事件
  • 参数: bool - 新的连接状态(true 表示已连接,false 表示断开连接)
  • 使用示例:
ethernet.ConnectChanged += (isConnected) =>
{
    if (isConnected)
    {
        Console.WriteLine("设备连接成功");
        // 连接成功后的处理逻辑
    }
    else
    {
        Console.WriteLine("设备连接断开");
        // 连接断开后的处理逻辑
    }
};

数据读写

抽象方法(子类必须实现)
ReadNode<T>(string Adr)
public abstract T? ReadNode<T>(string Adr)
  • 描述: 读取变量地址的底层方法
  • 类型参数: T - 返回值类型
  • 参数: Adr - 变量地址
  • 返回值: T? - 读取的值,可为 null
ReadNodes<T>(List<string> Adrs)
public abstract T? ReadNodes<T>(List<string> Adrs)
  • 描述: 读取变量地址列表的底层方法
  • 类型参数: T - 返回值类型
  • 参数: Adrs - 变量地址列表
  • 返回值: T? - 读取的值,可为 null
WriteNode(string trg, object value)
public abstract void WriteNode(string trg, object value)
  • 描述: 写入变量地址的底层方法
  • 参数:
    • trg - 目标变量地址
    • value - 要写入的值
虚方法(可重写)
Read(string trg)
public virtual object? Read(string trg)
  • 描述: 读取单个变量内容,处理数组类型转换
  • 参数: trg - 变量地址
  • 返回值: object? - 读取的值,可为 null
  • 功能特性:
    • 自动检测连接状态
    • 支持数组类型自动转换
    • 处理空值情况
Read(List<string> trgs)
public virtual object? Read(List<string> trgs)
  • 描述: 读取一列变量内容
  • 参数: trgs - 变量地址列表
  • 返回值: object? - 读取的值,可为 null
Read<T>(string trg)
public virtual T? Read<T>(string trg)
  • 描述: 读取指定类型的变量
  • 类型参数: T - 返回值类型
  • 参数: trg - 变量地址
  • 返回值: T? - 读取的值,可为 null
ReadString(string trg, string encoding = "UTF-8")
public virtual string ReadString(string trg, string encoding = "UTF-8")
  • 描述: 读取字符串变量并指定编码格式
  • 参数:
    • trg - 变量地址
    • encoding - 编码格式,默认为 "UTF-8"
  • 返回值: string - 读取的字符串
  • 支持编码: UTF-8、GB2312、ASCII 等
Write(string trg, object value)
public virtual void Write(string trg, object value)
  • 描述: 修改变量内容
  • 参数:
    • trg - 变量地址
    • value - 要写入的值
Try 方法(安全操作)
TryRead(string trg, out object? value)
public bool TryRead(string trg, out object? value)
  • 描述: 尝试读取变量,返回是否成功
  • 参数:
    • trg - 变量地址
    • value - 输出参数,读取的值
  • 返回值: bool - 是否成功读取
TryRead(List<string> trg, out object? value)
public bool TryRead(List<string> trg, out object? value)
  • 描述: 尝试读取一列变量,返回是否成功
  • 参数:
    • trg - 变量地址列表
    • value - 输出参数,读取的值
  • 返回值: bool - 是否成功读取
TryReadString(string trg, string encoding, out object? value)
public bool TryReadString(string trg, string encoding, out object? value)
  • 描述: 尝试读取字符串变量,返回是否成功
  • 参数:
    • trg - 变量地址
    • encoding - 编码格式
    • value - 输出参数,读取的值
  • 返回值: bool - 是否成功读取
TryRead<T>(string trg, out T? value)
public bool TryRead<T>(string trg, out T? value)
  • 描述: 尝试读取指定类型变量,返回值和成功状态
  • 类型参数: T - 返回值类型
  • 参数:
    • trg - 变量地址
    • value - 输出参数,读取的值
  • 返回值: bool - 是否成功读取
TryWrite(string trg, object value)
public bool TryWrite(string trg, object value)
  • 描述: 尝试修改变量内容,返回是否成功
  • 参数:
    • trg - 变量地址
    • value - 要写入的值
  • 返回值: bool - 是否成功写入

心跳检测

字段
_heartbeatWriteState
private bool _heartbeatWriteState = true;
  • 描述: 心跳写入状态跟踪变量(布尔类型)
  • 类型: bool
  • 初始值: true
_heartbeatNumericState
private int _heartbeatNumericState = 1;
  • 描述: 心跳写入状态跟踪变量(数值类型)
  • 类型: int
  • 初始值: 1
_isHeartbeatBoolType
private bool _isHeartbeatBoolType = true;
  • 描述: 心跳类型标志,默认为 bool 类型
  • 类型: bool
  • 初始值: true
方法
OpenConnect(string ClientUrl, string HeartbeatAddress)
public void OpenConnect(string ClientUrl, string HeartbeatAddress)
  • 描述: 启动连接监控和心跳检测
  • 参数:
    • ClientUrl - 客户端 URL 地址
    • HeartbeatAddress - 心跳检测变量地址
  • 功能特性:
    • 自动检测连接状态
    • 定时执行心跳检测
    • 自动重连机制
    • 智能数据类型检测

使用说明

创建子类实现

要使用 BaseEthernet,首先需要创建一个继承自它的子类,并实现所有抽象方法:

using KupaKuper_EthernetWrapper.Ethernet;

public class MyEthernet : BaseEthernet
{
    private readonly object _connectionLock = new object();
    private bool _isConnected = false;

    public MyEthernet()
    {
        // 初始化逻辑
    }

    public override async Task CloseAsync()
    {
        lock (_connectionLock)
        {
            if (!_isConnected) return;
            
            // 实现关闭连接的具体逻辑
            // 例如:关闭网络连接、释放资源等
            
            _isConnected = false;
            Connected = false; // 触发连接状态变化事件
        }
        await Task.CompletedTask;
    }

    public override async Task ConnectAsync()
    {
        lock (_connectionLock)
        {
            if (_isConnected) return;
            
            try
            {
                // 实现连接逻辑
                // 例如:建立网络连接、验证身份等
                
                _isConnected = true;
                Connected = true; // 触发连接状态变化事件
            }
            catch (Exception ex)
            {
                _isConnected = false;
                Connected = false;
                throw new Exception($"连接失败: {ex.Message}");
            }
        }
        await Task.CompletedTask;
    }

    public override T? ReadNode<T>(string Adr)
    {
        if (!Connected) return default;
        
        try
        {
            // 实现单个节点读取的具体逻辑
            // 根据具体协议实现数据读取
            
            // 示例:返回模拟数据
            if (typeof(T) == typeof(bool))
                return (T)(object)true;
            else if (typeof(T) == typeof(int))
                return (T)(object)123;
            else if (typeof(T) == typeof(string))
                return (T)(object)"Hello World";
            
            return default;
        }
        catch (Exception ex)
        {
            throw new Exception($"读取节点失败: {ex.Message}");
        }
    }

    public override T? ReadNodes<T>(List<string> Adrs)
    {
        if (!Connected) return default;
        
        try
        {
            // 实现多节点读取的具体逻辑
            // 根据具体协议实现批量数据读取
            
            // 示例:返回模拟数据数组
            if (typeof(T) == typeof(bool[]))
                return (T)(object)new bool[] { true, false, true };
            else if (typeof(T) == typeof(int[]))
                return (T)(object)new int[] { 1, 2, 3 };
            
            return default;
        }
        catch (Exception ex)
        {
            throw new Exception($"批量读取节点失败: {ex.Message}");
        }
    }

    public override void WriteNode(string trg, object value)
    {
        if (!Connected) return;
        
        try
        {
            // 实现写入节点的具体逻辑
            // 根据具体协议实现数据写入
            
            Console.WriteLine($"写入地址 {trg} 值: {value}");
        }
        catch (Exception ex)
        {
            throw new Exception($"写入节点失败: {ex.Message}");
        }
    }
}

初始化与连接

// 创建实例
var ethernet = new MyEthernet();

// 设置重连间隔(毫秒)
ethernet.ReconnectTime = 2000; // 2秒

// 注册连接状态变化事件
ethernet.ConnectChanged += (isConnected) =>
{
    if (isConnected)
    {
        Console.WriteLine("设备连接成功");
        // 连接成功后的初始化操作
        InitializeAfterConnection();
    }
    else
    {
        Console.WriteLine("设备连接断开");
        // 连接断开后的清理操作
        CleanupAfterDisconnection();
    }
};

// 启动连接监控和心跳检测
string clientUrl = "192.168.1.100:502"; // PLC地址
string heartbeatAddress = "DB1.DBX0.0"; // 心跳变量地址
ethernet.OpenConnect(clientUrl, heartbeatAddress);

// 手动连接(可选)
await ethernet.ConnectAsync();

数据读写操作

读取数据
// 读取布尔值
bool? boolValue = ethernet.Read<bool>("DB1.DBX0.0");
if (boolValue.HasValue)
{
    Console.WriteLine($"布尔值: {boolValue.Value}");
}

// 读取整数
int? intValue = ethernet.Read<int>("DB1.DBW2.0");
if (intValue.HasValue)
{
    Console.WriteLine($"整数值: {intValue.Value}");
}

// 读取浮点数
float? floatValue = ethernet.Read<float>("DB1.DBD4.0");
if (floatValue.HasValue)
{
    Console.WriteLine($"浮点值: {floatValue.Value}");
}

// 读取字符串
string strValue = ethernet.ReadString("DB1.DBB8.0", "UTF-8");
Console.WriteLine($"字符串值: {strValue}");

// 读取数组
int[]? arrayValue = ethernet.Read<int[]>("DB1.DBB12.0");
if (arrayValue != null)
{
    Console.WriteLine($"数组值: {string.Join(", ", arrayValue)}");
}

// 安全读取(推荐)
if (ethernet.TryRead<int>("DB1.DBW2.0", out int safeIntValue))
{
    Console.WriteLine($"安全读取整数值: {safeIntValue}");
}
else
{
    Console.WriteLine("读取失败");
}

// 批量读取
var addresses = new List<string> 
{ 
    "DB1.DBX0.0", 
    "DB1.DBW2.0", 
    "DB1.DBD4.0" 
};

if (ethernet.TryRead(addresses, out object? batchResult))
{
    Console.WriteLine($"批量读取结果: {batchResult}");
}
写入数据
// 写入布尔值
ethernet.Write("DB1.DBX0.0", true);

// 写入整数
ethernet.Write("DB1.DBW2.0", 123);

// 写入浮点数
ethernet.Write("DB1.DBD4.0", 3.14f);

// 写入字符串
string message = "Hello PLC";
byte[] stringBytes = Encoding.UTF8.GetBytes(message);
ethernet.Write("DB1.DBB8.0", stringBytes);

// 写入数组
int[] dataArray = { 1, 2, 3, 4, 5 };
ethernet.Write("DB1.DBB12.0", dataArray);

// 安全写入(推荐)
if (ethernet.TryWrite("DB1.DBW2.0", 456))
{
    Console.WriteLine("写入成功");
}
else
{
    Console.WriteLine("写入失败");
}

高级用法

自定义心跳检测

// 自定义心跳检测逻辑
public class CustomEthernet : BaseEthernet
{
    public override void OpenConnect(string ClientUrl, string HeartbeatAddress)
    {
        // 自定义心跳检测间隔
        ReconnectTime = 3000; // 3秒
        
        // 调用基类实现
        base.OpenConnect(ClientUrl, HeartbeatAddress);
    }
    
    // 其他实现...
}

批量操作优化

// 批量读写优化示例
public async Task BatchOperationExample()
{
    var ethernet = new MyEthernet();
    
    // 批量读取多个变量
    var readAddresses = new List<string>
    {
        "DB1.DBX0.0",
        "DB1.DBW2.0", 
        "DB1.DBD4.0",
        "DB1.DBB8.0"
    };
    
    if (ethernet.TryRead(readAddresses, out object? readResults))
    {
        // 处理批量读取结果
        ProcessBatchResults(readResults);
    }
    
    // 批量写入多个变量
    var writeOperations = new Dictionary<string, object>
    {
        ["DB1.DBX0.0"] = true,
        ["DB1.DBW2.0"] = 100,
        ["DB1.DBD4.0"] = 2.718f
    };
    
    foreach (var operation in writeOperations)
    {
        if (ethernet.TryWrite(operation.Key, operation.Value))
        {
            Console.WriteLine($"写入 {operation.Key} 成功");
        }
    }
}

错误处理与重试机制

public async Task RobustOperationExample()
{
    var ethernet = new MyEthernet();
    
    // 带重试的读取操作
    int retryCount = 3;
    for (int i = 0; i < retryCount; i++)
    {
        try
        {
            if (ethernet.TryRead<int>("DB1.DBW2.0", out int value))
            {
                Console.WriteLine($"读取成功: {value}");
                break;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"第 {i + 1} 次读取失败: {ex.Message}");
            
            if (i == retryCount - 1)
            {
                // 最后一次重试失败,执行重连
                await ethernet.Reconnect();
            }
            
            await Task.Delay(1000); // 等待1秒后重试
        }
    }
}

最佳实践

1. 连接管理

  • 连接检查: 在执行操作前检查 Connected 状态
  • 事件处理: 合理使用 ConnectChanged 事件处理连接状态变化
  • 资源释放: 及时调用 CloseAsync() 释放资源

2. 数据读写

  • 安全操作: 优先使用 Try 系列方法进行安全操作
  • 批量优化: 对多个相关变量使用批量读写操作
  • 类型匹配: 确保读写的数据类型与变量定义匹配

3. 错误处理

  • 异常捕获: 对关键操作进行异常捕获
  • 重试机制: 实现合理的重试逻辑
  • 日志记录: 记录重要的操作和错误信息

4. 性能优化

  • 连接复用: 避免频繁创建和销毁连接
  • 批量操作: 减少单次操作次数
  • 心跳优化: 根据实际需求调整心跳检测间隔

常见问题

Q: 连接状态不更新怎么办?

A: 确保在子类的 ConnectAsync() 和 CloseAsync() 方法中正确设置 Connected 属性

Q: 数据读取返回 null 是什么原因?

A: 可能的原因包括:连接断开、变量地址错误、权限不足、数据类型不匹配等

Q: 如何实现自定义协议?

A: 创建继承自 BaseEthernet 的子类,实现所有抽象方法,根据具体协议实现通信逻辑

Q: 心跳检测失败如何处理?

A: 心跳检测失败会自动触发重连机制,也可以通过 ConnectChanged 事件进行自定义处理

Q: 如何优化大量数据的读写性能?

A: 使用批量读写方法,合理设置操作间隔,避免频繁的小数据包传输

版本信息

  • 当前版本: 1.0
  • 目标框架: .NET Standard 2.0+
  • 依赖项: KupaKuper_HelpClass
  • 兼容性: 支持多种以太网通信协议

本文档基于 BaseEthernet 类实际实现编写,具体使用请参考实际代码和具体协议实现。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on KupaKuper_EthernetWrapper:

Package Downloads
KupaKuper_HMI_Config

KupaKuper_HMI_Device的支持包,主要包含配置文件读取和解析,提供数据模型和结构

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.5 563 7/13/2026
2.2.4 411 4/21/2026
2.2.3 444 3/24/2026
2.2.2 171 3/21/2026
2.2.1-beta 193 3/16/2026
2.1.1 279 2/28/2026
2.0.1 567 8/28/2025
2.0.0 329 8/26/2025
1.2.1 271 8/26/2025
1.2.0 350 8/25/2025
1.2.0-beta 224 8/22/2025
1.1.2-beta 201 8/2/2025
1.1.0-beta 123 8/2/2025
1.0.0 292 7/28/2025

对于Opc不能直接读取WString类型的问题,可以支持使用ReadString来读取byte数组实现Wstring的读取