ProtocolConversion.Core 0.1.1

ProtocolConversion — 协议转换库

基于 .NET 10 / C# 的协议转换类库:将一种协议的消息翻译转换为另一种协议的消息,以类库形式提供,可方便地集成到其他系统中。

支持协议:SECS/GEM(基于 Secs4Net)、HTTP、Rpc(gRPC), 支持通过 Redis / RabbitMQ 等发布订阅中间件进行跨进程消息传递,支持 EF Core + MySQL 消息流水存储,支持在一个进程中创建 多个转换实例。

需求对照

需求 实现
协议翻译(协议 A ↔ 协议 B) 协议适配器 + 统一消息模型 ConversionMessage + 路由管道
以类库形式提供 多项目解决方案,NuGet 风格包结构 + DI 扩展
跨进程通讯(Redis、RabbitMQ 等发布订阅) IMessageBus 抽象,独立扩展包 + Options 配置,新增中间件零侵入
翻译层支持用户按条件自定义翻译 翻译规则引擎:条件谓词 + 自定义翻译器 + 内置映射翻译器
支持 SECS/GEM、HTTP、Rpc IProtocolAdapter 抽象 + 各协议独立适配器包
支持创建多个实例 IProtocolConversionManager 实例管理器,实例间完全隔离
数据落地(来回数据可存储),EF + MySQL EF Core + Pomelo MySQL,收/译/发/失败全阶段流水

架构

[协议A 端点] ──► AdapterA(收) ──► 翻译层(规则匹配) ──► MessageBus(跨进程发布/订阅) ──► AdapterB(发) ──► [协议B 端点]
                        │                  │                        │
                        └──────────── 消息流水存储(EF Core / MySQL)◄┘
                          Received / Translated / Sent / Failed 全阶段留痕

项目结构

ProtocolConversion.slnx
├── src/
│   ├── ProtocolConversion.Abstractions        # 核心抽象:统一消息模型、适配器/总线/翻译/存储接口
│   ├── ProtocolConversion.Core                # 翻译引擎、路由管道、实例管理器、DI 扩展、进程内总线/存储
│   ├── ProtocolConversion.Bus.Redis           # Redis 发布订阅总线
│   ├── ProtocolConversion.Bus.RabbitMQ        # RabbitMQ 发布订阅总线
│   ├── ProtocolConversion.Persistence.MySql   # EF Core + MySQL 消息流水存储
│   ├── ProtocolConversion.Protocol.Http       # HTTP 适配器(入站监听 / 出站调用)
│   ├── ProtocolConversion.Protocol.Rpc        # gRPC 适配器(服务端 / 客户端)
│   └── ProtocolConversion.Protocol.SecsGem    # SECS/GEM 适配器(Secs4Net,HSMS + SECS-II)
├── tests/ProtocolConversion.Tests             # 单元测试与端到端测试
└── samples/
    ├── ProtocolConversion.Sample              # HTTP 翻译 + 跨进程发布示例
    └── ProtocolConversion.SecsGemSample       # SECS/GEM 协议转换示例(含设备模拟器)

快速开始

1. 引入与注册

using ProtocolConversion.Core;
using ProtocolConversion.Core.Instances;
using ProtocolConversion.Protocol.Http;
using ProtocolConversion.Protocol.SecsGem;
using ProtocolConversion.Bus.Redis;
using ProtocolConversion.Persistence.MySql;

var services = new ServiceCollection();
services.AddProtocolConversion();                    // 注册实例管理器
// 或自行创建:var manager = new ProtocolConversionManager();

2. 创建转换实例(HTTP → SECS/GEM 翻译示例)

