EnerOS v0.25.0 版本说明
发布日期:2025-09-14 版本代号:Plugin Git Tag:v0.25.0 支持状态:稳定(Stable) Crate 总数:64(新增 4 个) 测试用例数:8100+(新增 500+)
概述
EnerOS v0.25.0「Plugin」是插件系统专项版本,将 EnerOS 从封闭系统升级为可扩展平台。电力行业场景碎片、协议繁多、设备多样,单靠内核无法覆盖所有需求。v0.25.0 引入完整的插件系统,允许第三方以插件形式扩展内核能力——接入私有协议、自定义设备模型、扩展分析算法、集成外部系统——同时保证内核的安全与稳定。
本版本引入了五大核心能力:插件系统(Plugin System)、插件 SDK(Plugin SDK)、动态加载(Dynamic Loading)、插件市场(Plugin Marketplace)、沙箱隔离(Sandbox Isolation)。插件以 WebAssembly(WASM)模块形式分发,在沙箱中运行,通过显式能力授权访问内核资源。
设计哲学上,v0.25.0 坚持「安全优先」——所有插件默认运行在沙箱中,仅能访问显式授予的能力(Capability);「热插拔」——插件支持运行时加载与卸载,无需重启;「可治理」——插件的安装、更新、卸载均有审计记录。
关键数据
| 指标 | 数值 | 说明 |
|---|---|---|
| 插件加载时间 | < 50ms | WASM 模块 |
| 插件调用延迟 | 120μs | 沙箱内 |
| 沙箱隔离强度 | 进程级 | WASM + 能力授权 |
| 初始市场插件 | 32 个 | 官方+社区 |
| 新增 Crate | 4 | 插件相关 |
| 新增测试 | 500+ | 含安全测试 |
新特性
1. 插件系统
引入 eneros-plugin Crate,提供完整的插件运行时。插件以 WASM 模块形式存在,通过宿主提供的接口访问内核能力。
插件注册
use eneros_plugin::{PluginManager, Plugin, PluginManifest};
let mut manager = PluginManager::new()
.sandbox(Sandbox::strict())
.capability_store(CapabilityStore::new());
// 安装插件
let manifest = PluginManifest::from_file("modbus-advanced.wasm")?;
let plugin: Plugin = manager.install(manifest).await?;
// 授予能力
plugin.grant(Capability::Network("modbus-tcp"))?;
plugin.grant(Capability::Device("read-only"))?;
// 启动插件
plugin.start().await?;
插件清单
# plugin.toml
name = "modbus-advanced"
version = "1.2.0"
author = "EnerOS Community"
description = "高级 Modbus 协议插件"
[capabilities]
network = ["modbus-tcp", "modbus-rtu"]
device = ["read-only"]
storage = ["config"]
[entry]
init = "plugin_init"
poll = "plugin_poll"
cleanup = "plugin_cleanup"
插件类型
| 类型 | 用途 | 示例 |
|---|---|---|
| 协议适配器 | 设备接入 | Modbus、IEC 104、DNP3 |
| 设备模型 | 设备扩展 | 私有设备参数库 |
| 分析算法 | 分析扩展 | 自定义稳定算法 |
| 数据源 | 数据集成 | 外部数据库接入 |
| UI 组件 | 界面扩展 | 自定义仪表盘 |
2. 插件 SDK
引入 eneros-plugin-sdk Crate,为插件开发者提供 Rust SDK。SDK 封装了与宿主的交互逻辑,开发者只需实现 trait 即可。
SDK 示例
use eneros_plugin_sdk::{Plugin, Context, Result};
struct ModbusPlugin {
client: ModbusClient,
}
impl Plugin for ModbusPlugin {
fn init(ctx: &Context) -> Result<Self> {
let addr = ctx.config("address")?;
let client = ModbusClient::connect(addr)?;
Ok(ModbusPlugin { client })
}
fn poll(&mut self, ctx: &Context) -> Result<()> {
// 读取寄存器
let values = self.client.read_holding(0, 10)?;
// 写入内核时序库
for (i, v) in values.iter().enumerate() {
ctx.write_timeseries(
&format!("modbus.register.{}", i),
*v as f64,
)?;
}
Ok(())
}
fn cleanup(&mut self) -> Result<()> {
self.client.close();
Ok(())
}
}
eneros_plugin_sdk::export_plugin!(ModbusPlugin);
SDK 能力 API
| API | 说明 | 需要能力 |
|---|---|---|
ctx.read_bus(id) | 读母线 | device.read |
ctx.write_timeseries(key, val) | 写时序 | storage.write |
ctx.send_event(event) | 发事件 | event.publish |
ctx.http_get(url) | HTTP 请求 | network.http |
ctx.log(level, msg) | 日志 | (默认) |
3. 动态加载
引入 eneros-plugin-loader Crate,支持运行时动态加载与卸载插件,无需重启系统。
热加载
use eneros_plugin_loader::{Loader, LoadOptions};
let loader = Loader::new(&manager);
// 运行时加载
let plugin = loader.load("modbus-advanced-1.2.0.wasm")
.options(LoadOptions {
sandbox_level: SandboxLevel::Strict,
auto_start: true,
})
.await?;
// 运行时卸载
loader.unload(&plugin.id).await?;
// 卸载会自动清理资源、断开连接
热更新
// 插件版本升级(零停机)
loader.upgrade(&plugin.id, "modbus-advanced-1.3.0.wasm")
.migrate_state(true) // 迁移运行状态
.await?;
加载性能
| 操作 | 耗时 | 说明 |
|---|---|---|
| 编译 WASM | 35ms | Cranelift 后端 |
| 实例化 | 8ms | 含内存分配 |
| 启动 | 5ms | init 函数 |
| 卸载 | 3ms | 含资源清理 |
4. 插件市场
引入 eneros-plugin-market Crate,提供插件市场客户端。用户可搜索、安装、更新来自官方与社区的插件。
市场操作
use eneros_plugin_market::{Market, SearchQuery};
let market = Market::connect("https://market.eneros.io")?;
// 搜索插件
let results = market.search(SearchQuery::new("modbus"))
.category("protocol")
.sort_by(SortBy::Downloads)
.top(10).await?;
for p in results {
println!("{} v{} - 下载 {} 次, 评分 {:.1}",
p.name, p.version, p.downloads, p.rating);
}
// 安装
market.install("modbus-advanced", "1.2.0").await?;
// 更新检查
let updates = market.check_updates().await?;
官方插件清单
| 插件名 | 类别 | 版本 | 下载量 |
|---|---|---|---|
| modbus-advanced | 协议 | 1.2.0 | 12k |
| iec104-pro | 协议 | 2.0.1 | 8.5k |
| dnp3-master | 协议 | 1.5.0 | 3.2k |
| pq-analyzer | 分析 | 0.9.2 | 5.1k |
| gridvis-ui | UI | 1.1.0 | 9.8k |
5. 沙箱隔离
引入 eneros-plugin-sandbox Crate,提供基于 WASM 的沙箱隔离。插件在独立实例中运行,无法直接访问宿主内存或文件系统。
沙箱配置
use eneros_plugin_sandbox::{Sandbox, SandboxLevel, ResourceLimit};
let sandbox = Sandbox::new()
.level(SandboxLevel::Strict)
.memory_limit(64 * 1024 * 1024) // 64 MB
.cpu_limit(Duration::milliseconds(100)) // 单次调用 100ms
.fs_access(FsAccess::None)
.network_access(NetworkAccess::Denied);
manager.set_sandbox(sandbox);
能力授权
// 默认无任何能力,需显式授予
plugin.grant(Capability::Network("modbus-tcp:502"))?;
plugin.grant(Capability::Timeseries("write:modbus.*"))?;
plugin.grant(Capability::Log("info"))?;
// 撤销能力
plugin.revoke(Capability::Network("modbus-tcp:502"))?;
沙箱安全模型
| 层级 | 隔离机制 | 适用场景 |
|---|---|---|
| Strict | WASM + 能力 + 资源限制 | 不可信插件 |
| Standard | WASM + 能力 | 社区插件 |
| Trusted | WASM | 官方插件 |
| Native | 进程隔离 | 内核模块 |
改进
- WASM 引擎:升级至 Wasmtime 25,执行性能提升 18%
- 能力粒度:能力授权从「类别级」细化至「资源级」
- 插件审计:所有插件操作(加载/卸载/调用)均记录审计日志
- 依赖管理:插件间依赖关系自动解析,避免冲突
Bug 修复
- 修复
eneros-plugin-loader热更新时状态迁移丢失的问题(#2508) - 修复
eneros-plugin-sandbox在插件崩溃时宿主内存泄漏的问题(#2513) - 修复
eneros-plugin-sdk在并发调用时 Context 死锁的问题(#2519) - 修复
eneros-plugin-market校验签名时未检查证书链的问题(#2524)
破坏性变更
PluginManager::install:返回类型从Result<()>改为Result<Plugin>,需保存返回值Capability枚举:Network变体从Network改为Network(&str),需指定具体地址
升级指南
- 执行
cargo update -p eneros-plugin - 更新
PluginManager::install调用以保存返回的Plugin - 更新
Capability::Network授权以指定具体地址 - 参考
docs/migration/v0.25.0.md获取详细迁移步骤