部署与体验
准备运行环境
github 地址 https://github.com/OpenEMS/openems
在 releases 页下载最新的 openems-edge.jar
可选择 clone 项目到本地,本文不涉及源码但是后续可能会用到
项目 jdk 设置为至少 jdk21,可选将 gradle-wrapper.properties 内的 distributionUrl 修改为 https\://mirrors.cloud.tencent.com/gradle/gradle-xxx-bin.zip 或者其他国内镜像地址
启动 jar 并配置基础组件
启动 jar
启动 openems-edge.jar,控制台会一直报 There are no Schedulers configured! 这是正常的不用管它
管理页
进入 http://localhost:8080/system/console ,这是 felix 的管理页,felix 是一个 OSGI 容器的实现,负责管理模块(Bundle)、服务(Service)和组件(Component)
OSGI 容器负责模块级别的热插拔和动态路由服务,主要为了模块化来避免 "巨石应用"以及提供不停机更新能力,可以类比为是单个 JVM 内的微服务架构,其同样有独立部署单元、注册中心、服务发现等机制(但是其核心目标与实现上和微服务架构同样存在不小差别,最大的区别是 OSGI 没有进程及资源隔离且调用是本地方法调用而不是网络调用)
其页面菜单大致有以下
OSGI
Bundles
Components
Configuration
Log Service
Servies
Status
Bundlelist
Bundles
Capabilities
Configurations
Declarative Services Components
Framework Properties
Overview
Permissions
Services
System Properties
Threads
Wire Admin
Web Console
Licenses
System Information
其中需要重点关注的菜单大都在 OSGI 下
| 菜单 | 功能 | 在 OpenEMS 的作用 |
|---|---|---|
| Configuration | 配置管理-对象级别的管理 | 最常用的入口。 OpenEMS 把所有业务模块(调度器、控制器、模拟设备)都做成了工厂类。在这里点击 + 填表单保存,Felix 就会在内存里真正实例化出一个对应的跑着业务的设备或算法 |
| Bundles | 模块管理-代码级别管理 | 显示所有独立的 jar 包(Bundle)。可以随时在这里上传新的 jar、停止或启动某个模块。它实现了热部署能力 |
| Components | 组件管理-依赖级管理 | 显示底层组件类的注册状态 |
| Log Service | 日志查看 | Felix 容器自身的日志和 OpenEMS 抛出的异常 |
| Status -> Threads | 线程快照 | 展示当前 JVM 里所有的线程状态 |
HelloWord
尝试添加模拟设备闭环一个场景
进入 OSGI -> Configuration 菜单,按顺序添加以下组件
添加方式为点击组件右侧 + 号,添加表单后点击 save 按钮创建
| 组件 | 表单(标注为 * 的修改项实际上是默认值,无需修改) | 角色 | 详情 |
|---|---|---|---|
| Simulator App | 勾选 Is enabled? |
提供仿真环境 | |
| Simulator Datasource: CSV Predefined | id* 修改为 datasource0,Source 修改为 H0_HOUSEHOLD_SUMMER_WEEKDAY_STANDARD_LOAD_PROFILE(这个类型为归一化值,有96个点),Time-Delta 设置为15 (24分钟模拟现实一天) | 模拟电表数据源 | |
| Simulator Datasource: CSV Predefined | id 修改为 datasource1,Source 修改为 H0_HOUSEHOLD_SUMMER_WEEKDAY_PV_PRODUCTION(这个类型为真实值,有1440个点),Factor 修改为 1,Time-Delta 设置为1 (24分钟模拟现实一天) | 模拟光伏数据源 | |
| Simulator GridMeter Reacting | id* 修改为 meter0 | 模拟电网电表 | 读到"当前从电网买/卖了多少电" |
| Simulator NRCMeter Acting | id 修改为 load0,Datasource-ID* 修改为 datasource0 | 模拟总负荷 | |
| Simulator EssSymmetric Reacting | id* 修改为 ess0 | 模拟储能 | 接受充放电指令 |
| Simulator Pv-Inverter | id 修改为 pvInverter0,Datasource-ID 修改为 datasource1 | 模拟光伏 | 当前光伏发了多少电 |
| Controller Ess Balancing | id* 修改为 ctrlBalancing0,Ess-ID 修改为 ess0,Grid-Meter-ID 修改为 meter0 | 自消纳决策逻辑 | 核心:看 meter0,算 ess0 该充放多少 |
| Scheduler All Alphabetically | id* 修改为 scheduler0,Controller-IDs 修改为 ctrlBalancing0 | 决定每个 Cycle 跑哪些 Controller | 把 ctrlBalancing0 纳入调度 |
| Controller Api REST/JSON Read-Write | Port 修改为任一可用端口,本文中将其修改为 18080 | 提供 REST API | 外部观察用,不参与控制逻辑 |
关键配置及原因
Controller 关联 ess.id 和 meter.id:Controller 不直接操作设备,而是通过 Channel 读写。它需要知道"我要读哪个电表的功率"和"我要写哪个储能的功率指令"。这就是 OpenEMS 的解耦设计------Controller 只认 Channel,不认协议(Channel 是挂在 Component 下面的子级数据点,每个 Component 内部会声明一堆 Channel,分别代表它的某个具体读值或写值)
Scheduler 把 ctrlBalancing0 放进 controllers.ids:Scheduler 是 Cycle 调度器,它按这个列表决定执行哪些 controllers 以及 controllers 的执行顺序
datasource:模拟电表/光伏不会自己生成数据,它们只是"读 datasource 在当前时间点的值,乘以 factor,作为自己的 ActivePower"(这一点只针对模拟设备,真实设备是绑定 bridge 获取的数据)
注意到上述模拟设备中有 Acting 和 Reacting 两种,它们的区别是 Reacting 模拟设备不会主动决定自己的状态,而是根据系统其它组件的状态实时计算,Acting 模拟设备则主动向系统提供输入数据。在本次配置里,光伏和负荷用 Acting,作为系统的输入源;储能和电网电表用 Reacting,作为系统的响应结果。这样能量平衡公式 Grid = Load - PV - ESS 才能在 meter0 上动态体现出来,否则 Controller 看不到自己动作的反馈,整个闭环就断了。
这套配置构造了一个最小可运行系统,来验证 openems 的动态调整功能
验证
bash
# 具体端口号为 Controller Api REST/JSON Read-Write 中设置的端口号
# REST 查询的地址格式是 {ComponentId}/{ChannelId}------前者是在 ConfigMgr 里给组件起的 ID(如 ess0),后者是组件按 Nature 接口规范暴露的数据点
curl -u admin:admin http://localhost:18080/rest/channel/ess0/Soc
curl -u admin:admin http://localhost:18080/rest/channel/ess0/ActivePower
curl -u admin:admin http://localhost:18080/rest/channel/meter0/ActivePower
curl -u admin:admin http://localhost:18080/rest/channel/pvInverter0/ActivePower
四个接口分别是查询储能百分比,储能放电功率,电网放电功率,光伏发电功率
配置的这个 controller 目标为使得电网放电功率接近 0,也就是光伏发电多了会尽量储能,光伏发电不够会从储能放能,实在不够的才会从电网来补充。如果需要实现更复杂的需求例如根据电网峰谷价格储能卖电需要配置其它的 controller 或者通过 scheduler 组合多个 controller 来实现
持续观察这几个接口的返回值应该能看到默认策略起到作用,openems 会根据电网放电功率做动态控制调控储能放电功率,储能百分比也会随着充放电波动