var instance = await manager.CreateAsync("line-1", builder => builder

    // 跨进程消息总线(Redis / RabbitMQ / 进程内)
    .UseRedisBus(o => o.ConnectionString = "localhost:6379")

    // 消息流水存储(EF Core + MySQL,收发数据全阶段落地)
    .UseMySqlStore(o => o.ConnectionString = "Server=localhost;Database=protocol_conversion;User=root;Password=***;")

    // 协议适配器
    .AddHttpInbound("http-in", o => { o.ListenUrl = "http://localhost:8080"; o.Path = "/conversion"; })
    .AddSecsGem("gem", o => { o.IpAddress = "127.0.0.1"; o.Port = 5000; o.IsActive = true; })

    // 翻译路由:HTTP 请求 → 按条件翻译 → 发送到 SECS/GEM
    .AddRoute("http-to-gem", "http-in", "gem", route => route

        // 条件规则:按来源协议 / 消息头 / 负载任意条件匹配,首个命中生效
        .When(
            m => m.GetHeader("SECS.SF") == "S1F3",
            new JsonFieldMappingTranslator(new Dictionary<string, string>
            {
                ["$.lotId"] = "$.body.lot_no",       // JSON 字段按路径搬移
                ["$.quantity"] = "$.body.qty",
            }))

        // 自定义翻译器(实现 IMessageTranslator)
        .When(m => m.SourceProtocol == "SECS/GEM", new MySecsToHttpTranslator())

        // 兜底翻译 + 未命中行为
        .Use(new MyDefaultTranslator(), priority: 100)
        .OnUnmatched(UnmatchedMessageBehavior.PassThrough))

    // 跨进程路由:消息发布到总线主题(其他进程可订阅消费)
    .AddRoute("http-to-bus", "http-in", "topic:converted-messages"));

await instance.StartAsync();   // 启动全部适配器并激活路由

3. 多实例管理

var instanceA = await manager.CreateAsync("line-a", builder => /* ... */);
var instanceB = await manager.CreateAsync("line-b", builder => /* ... */);
await manager.StartAllAsync();
await manager.DestroyAsync("line-a");          // 销毁实例

每个实例拥有独立的适配器、路由、总线通道与存储配置,实例之间互不影响。

核心概念

统一消息模型 ConversionMessage

所有协议消息都会被归一化为统一消息:

字段 说明
MessageId / CorrelationId 消息标识 / 请求-应答关联标识
Direction Inbound(接收)/ Outbound(发送)
SourceProtocol / TargetProtocol 来源协议 / 目标协议
Headers 协议元数据(HTTP 头、SECS S/F、RPC 信息等)
Payload / PayloadText / PayloadAsJson() 字节负载 / 文本 / JSON 访问

常用消息头前缀:http.header.*(HTTP 头)、SECS.Stream / SECS.Function / SECS.SF(SECS)、rpc.method(gRPC)。

协议适配器

适配器 扩展方法 说明
HTTP 入站 AddHttpInbound(name, o => ...) Kestrel 监听;请求/应答模式:翻译后的消息作为 HTTP 应答返回(超时返回 202)
HTTP 出站 AddHttpOutbound(name, o => ...) 发送 HTTP 请求;响应可再触发 MessageReceived 形成来回转换
gRPC 入站 AddGrpcInbound(name, o => ...) 托管 gRPC 服务(Send 一元 / SendStream 双向流)
gRPC 出站 AddGrpcOutbound(name, o => ...) 通过 RPC 调用发送到远端服务
SECS/GEM AddSecsGem(name, o => ...) HSMS(SEMI E37)+ SECS-II;Primary 消息转入管道,应答(Secondary)自动回给对端

SECS/GEM 负载编码:默认为 JSON 项树({"format":"ASCII","value":"..."}、{"format":"List","items":[...]}), 便于其他协议直接消费 SECS 数据;设置 UseSmlPayload = true 可使用 SML 文本编码。 SECS 与统一消息的互转由 SecsMessageConverter 完成,可在自定义翻译中直接复用。

消息总线(跨进程发布/订阅)

路由端点写成 topic:主题名 即为总线端点,例如:

