EnerOS v0.36.0
发布日期:2026-05-02
版本代号:IoT
Git Tag:v0.36.0
支持状态:稳定(Stable)
Crate 总数:84(新增 6 个)
测试用例数:10700+(新增 700)
概述
EnerOS v0.36.0「IoT」是物联网泛在接入专题版本,将 EnerOS 的设备接入能力从传统 IEC 61850/SCADA 扩展到物联网协议体系,实现「源网荷储」全要素泛在接入。本版本使 EnerOS 能够接入百万级物联网设备,支撑智能配电网、分布式新能源、用户侧储能、电动汽车充电桩等新型设备的即插即用接入。
IoT 版本的核心设计哲学是「协议无关 + 设备影子」——上层应用不直接对接各种异构通信协议,而是通过统一的设备模型与设备影子进行交互。设备影子作为物理设备在内核中的数字代理,解耦了设备的在线状态与应用的访问需求:设备离线时,应用仍可读取影子中的最后已知状态;设备上线后,影子自动同步并追加离线期间的数据。
本版本引入五大核心能力:MQTT 协议支持、OPC UA 协议支持、设备影子引擎、批量设备管理、设备接入网关。所有能力均通过 eneros-iot、eneros-iot-mqtt、eneros-iot-opcua、eneros-iot-shadow、eneros-iot-batch 五个新 crate 实现。
关键数据
| 指标 | 数值 | 说明 |
|---|---|---|
| MQTT 并发连接 | 10 万 | 单节点 |
| OPC UA 设备接入 | 5 万 | 单节点 |
| 设备影子更新延迟 | 2ms | 单设备 |
| 批量配置下发 | 1 万台/秒 | 并行 |
| 新增 Crate | 6 | IoT 相关 |
| 新增测试 | 700+ | 含 150 个端到端 |
新特性
1. MQTT 协议支持
新增 eneros-iot-mqtt crate,提供高性能 MQTT 5.0 broker 与客户端,支持百万级设备并发接入。MQTT 是物联网领域事实标准,广泛应用于智能电表、充电桩、分布式光伏等设备。
MQTT Broker 配置
use eneros_iot_mqtt::{MqttBroker, BrokerConfig, AuthConfig};
let broker = MqttBroker::new(BrokerConfig {
listen: "0.0.0.0:1883".parse()?,
listen_tls: Some("0.0.0.0:8883".parse()?),
max_connections: 100_000,
max_packet_size: 256 * 1024,
auth: AuthConfig::Certificate {
ca: "/etc/eneros/ca.pem",
require_client_cert: true,
},
session_persistence: true,
retained_messages: 100_000,
}).await?;
// 启动 broker
broker.start().await?;
设备接入与数据流转
use eneros_iot_mqtt::{DeviceClient, TopicPattern};
// 设备侧:发布遥测数据
let client = DeviceClient::connect("mqtts://broker.eneros.io:8883").await?;
client.publish(
TopicPattern::telemetry("meter-001"),
json!({
"voltage": 220.3,
"current": 15.2,
"power": 3.35,
"timestamp": now_iso8601(),
}),
QoS::AtLeastOnce,
).await?;
// 平台侧:订阅设备数据流
let mut stream = broker.subscribe(TopicPattern::telemetry("+")).await?;
while let Some(msg) = stream.next().await {
let device_id = msg.topic.extract_device_id()?;
let telemetry: Telemetry = serde_json::from_slice(&msg.payload)?;
// 自动写入时序引擎
timeseries.write(device_id, telemetry).await?;
}
MQTT Topic 设计
| Topic 模式 | 用途 | QoS | 示例 |
|---|---|---|---|
| devices/{id}/telemetry | 遥测数据上报 | 1 | devices/meter-001/telemetry |
| devices/{id}/command | 命令下发 | 2 | devices/meter-001/command |
| devices/{id}/event | 事件上报 | 1 | devices/meter-001/event |
| devices/{id}/shadow | 影子更新 | 1 | devices/meter-001/shadow |
| devices/{id}/status | 在线状态 | 1 | devices/meter-001/status |
| broadcast/{topic} | 广播消息 | 0 | broadcast/ota-notice |
性能基准
| 指标 | 数值 | 说明 |
|---|---|---|
| 并发连接 | 10 万 | 单节点 |
| 消息吞吐 | 50 万/秒 | QoS 1 |
| 消息延迟 P99 | 3ms | 同节点 |
| 内存占用 | 1.2 GB | 10 万连接 |
| TLS 握手 | 8ms | 证书认证 |
2. OPC UA 协议支持
新增 eneros-iot-opcua crate,提供 OPC UA 客户端与服务端,接入工业控制系统(DCS/PLC/RTU)。OPC UA 是工业自动化领域主流协议,支持信息模型与安全机制。
OPC UA 客户端
use eneros_iot_opcua::{OpcUaClient, ClientConfig, SecurityPolicy};
let client = OpcUaClient::new(ClientConfig {
endpoint: "opc.tcp://10.20.30.40:4840",
security: SecurityPolicy::Basic256Sha256,
auth: AuthMode::UserName {
username: "eneros",
password: "********",
},
subscription_interval: Duration::milliseconds(100),
}).await?;
// 连接并浏览地址空间
let namespace = client.get_namespace("urn:PLC:Substation1").await?;
let nodes = client.browse(&namespace.root()).await?;
// 订阅节点数据变化
let subscription = client.subscribe(vec![
"ns=2;s=Bus1.Voltage",
"ns=2;s=Line3.Current",
"ns=2;s=CircuitBreaker42.Status",
]).await?;
let mut stream = subscription.data_changes();
while let Some(change) = stream.next().await {
println!("节点 {} 变更: {:?}", change.node_id, change.value);
timeseries.write(change.node_id, change.value).await?;
}
OPC UA 信息模型映射
| OPC UA 概念 | EnerOS 概念 | 映射方式 |
|---|---|---|
| Node | 设备/测点 | 自动注册 |
| Object | 设备实例 | 映射为 Equipment |
| Variable | 遥测数据 | 映射为 TimeseriesPoint |
| Method | 控制命令 | 映射为 Command |
| Event | 事件告警 | 映射为 Event |
3. 设备影子引擎
新增 eneros-iot-shadow crate,为每个设备维护一个数字影子,包含期望状态(desired)、上报状态(reported)与最后已知状态(last_known)。
影子数据结构
use eneros_iot_shadow::{DeviceShadow, ShadowState};
let shadow = shadow_store.get_or_create("meter-001").await?;
// 设备上报状态
shadow.update_reported(json!({
"voltage": 220.3,
"current": 15.2,
"power_factor": 0.95,
"status": "online",
})).await?;
// 应用设置期望状态
shadow.update_desired(json!({
"switch": "on",
"brightness": 80,
})).await?;
// 获取当前影子状态
let state: ShadowState = shadow.state().await?;
println!("期望状态: {:?}", state.desired);
println!("上报状态: {:?}", state.reported);
println!("差异: {:?}", state.delta); // desired 与 reported 的差异
影子更新流程
// 设备上线后自动同步差异
shadow.on_device_online(|device_id| {
let delta = shadow.delta().await?;
if !delta.is_empty() {
// 向设备下发期望状态
mqtt_client.publish(
TopicPattern::command(device_id),
delta,
QoS::AtLeastOnce,
).await?;
}
}).await?;
// 设备离线时保留最后状态
shadow.on_device_offline(|device_id| {
shadow.freeze_last_known().await?;
}).await?;
影子版本与冲突
| 字段 | 类型 | 说明 |
|---|---|---|
| version | u64 | 单调递增版本号 |
| timestamp | DateTime | 最后更新时间 |
| desired | JSON | 期望状态 |
| reported | JSON | 上报状态 |
| last_known | JSON | 最后已知状态 |
| metadata | Map | 各字段更新时间 |
4. 批量设备管理
新增 eneros-iot-batch crate,支持大规模设备的批量注册、批量配置、批量升级、批量控制。
批量注册
use eneros_iot_batch::{BatchManager, BatchOperation};
let manager = BatchManager::new(&ctx);
// 批量注册设备(CSV 导入)
let job = manager.batch_register()
.source("devices.csv")
.template(DeviceTemplate::new("smart-meter-v3"))
.parallelism(32)
.on_progress(|p| println!("注册进度: {:.1}%", p.percentage))
.execute().await?;
println!("成功: {}, 失败: {}", job.success, job.failure);
批量配置下发
// 批量配置 1 万台设备
let rollout = manager.batch_config()
.target(DeviceFilter::model("smart-meter-v3"))
.config(ConfigPatch {
collection_interval: Duration::seconds(15),
reporting_endpoint: "mqtts://broker.eneros.io:8883",
firmware_version: "3.2.1",
})
.strategy(RolloutStrategy::Wave {
wave_size: 500,
wave_interval: Duration::minutes(5),
failure_threshold: 0.02, // 2% 失败率暂停
})
.execute().await?;
批量操作类型
| 操作 | 说明 | 并发度 | 耗时(1 万台) |
|---|---|---|---|
| 注册 | 批量注册设备 | 32 | 5 分钟 |
| 配置 | 批量下发配置 | 16 | 10 分钟 |
| 升级 | 批量 OTA 升级 | 8 | 30 分钟 |
| 控制 | 批量控制命令 | 64 | 30 秒 |
| 查询 | 批量状态查询 | 128 | 10 秒 |
5. 设备接入网关
新增 eneros-iot crate(IoT 核心),提供统一的设备接入网关,支持多协议并存与协议转换。
多协议接入
use eneros_iot::{DeviceGateway, ProtocolAdapter};
let gateway = DeviceGateway::new(&ctx);
// 注册协议适配器
gateway.register_adapter(ProtocolAdapter::mqtt(mqtt_config))?;
gateway.register_adapter(ProtocolAdapter::opcua(opcua_config))?;
gateway.register_adapter(ProtocolAdapter::modbus(modbus_config))?;
gateway.register_adapter(ProtocolAdapter::iec104(iec104_config))?;
// 统一设备模型
gateway.on_device_data(|data| {
// 无论来自哪种协议,统一为 EnerOS 设备模型
let device_id = data.device_id;
let telemetry = data.to_telemetry();
timeseries.write(device_id, telemetry).await?;
shadow_store.update_reported(device_id, data.payload).await?;
}).await?;
gateway.start().await?;
协议适配对比
| 协议 | 适用设备 | 数据模型 | 安全机制 |
|---|---|---|---|
| MQTT | 智能电表、充电桩 | Topic + JSON | TLS + 证书 |
| OPC UA | PLC、DCS | 信息模型 | 安全策略 |
| Modbus | RTU、传感器 | 寄存器映射 | 网段隔离 |
| IEC 104 | 传统 RTU | 遥测遥信 | 应用层认证 |
| CoAP | 低功耗设备 | RESTful | DTLS |
设备发现
// 自动发现局域网内设备
let discovered = gateway.discover()
.protocol(Protocol::Mqtt)
.subnet("10.20.30.0/24")
.timeout(Duration::seconds(10))
.execute().await?;
for device in &discovered {
println!("发现设备: {} ({:?}) @ {}",
device.id, device.protocol, device.address);
// 自动注册到设备注册表
gateway.auto_register(device).await?;
}
改进
- 时序引擎:新增 IoT 数据专用写入路径,小批量写入吞吐提升 3 倍
- 拓扑引擎:支持从 IoT 设备自动构建低压配电网拓扑
- Agent 运行时:新增 IoTAgent 类型,专门处理设备交互
- 安全网关:IoT 设备接入强制设备证书认证
- 可观测性:IoT 设备指标接入中心监控
Bug 修复
- 修复
eneros-iot-mqtt在大量客户端同时连接时 broker 崩溃的问题(#3603) - 修复
eneros-iot-opcua订阅在服务端重启后未自动恢复的问题(#3610) - 修复
eneros-iot-shadow并发更新时版本号冲突的问题(#3616) - 修复
eneros-iot-batch批量操作在中途失败时未回滚的问题(#3622) - 修复
eneros-iot多协议并发时资源竞争导致数据丢失的问题(#3628)
破坏性变更
DeviceShadow::update:拆分为update_reported与update_desiredDeviceGateway::register_adapter:返回Result<()>,需处理冲突BatchManager:所有方法改为异步(async)
升级指南
- 更新
Cargo.toml中的eneros依赖至0.36.0 - 运行
eneros iot init初始化 IoT 网关 - 在
eneros.toml中配置 MQTT/OPC UA 协议参数 - 运行
eneros iot import devices.csv批量导入设备
致谢
感谢 35 位贡献者提交的 520+ 个 commit,以及物联网协议社区提供的兼容性测试。