IPacker 接口 - Snet Docs

🧩 IPacker 接口

命名空间: Snet.Model.@interface | 接口: IPacker | 成员: 6 个方法(同步 + 异步)

IPacker地址自动组包与解包能力接口。每个数采驱动都通过 IDaq 实现它,因此在驱动实例上即可直接组包、解包——无需手动装配处理器。

public interface IPacker
{
    OperateResult Packer(Address? address, string protocolTypeKey, int maxByteLength = 0, DataFormat format = DataFormat.ABCD);
    Task<OperateResult> PackerAsync(Address? address, string protocolTypeKey, int maxByteLength = 0, DataFormat format = DataFormat.ABCD, CancellationToken token = default);
    OperateResult UnPacker(AddressValue addressValue, bool isStringReverseByteWord = false);
    Task<OperateResult> UnPackerAsync(AddressValue addressValue, bool isStringReverseByteWord = false, CancellationToken token = default);
    OperateResult UnPacker(ConcurrentDictionary<string, AddressValue> pairs, bool isStringReverseByteWord = false);
    Task<OperateResult> UnPackerAsync(ConcurrentDictionary<string, AddressValue> pairs, bool isStringReverseByteWord = false, CancellationToken token = default);
}

接口层次结构

IPacker 是组成 IDaq 的 15 个组件接口之一——IDaq : ... IClone, IPacker, IDisposable, IAsyncDisposable。由 DaqAbstract<,>(全部 36+ 协议驱动的基类)实现,内部委托 PackerHandler(组包)与 BytesHandler(解包)。

成员参考

Packer — 智能地址自动组包

成员 签名 描述
Packer OperateResult Packer(Address? address, string protocolTypeKey, int maxByteLength = 0, DataFormat format = DataFormat.ABCD) 将地址集优化为最小批量读取结构
PackerAsync Task<OperateResult> PackerAsync(Address? address, string protocolTypeKey, int maxByteLength = 0, DataFormat format = DataFormat.ABCD, CancellationToken token = default) 异步变体

参数:

参数 描述
address 原始地址集合
protocolTypeKey 供应商 ProtocolType 枚举的字符串名——如 "SiemensS7Net_S1200""ModbusTcpNet""OmronFinsNet"。接受各供应商数据类中 ProtocolType.ToString() 的返回值
maxByteLength 单次批量读取最大字节数。0 = 自动使用协议上限(推荐)。也可以使用调试工具直接读取得知最大字节数
format 数据字节序格式

返回ResultData 负载):协议族支持组包 → 优化后的 Address;不支持 → 原样返回原始地址。传入 null 返回 null。永不抛异常——结果始终是 OperateResult

UnPacker — 自动解包

成员 签名 描述
UnPacker OperateResult UnPacker(AddressValue addressValue, bool isStringReverseByteWord = false) 解包单个组包批次,返回以地址名为键的 ConcurrentDictionary<string, AddressValue>
UnPackerAsync Task<OperateResult> UnPackerAsync(AddressValue addressValue, bool isStringReverseByteWord = false, CancellationToken token = default) 异步变体
UnPacker OperateResult UnPacker(ConcurrentDictionary<string, AddressValue> pairs, bool isStringReverseByteWord = false) 解包一次读取结果的全部批次,返回 List<ConcurrentDictionary<string, AddressValue>>
UnPackerAsync Task<OperateResult> UnPackerAsync(ConcurrentDictionary<string, AddressValue> pairs, bool isStringReverseByteWord = false, CancellationToken token = default) 异步变体

参数:

参数 描述
isStringReverseByteWord String 解包时是否按 16 位字反转字节(每 2 字节一组交换)。连接级配置——如欧姆龙 FINS 的字符串按字反转字节读取。默认 false
重要

输入必须来自组包后的读取。组包时为每个批次附加特定参数(AddressExtendParam 持有各地址的 BytesModel 列表);UnPacker 据此将批次的原始字节解析回各地址的值。对非组包数据解包会失败并返回明确的错误信息。

快速入门

using Snet.Siemens;
using Snet.Model.data;
using Snet.Model.@enum;
using Snet.Model.@interface;   // IPacker

var op = await SiemensOperate.InstanceAsync(new SiemensData.Basics
{
    IpAddress = "192.168.1.100",
    Port = 102
});

// 1) 组包:将分散地址合并为最少的批量读取
var address = new Address(new List<AddressDetails>
{
    new("Reading", DataType.Float),
    new("Reading 2", DataType.Float),
    new("Reading 3", DataType.Int),
    new("Reading 4", DataType.Bool)
});
OperateResult packed = await op.PackerAsync(address, "SiemensS7Net_S1200");
if (!packed.Status) return;                                   // 组包失败 / 协议不支持
var packedAddr = packed.GetSource<Address>();                 // ResultData = 优化后的 Address

// 2) 一次往返读取组包后的批次
OperateResult result = await op.ReadAsync(packedAddr);
if (!result.Status) return;                                   // 读取失败
var data = result.GetSource<ConcurrentDictionary<string, AddressValue>>();

// 3) 解包:将每个批次的原始字节解析回各地址的值
OperateResult unpacked = await op.UnPackerAsync(data);
if (!unpacked.Status) return;                                 // 解包失败
var values = unpacked.GetSource<List<ConcurrentDictionary<string, AddressValue>>>();
foreach (var dict in values)
    foreach (var v in dict)
        Console.WriteLine($"{v.Key} = {v.Value.ResultValue}");

解包单个批次

持有单个批次的 AddressValue 时(如来自订阅或事件负载),使用单值重载:

OperateResult unpacked = await op.UnPackerAsync(kv.Value);   // kv.Value = 一个组包批次
if (!unpacked.Status) return;                                 // 解包失败
var values = unpacked.GetSource<ConcurrentDictionary<string, AddressValue>>();
提示

GetSource<T>()OperateResult 的成员方法(继承自 ResultModel)——无参,自动把结果的 ResultData 解包为 T。在 OperateResult 对象本身上调用(packed.GetSource<Address>()),不要直接对 packed.ResultData 调用;使用解包值前先检查 Status(操作失败时返回 default)。

透传行为

Packer 不会盲目优化——符号/标签寻址的协议原样返回:

  • SiemensS7Plus(符号访问)
  • MelsecCipNet(标签访问)
  • OmronCipNet / OmronConnectedCipNet(标签访问)
  • OmronHostLinkCMode / OmronHostLinkCModeOverTcp(已不在组包器供应商映射表中——原样返回)

成功时结果 Message"组包成功",解包为 "解包成功"

底层机制

组件 角色
DaqAbstract.packerHandler 公共字段——Packer 使用的 PackerHandler 单例
DaqAbstract.bytesHandler 公共字段——UnPacker 使用的 BytesHandler 单例
Snet.Core.packer.IPackerCore 底层按协议实现的组包引擎(每个协议族一个实现)

引擎细节、受支持的协议族与 maxByteLength 语义:地址自动组包

相关资源