.AddRoute("a", "http-in", "topic:orders")      // 发布到总线
.AddRoute("b", "topic:orders", "gem")          // 从总线订阅
总线 扩展方法 说明
Redis UseRedisBus(o => ...) / AddRedisMessageBus(...) PUB/SUB,可配置频道前缀
RabbitMQ UseRabbitMqBus(o => ...) / AddRabbitMqMessageBus(...) topic 交换机,每个订阅者独立队列
进程内 new InMemoryMessageBus() 单进程部署 / 开发调试 / 测试

新增其他中间件:实现 IMessageBus 两个方法(PublishAsync / SubscribeAsync)并提供扩展方法即可,核心库零改动。

翻译层

规则按 Priority 升序匹配,首个命中生效:

.AddRoute("r", "in", "out", route => route
    // 条件 + 自定义翻译器(实现 IMessageTranslator)
    .When(m => m.SourceProtocol == "SECS/GEM", new MyTranslator(), priority: 0)
    // 条件 + 委托
    .When(m => m.GetHeader("KIND") == "A", m => m.WithPayload("..."u8.ToArray()))
    // 兜底
    .Use(new DefaultTranslator(), priority: 100)
    // 未命中行为:PassThrough(透传)/ Drop(丢弃)/ Error(记失败)
    .OnUnmatched(UnmatchedMessageBehavior.PassThrough));

也可以用 Rule.When(...) 构建独立规则对象复用:

var rule = Rule.WhenHeader("SECS.SF", "S1F3")
               .WithPriority(10)
               .TranslateUsing(new MyTranslator())
               .Build();

内置翻译器:

  • JsonFieldMappingTranslator — JSON 字段按路径搬移("$.lotId" → "$.body.lot_no")
  • HeaderMappingTranslator — 消息头改名映射
  • DelegateTranslator — 委托包装

自定义翻译器:实现 IMessageTranslator.TranslateAsync 即可,可注入任意服务(数据库、规则引擎、AI 服务等)。

错误应答:翻译/转发失败时,若消息需要应答(CorrelationId 存在且来源为适配器), 管道会向请求方回发带 conversion.error 消息头的错误应答(HTTP 返回 500 + 错误详情),避免调用方等待超时。

消息流水存储(EF Core + MySQL)

.UseMySqlStore(o => o.ConnectionString = "Server=localhost;Database=protocol_conversion;User=root;Password=***;")
// 或 services.AddMySqlMessageStore(o => ...);
  • 管道的 Received / Translated / Sent / Failed 各阶段均写入 conversion_messages 表
  • 默认自动建表(AutoCreateSchema),可通过 ServerVersion 指定 MySQL 版本
  • 查询接口 IMessageStore.QueryAsync(MessageQuery):按实例、路由、消息 ID、关联 ID、阶段、来源协议、时间范围过滤
  • 接入其他数据库:实现 IMessageStore 或复用 ConversionDbContext(换任意 EF Core Provider)

扩展指南

扩展点 接口 接入方式
新协议 IProtocolAdapter(可继承 ProtocolAdapterBase) 新建适配器包 + AddXxx(...) 扩展方法
新消息中间件 IMessageBus 新建总线包 + UseXxxBus(...) 扩展方法
自定义翻译 IMessageTranslator / ITranslationRule 注册到路由规则
新存储 IMessageStore UseMessageStore(...) 或 DI 注册

示例与测试

示例 1:HTTP ↔ 翻译 ↔ 跨进程发布(samples/ProtocolConversion.Sample)

# 运行示例(默认 HTTP :8080,可用环境变量覆盖配置)
dotnet run --project samples/ProtocolConversion.Sample

# 发送测试请求
curl -X POST http://localhost:8080/conversion \
     -H "Content-Type: application/json" \
     -d '{"lotId":"LOT-1","quantity":5}'
# 应答:{"lotId":"LOT-1","quantity":5,"body":{"lot_no":"LOT-1","qty":5}}

示例支持通过 appsettings.json 或环境变量(Conversion__Http__ListenUrl、Conversion__MySql__ConnectionString、 Conversion__Redis__ConnectionString 等)配置 MySQL、Redis / RabbitMQ 与目标地址; 未配置外部服务时自动使用进程内总线与存储,开箱即用。

示例 2:SECS/GEM 协议转换(samples/ProtocolConversion.SecsGemSample)

完整演示 HTTP ↔ SECS/GEM 双向翻译,内置 设备模拟器(HSMS 被动方),无需真实设备即可运行:

HTTP 客户端 ──JSON──► HTTP 入站 ──翻译──► SECS/GEM 适配器 ──HSMS──► 设备模拟器
HTTP 客户端 ◄─JSON──  HTTP 应答 ◄─翻译──  SECS/GEM 适配器 ◄─S1F4──  设备模拟器

设备模拟器 ──S6F11 事件──► 适配器 ──翻译──► 总线主题 topic:secs.events(跨进程)
设备模拟器 ──S1F1 请求──► 转换管道自动应答 S1F2(设备发起的请求同样被转换处理)
# 启动(设备模拟器 + 转换实例,默认 HTTP :8081、HSMS :5000)
dotnet run --project samples/ProtocolConversion.SecsGemSample

# 查询设备状态(业务语义写法:{"svids":[...]})
curl -X POST http://localhost:8081/secs -H "Content-Type: application/json" \
     -d '{"svids":[1,2,3]}'
# 应答:{"sf":"S1F4","data":{"format":"L","items":[{"format":"U4","value":[2]},{"format":"F8","value":[28.78]},{"format":"A","value":"LOT-083"}]}}

# 查询设备状态(SECS 协议写法:直接指定 S/F 与项树)
curl -X POST http://localhost:8081/secs -H "Content-Type: application/json" \
     -d '{"sf":"S1F3","item":{"format":"L","items":[{"format":"U4","value":[1,2,3]}]}}'

# 查询设备常量(S2F13 → S2F14)
curl -X POST http://localhost:8081/secs -H "Content-Type: application/json" \
     -d '{"sf":"S2F13","item":{"format":"L","items":[{"format":"U2","value":[1,2]}]}}'

# AreYouThere(S1F1 → S1F2)
curl -X POST http://localhost:8081/secs -H "Content-Type: application/json" \
     -d '{"sf":"S1F1","item":{"format":"L","items":[]}}'

该示例演示的翻译层能力:

翻译器 作用
FindSvidRequestTranslator 业务语义 JSON {"svids":[...]} → SECS S1F3(条件规则优先匹配)
JsonToSecsTranslator 通用协议 JSON {"sf":"S1F3","item":{...}} → SECS 消息
SecsToJsonTranslator SECS 消息(含设备事件)→ 业务 JSON
AreYouThereAckTranslator 设备 S1F1 → 自动应答 S1F2(Primary Message 应答路由)

收发数据的来回全过程写入消息流水存储;配置 SecsGemSample__Redis__ConnectionString 可切换为 Redis 跨进程总线, 配置 SecsGemSample__MySql__ConnectionString 可切换为 MySQL 存储,SecsGemSample__LogLevel=Debug 可查看 SECS 报文细节。

运行测试

dotnet test tests/ProtocolConversion.Tests

打包发布(NuGet Package)

本库以 NuGet 包形式提供给其他系统集成:每个功能包独立打包,另提供元包 ProtocolConversion 一键引入全部能力(安装元包即传递引入所有子包)。

包名 内容
ProtocolConversion 元包:安装即包含以下全部功能
ProtocolConversion.Abstractions 统一消息模型与核心接口
ProtocolConversion.Core 翻译引擎、路由管道、多实例管理器、DI 扩展
ProtocolConversion.Protocol.SecsGem SECS/GEM 适配器(Secs4Net)
ProtocolConversion.Protocol.Http HTTP 适配器
ProtocolConversion.Protocol.Rpc gRPC 适配器
ProtocolConversion.Bus.Redis Redis 发布订阅总线
ProtocolConversion.Bus.RabbitMQ RabbitMQ 发布订阅总线
ProtocolConversion.Persistence.MySql EF Core + MySQL 消息流水存储

构建与打包

# 打包(生成 nupkg + snupkg 符号包到 artifacts/)
dotnet pack ProtocolConversion.slnx -c Release -o artifacts

# 指定版本号打包
dotnet pack ProtocolConversion.slnx -c Release -o artifacts -p:PackageVersion=1.2.0

版本号在 Directory.Build.props 的 <VersionPrefix> 统一维护;包元数据(作者、标签、 README、XML 文档)同样在 Directory.Build.props 中集中配置。

发布到 NuGet 仓库

# 发布到内网 NuGet 源(如 Azure Artifacts / NuGet.Server / BaGet 等)
dotnet nuget push artifacts/*.nupkg \
    --source https://your-internal-feed/v3/index.json \
    --api-key <YOUR_API_KEY>

其他系统如何使用

# 安装元包(获得全部功能)
dotnet add package ProtocolConversion

# 或按需只安装某个子包(如仅需 SECS/GEM 适配器)
dotnet add package ProtocolConversion.Protocol.SecsGem
using ProtocolConversion.Core;
using ProtocolConversion.Core.Instances;

services.AddProtocolConversion();   // 注册实例管理器,随后创建转换实例即可

提示:若内网仓库要求包许可证/仓库地址,可在 Directory.Build.props 中补充 <PackageLicenseExpression>、<RepositoryUrl>、<PackageProjectUrl> 后重新打包。

技术栈

  • .NET 10 / C#,Microsoft.Extensions.*(DI / Options / Logging)
  • Secs4Net 3.1 + Secs4Net.Sml(SECS/GEM)
  • Grpc.AspNetCore / Grpc.Net.Client(Rpc)
  • StackExchange.Redis、RabbitMQ.Client 7(跨进程消息总线)
  • Entity Framework Core 9 + Pomelo.EntityFrameworkCore.MySql(MySQL 存储)
  • xUnit(测试)

Showing the top 20 packages that depend on ProtocolConversion.Core.

Packages Downloads
ProtocolConversion
协议转换库(元包):将一种协议的消息翻译转换为另一种协议的消息。安装本包即包含全部功能:SECS/GEM(Secs4Net)、HTTP、Rpc(gRPC)协议适配器,Redis / RabbitMQ 跨进程发布订阅总线,EF Core + MySQL 消息流水存储,条件化翻译规则引擎与多实例管理。也可按需安装子包:ProtocolConversion.Protocol.SecsGem、ProtocolConversion.Protocol.Http、ProtocolConversion.Protocol.Rpc、ProtocolConversion.Bus.Redis、ProtocolConversion.Bus.RabbitMQ、ProtocolConversion.Persistence.MySql。
0
ProtocolConversion.Bus.RabbitMQ
RabbitMQ based publish/subscribe message bus provider for the protocol conversion library.
0
ProtocolConversion.Bus.Redis
Redis based publish/subscribe message bus provider for the protocol conversion library.
0
ProtocolConversion.Persistence.MySql
EF Core based message persistence (MySQL / Pomelo) for the protocol conversion library.
0
ProtocolConversion.Protocol.Http
HTTP protocol adapters (inbound listener and outbound caller) for the protocol conversion library.
0
ProtocolConversion.Protocol.Rpc
gRPC (Rpc) protocol adapters (inbound server and outbound client) for the protocol conversion library.
0
ProtocolConversion.Protocol.SecsGem
SECS/GEM protocol adapter (powered by Secs4Net) for the protocol conversion library.
0

Version Downloads Last updated
0.1.1 0 11/10/2026