REST API
EnerOS REST API 遵循 RESTful 规范,使用标准 HTTP 方法语义,所有响应体为 JSON。端点由 eneros-api crate 提供,经 eneros-gateway 校验后转发至内核。每个端点都经过完整的鉴权、限流、审计链路。
通用约定
HTTP 方法语义
| 方法 | 语义 | 幂等 | 安全 | 请求体 | 典型用途 |
|---|---|---|---|---|---|
| GET | 读取资源 | 是 | 是 | 否 | 查询列表/详情 |
| POST | 创建资源 / 触发动作 | 否 | 否 | 是 | 创建网络、触发潮流 |
| PUT | 全量更新资源 | 是 | 否 | 是 | 替换资源 |
| PATCH | 部分更新资源 | 否 | 否 | 是 | 修改字段 |
| DELETE | 删除资源 | 是 | 否 | 否 | 删除资源 |
端点列表
| 方法 | 路径 | 说明 | 鉴权 | 限流 |
|---|---|---|---|---|
| GET | /api/v1/health | 健康检查 | 否 | 60/min |
| POST | /api/v1/auth/token | 获取 Token | 否 | 30/min |
| POST | /api/v1/auth/refresh | 刷新 Token | 是 | 30/min |
| GET | /api/v1/networks | 电网列表 | 是 | 600/min |
| POST | /api/v1/networks | 创建电网 | 是 | 60/min |
| GET | /api/v1/networks/{id} | 电网详情 | 是 | 600/min |
| PUT | /api/v1/networks/{id} | 更新电网 | 是 | 60/min |
| DELETE | /api/v1/networks/{id} | 删除电网 | 是 | 30/min |
| POST | /api/v1/networks/{id}/powerflow | 触发潮流计算 | 是 | 30/min |
| POST | /api/v1/networks/{id}/validate | 校验拓扑 | 是 | 60/min |
| GET | /api/v1/agents | Agent 列表 | 是 | 600/min |
| POST | /api/v1/agents | 创建 Agent | 是 | 60/min |
| GET | /api/v1/agents/{id} | Agent 详情 | 是 | 600/min |
| PUT | /api/v1/agents/{id} | 更新 Agent 配置 | 是 | 60/min |
| DELETE | /api/v1/agents/{id} | 删除 Agent | 是 | 30/min |
| POST | /api/v1/agents/{id}/command | 下发 Agent 指令 | 是 | 100/min |
| POST | /api/v1/agents/{id}/pause | 暂停 Agent | 是 | 60/min |
| POST | /api/v1/agents/{id}/resume | 恢复 Agent | 是 | 60/min |
| GET | /api/v1/devices | 设备列表 | 是 | 600/min |
| GET | /api/v1/devices/{id} | 设备详情 | 是 | 600/min |
| PATCH | /api/v1/devices/{id} | 更新设备状态 | 是 | 60/min |
| GET | /api/v1/timeseries | 时序数据查询 | 是 | 600/min |
| POST | /api/v1/timeseries/batch | 批量写入时序 | 是 | 1000/min |
| GET | /api/v1/events | 事件历史 | 是 | 600/min |
| GET | /api/v1/alarms | 告警列表 | 是 | 600/min |
| PATCH | /api/v1/alarms/{id}/ack | 确认告警 | 是 | 60/min |
| GET | /api/v1/audit | 审计日志 | 是 | 600/min |
| GET | /api/v1/tasks/{id} | 任务状态查询 | 是 | 600/min |
| DELETE | /api/v1/tasks/{id} | 取消任务 | 是 | 30/min |
分页、过滤、排序
分页参数
列表端点统一支持以下分页参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
page | int | 否 | 1 | 页码,从 1 开始 |
page_size | int | 否 | 20 | 每页数量,最大 100 |
cursor | string | 否 | — | 游标(用于游标分页,优先于 page) |
分页响应:
{
"data": [/* ... */],
"meta": {
"page": 1,
"page_size": 20,
"total": 137,
"total_pages": 7,
"next_cursor": "eyJpZCI6Im5ldF94eHgifQ=="
}
}
过滤参数
各端点支持的过滤字段示例:
| 端点 | 过滤字段 | 示例 |
|---|---|---|
/networks | status, name | ?status=ready&name=IEEE |
/agents | status, type | ?status=running&type=dispatch |
/devices | type, online | ?type=PV&online=true |
/alarms | severity, status, from, to | ?severity=critical&from=2026-07-06T00:00:00Z |
/events | topic, from, to | ?topic=alarm.critical&from=... |
排序参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
sort | string | 否 | -created_at | 字段名前缀 - 表示降序 |
sort 多字段 | string | 否 | — | 逗号分隔,如 name,-created_at |
示例:?sort=-created_at&page=2&page_size=50
端点详解
健康检查
GET /api/v1/health 检查服务可用性,无需鉴权。
请求参数:无
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
status | string | ok / degraded / down |
version | string | EnerOS 版本号 |
uptime_seconds | int | 服务运行时长 |
checks | object | 各子系统状态 |
cURL 示例:
curl http://localhost:8080/api/v1/health
响应示例:
{
"data": {
"status": "ok",
"version": "0.47.0",
"uptime_seconds": 86400,
"checks": {
"database": "ok",
"timeseries": "ok",
"eventbus": "ok",
"realtime": "ok"
}
},
"request_id": "req_20260706_001",
"timestamp": "2026-07-06T08:30:00Z"
}
获取 Token
POST /api/v1/auth/token 通过用户名密码换取 Bearer Token。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
username | string | 是 | — | 用户名 |
password | string | 是 | — | 密码 |
tenant_id | string | 否 | 默认租户 | 租户 ID |
scope | string | 否 | default | 权限范围 |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
响应示例:
{
"data": {
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "rft_20260706_abc123",
"expires_in": 3600,
"token_type": "Bearer"
},
"request_id": "req_20260706_002",
"timestamp": "2026-07-06T08:30:00Z"
}
创建电网
POST /api/v1/networks 创建一个新的电网模型。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | 是 | — | 电网名称,最长 64 字符 |
description | string | 否 | "" | 描述,最长 256 字符 |
base_kv | float | 否 | 110.0 | 基准电压(kV) |
base_mva | float | 否 | 100.0 | 基准容量(MVA) |
buses | array | 是 | — | 母线列表,至少 1 条 |
buses[].id | int | 是 | — | 母线编号 |
buses[].type | string | 是 | — | slack / pv / pq |
buses[].v | float | 否 | 1.0 | 电压标幺值(slack/pv 必填) |
buses[].theta | float | 否 | 0.0 | 相角(弧度,slack 必填) |
buses[].area | int | 否 | 1 | 区域编号 |
branches | array | 否 | [] | 支路列表 |
branches[].from | int | 是 | — | 起始母线 |
branches[].to | int | 是 | — | 终止母线 |
branches[].r | float | 是 | — | 电阻标幺值 |
branches[].x | float | 是 | — | 电抗标幺值 |
branches[].b | float | 否 | 0.0 | 充电容纳标幺值 |
generators | array | 否 | [] | 发电机列表 |
loads | array | 否 | [] | 负荷列表 |
tags | object | 否 | {} | 自定义标签 |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/networks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "IEEE-14",
"base_kv": 110.0,
"base_mva": 100.0,
"buses": [
{"id": 1, "type": "slack", "v": 1.05, "theta": 0.0},
{"id": 2, "type": "pv", "v": 1.04},
{"id": 3, "type": "pq"}
],
"branches": [
{"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528}
],
"generators": [
{"bus": 1, "mw": 50.0, "mvar": 0.0}
],
"loads": [
{"bus": 3, "mw": 94.2, "mvar": 19.0}
],
"tags": {"owner": "ieee", "scenario": "summer"}
}'
Rust 示例:
use eneros_sdk::{ApiClient, models::NetworkInput};
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = ApiClient::builder()
.endpoint("http://localhost:8080")
.token("<bearer-token>")
.build()?;
let input = NetworkInput {
name: "IEEE-14".to_string(),
base_kv: Some(110.0),
base_mva: Some(100.0),
buses: vec![
json!({"id": 1, "type": "slack", "v": 1.05, "theta": 0.0}),
json!({"id": 2, "type": "pv", "v": 1.04}),
json!({"id": 3, "type": "pq"}),
],
branches: vec![
json!({"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528}),
],
generators: vec![json!({"bus": 1, "mw": 50.0, "mvar": 0.0})],
loads: vec![json!({"bus": 3, "mw": 94.2, "mvar": 19.0})],
tags: json!({"owner": "ieee", "scenario": "summer"}),
..Default::default()
};
let network = client.networks().create(&input).await?;
println!("created network: {}", network.id);
Ok(())
}
Python 示例:
from eneros_sdk import ApiClient
client = ApiClient(
endpoint="http://localhost:8080",
token="<bearer-token>",
)
network = client.networks.create({
"name": "IEEE-14",
"base_kv": 110.0,
"base_mva": 100.0,
"buses": [
{"id": 1, "type": "slack", "v": 1.05, "theta": 0.0},
{"id": 2, "type": "pv", "v": 1.04},
{"id": 3, "type": "pq"},
],
"branches": [
{"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528},
],
"generators": [{"bus": 1, "mw": 50.0, "mvar": 0.0}],
"loads": [{"bus": 3, "mw": 94.2, "mvar": 19.0}],
"tags": {"owner": "ieee", "scenario": "summer"},
})
print(f"created network: {network.id}")
响应示例:
{
"data": {
"id": "net_8f3a2b",
"name": "IEEE-14",
"description": "",
"base_kv": 110.0,
"base_mva": 100.0,
"bus_count": 14,
"branch_count": 20,
"generator_count": 5,
"load_count": 11,
"status": "ready",
"tags": {"owner": "ieee", "scenario": "summer"},
"created_at": "2026-07-06T08:30:00Z",
"updated_at": "2026-07-06T08:30:00Z"
},
"request_id": "req_20260706_003",
"timestamp": "2026-07-06T08:30:00Z"
}
获取电网列表
GET /api/v1/networks 返回当前租户下的电网列表。
请求参数(Query):
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
page | int | 否 | 1 | 页码 |
page_size | int | 否 | 20 | 每页数量 |
status | string | 否 | — | 过滤状态 |
name | string | 否 | — | 模糊匹配名称 |
tag | string | 否 | — | 按 tag 过滤,格式 key:value |
sort | string | 否 | -created_at | 排序字段 |
响应示例:
{
"data": [
{
"id": "net_8f3a2b",
"name": "IEEE-14",
"bus_count": 14,
"status": "ready",
"created_at": "2026-07-06T08:30:00Z"
},
{
"id": "net_9c4d1e",
"name": "IEEE-30",
"bus_count": 30,
"status": "ready",
"created_at": "2026-07-05T10:00:00Z"
}
],
"meta": {
"page": 1,
"page_size": 20,
"total": 2,
"total_pages": 1
},
"request_id": "req_20260706_004",
"timestamp": "2026-07-06T08:30:00Z"
}
触发潮流计算
POST /api/v1/networks/{id}/powerflow 触发一次潮流计算任务。
路径参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 电网 ID |
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
method | string | 否 | newton_raphson | 算法:newton_raphson / fast_decoupled / dc |
tolerance | float | 否 | 1e-8 | 收敛精度 |
max_iterations | int | 否 | 50 | 最大迭代次数 |
async | bool | 否 | false | 是否异步执行 |
flat_start | bool | 否 | false | 是否平启动 |
timeout_ms | int | 否 | 30000 | 超时时间(毫秒) |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/networks/net_8f3a2b/powerflow \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"method": "newton_raphson", "tolerance": 1e-8, "max_iterations": 50}'
响应示例(同步模式):
{
"data": {
"task_id": "pf_20260706_001",
"network_id": "net_8f3a2b",
"status": "converged",
"method": "newton_raphson",
"iterations": 4,
"duration_ms": 12,
"tolerance": 1e-8,
"buses": [
{"id": 1, "v": 1.05, "theta": 0.0, "p_gen": 50.0, "q_gen": 12.5},
{"id": 2, "v": 1.04, "theta": -0.039, "p_gen": 0.0, "q_gen": 0.0}
],
"branches": [
{"from": 1, "to": 2, "p_from": 50.0, "q_from": 12.5, "loading": 0.45}
],
"losses": {"p_mw": 1.23, "q_mvar": 5.67},
"started_at": "2026-07-06T08:30:00Z",
"completed_at": "2026-07-06T08:30:00.012Z"
},
"request_id": "req_20260706_005",
"timestamp": "2026-07-06T08:30:00Z"
}
响应示例(异步模式):
{
"data": {
"task_id": "pf_20260706_002",
"network_id": "net_8f3a2b",
"status": "queued",
"poll_url": "/api/v1/tasks/pf_20260706_002"
},
"request_id": "req_20260706_006",
"timestamp": "2026-07-06T08:30:00Z"
}
创建 Agent
POST /api/v1/agents 创建并注册一个新的 Agent。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | 是 | — | Agent 名称 |
type | string | 是 | — | dispatch / self_healing / trading / maintenance / planning |
network_id | string | 否 | — | 关联电网 ID |
config | object | 否 | {} | Agent 配置 |
tools | array | 否 | [] | 允许使用的工具列表 |
reasoning_model | string | 否 | default | 推理模型 |
max_actions_per_minute | int | 否 | 60 | 最大动作频率 |
auto_start | bool | 否 | false | 创建后自动启动 |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/agents \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "DispatchAgent-01",
"type": "dispatch",
"network_id": "net_8f3a2b",
"config": {"objective": "economic", "horizon_minutes": 15},
"tools": ["powerflow", "topology", "forecast"],
"reasoning_model": "default",
"max_actions_per_minute": 30,
"auto_start": true
}'
JavaScript 示例:
import { ApiClient } from '@eneros/sdk';
const client = new ApiClient({
endpoint: 'http://localhost:8080',
token: '<bearer-token>',
});
const agent = await client.agents.create({
name: 'DispatchAgent-01',
type: 'dispatch',
networkId: 'net_8f3a2b',
config: { objective: 'economic', horizonMinutes: 15 },
tools: ['powerflow', 'topology', 'forecast'],
reasoningModel: 'default',
maxActionsPerMinute: 30,
autoStart: true,
});
console.log('created agent:', agent.id);
响应示例:
{
"data": {
"id": "agent_dispatch_01",
"name": "DispatchAgent-01",
"type": "dispatch",
"network_id": "net_8f3a2b",
"status": "running",
"config": {"objective": "economic", "horizon_minutes": 15},
"tools": ["powerflow", "topology", "forecast"],
"reasoning_model": "default",
"max_actions_per_minute": 30,
"created_at": "2026-07-06T08:30:00Z",
"started_at": "2026-07-06T08:30:01Z"
},
"request_id": "req_20260706_007",
"timestamp": "2026-07-06T08:30:00Z"
}
下发 Agent 指令
POST /api/v1/agents/{id}/command 向 Agent 下发一条指令。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
command | string | 是 | — | 指令名称 |
params | object | 否 | {} | 指令参数 |
priority | string | 否 | normal | low / normal / high / emergency |
timeout_ms | int | 否 | 5000 | 指令超时 |
await_result | bool | 否 | true | 是否等待结果 |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/agents/agent_dispatch_01/command \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"command": "set_generation",
"params": {"bus": 2, "mw": 50.0},
"priority": "normal",
"timeout_ms": 5000,
"await_result": true
}'
响应示例:
{
"data": {
"command_id": "cmd_20260706_001",
"agent_id": "agent_dispatch_01",
"command": "set_generation",
"status": "success",
"result": {
"bus": 2,
"mw_set": 50.0,
"constraint_checked": true,
"audit_id": "aud_20260706_001"
},
"duration_ms": 12,
"executed_at": "2026-07-06T08:30:00Z"
},
"request_id": "req_20260706_008",
"timestamp": "2026-07-06T08:30:00Z"
}
时序数据查询
GET /api/v1/timeseries 查询时序数据,支持聚合与降采样。
请求参数(Query):
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
metric | string | 是 | — | 指标名,如 branch_loading |
tags | string | 否 | — | 标签过滤,格式 key:value,key2:value2 |
from | datetime | 是 | — | 起始时间(RFC 3339) |
to | datetime | 是 | — | 结束时间 |
aggregation | string | 否 | none | none / avg / sum / max / min / count |
interval | string | 否 | — | 降采样间隔,如 1m / 5m / 1h |
fill | string | 否 | null | 缺失值填充策略:null / zero / linear |
limit | int | 否 | 10000 | 最大返回点数 |
cURL 示例:
curl -G http://localhost:8080/api/v1/timeseries \
-H "Authorization: Bearer <token>" \
--data-urlencode "metric=branch_loading" \
--data-urlencode "tags=network:net_8f3a2b,branch:1-2" \
--data-urlencode "from=2026-07-06T00:00:00Z" \
--data-urlencode "to=2026-07-06T08:00:00Z" \
--data-urlencode "aggregation=avg" \
--data-urlencode "interval=5m"
Python 示例:
from eneros_sdk import ApiClient
from datetime import datetime, timezone, timedelta
client = ApiClient(endpoint="http://localhost:8080", token="<bearer-token>")
result = client.timeseries.query(
metric="branch_loading",
tags={"network": "net_8f3a2b", "branch": "1-2"},
from_=datetime.now(timezone.utc) - timedelta(hours=8),
to=datetime.now(timezone.utc),
aggregation="avg",
interval="5m",
)
for point in result.points:
print(f"{point.timestamp} -> {point.value}")
响应示例:
{
"data": {
"metric": "branch_loading",
"tags": {"network": "net_8f3a2b", "branch": "1-2"},
"aggregation": "avg",
"interval": "5m",
"points": [
{"timestamp": "2026-07-06T00:00:00Z", "value": 0.42},
{"timestamp": "2026-07-06T00:05:00Z", "value": 0.45},
{"timestamp": "2026-07-06T00:10:00Z", "value": 0.48}
],
"count": 96
},
"request_id": "req_20260706_009",
"timestamp": "2026-07-06T08:30:00Z"
}
批量写入时序
POST /api/v1/timeseries/batch 批量写入时序数据点,单次最多 10000 点。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
points | array | 是 | — | 数据点数组 |
points[].metric | string | 是 | — | 指标名 |
points[].timestamp | datetime | 否 | 当前时间 | 时间戳 |
points[].value | float | 是 | — | 数值 |
points[].tags | object | 否 | {} | 标签 |
cURL 示例:
curl -X POST http://localhost:8080/api/v1/timeseries/batch \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"points": [
{"metric": "branch_loading", "timestamp": "2026-07-06T08:30:00Z", "value": 0.42, "tags": {"network": "net_8f3a2b", "branch": "1-2"}},
{"metric": "bus_voltage", "timestamp": "2026-07-06T08:30:00Z", "value": 1.05, "tags": {"network": "net_8f3a2b", "bus": "1"}}
]
}'
响应示例:
{
"data": {
"accepted": 2,
"rejected": 0,
"errors": []
},
"request_id": "req_20260706_010",
"timestamp": "2026-07-06T08:30:00Z"
}
告警列表与确认
GET /api/v1/alarms 获取告警列表,PATCH /api/v1/alarms/{id}/ack 确认告警。
列表请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
severity | string | 否 | — | info / warn / error / critical |
status | string | 否 | — | active / acknowledged / cleared |
network_id | string | 否 | — | 限定电网 |
from | datetime | 否 | — | 起始时间 |
to | datetime | 否 | — | 结束时间 |
确认告警请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
acknowledged_by | string | 是 | — | 确认人 |
note | string | 否 | "" | 备注 |
响应示例(列表):
{
"data": [
{
"id": "alm_001",
"severity": "critical",
"status": "active",
"type": "BRANCH_OVERLOAD",
"message": "Branch 1-2 overload: 105% of limit",
"network_id": "net_8f3a2b",
"source": {"type": "constraint_engine", "id": "ce_01"},
"details": {"branch_id": "1-2", "loading": 1.05, "limit": 1.0},
"raised_at": "2026-07-06T08:30:00Z",
"acknowledged_at": null,
"cleared_at": null
}
],
"meta": {"page": 1, "page_size": 20, "total": 1, "total_pages": 1},
"request_id": "req_20260706_011",
"timestamp": "2026-07-06T08:30:00Z"
}
审计日志查询
GET /api/v1/audit 查询操作审计日志,需要审计权限。
请求参数:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
actor | string | 否 | — | 操作者 |
action | string | 否 | — | 操作类型 |
resource_type | string | 否 | — | 资源类型 |
resource_id | string | 否 | — | 资源 ID |
from | datetime | 否 | — | 起始时间 |
to | datetime | 否 | — | 结束时间 |
page | int | 否 | 1 | 页码 |
page_size | int | 否 | 50 | 每页数量 |
响应示例:
{
"data": [
{
"id": "aud_20260706_001",
"timestamp": "2026-07-06T08:30:00Z",
"actor": {"type": "user", "id": "admin", "tenant": "default"},
"action": "agent.command",
"resource": {"type": "agent", "id": "agent_dispatch_01"},
"request_id": "req_20260706_008",
"ip": "192.168.1.10",
"user_agent": "curl/7.88.1",
"result": "success",
"details": {"command": "set_generation", "params": {"bus": 2, "mw": 50.0}}
}
],
"meta": {"page": 1, "page_size": 50, "total": 1, "total_pages": 1},
"request_id": "req_20260706_012",
"timestamp": "2026-07-06T08:30:00Z"
}
错误码
通用错误码
| HTTP 状态 | 错误码 | 含义 |
|---|---|---|
| 400 | INVALID_REQUEST | 请求参数错误 |
| 400 | INVALID_FIELD | 字段值非法 |
| 401 | UNAUTHORIZED | 未认证或 token 失效 |
| 401 | TOKEN_EXPIRED | Token 已过期 |
| 403 | FORBIDDEN | 权限不足 |
| 404 | NOT_FOUND | 资源不存在 |
| 405 | METHOD_NOT_ALLOWED | 方法不支持 |
| 409 | CONFLICT | 资源状态冲突 |
| 409 | CONSTRAINT_VIOLATION | 违反安全约束 |
| 413 | PAYLOAD_TOO_LARGE | 请求体过大 |
| 422 | VALIDATION_FAILED | 业务校验失败 |
| 429 | RATE_LIMITED | 触发限流 |
| 500 | INTERNAL_ERROR | 内核错误 |
| 503 | SERVICE_UNAVAILABLE | 服务不可用 |
| 504 | GATEWAY_TIMEOUT | 网关超时 |
业务错误码
| HTTP 状态 | 错误码 | 含义 |
|---|---|---|
| 409 | POWERFLOW_DIVERGED | 潮流不收敛 |
| 409 | NETWORK_LOCKED | 网络被锁定 |
| 422 | TOPOLOGY_INVALID | 拓扑不合法 |
| 422 | PARAM_OUT_OF_RANGE | 参数越界 |
| 422 | AGENT_BUSY | Agent 忙 |
| 422 | BUS_NOT_FOUND | 母线不存在 |
| 422 | BRANCH_NOT_FOUND | 支路不存在 |
| 422 | ISLANDED_BUS | 母线孤岛 |
| 422 | VOLTAGE_OUT_OF_LIMIT | 电压越限 |
错误响应体统一格式:
{
"error": {
"code": "CONSTRAINT_VIOLATION",
"message": "Branch 1-2 overload: 105% of limit",
"details": {"branch_id": "1-2", "loading": 1.05, "limit": 1.0},
"trace_id": "trace_abc123",
"doc_url": "https://docs.openeneros.com/api-reference/rest#错误码"
},
"request_id": "req_20260706_008"
}
字段枚举值说明
NetworkStatus
| 值 | 说明 |
|---|---|
draft | 草稿,可编辑 |
ready | 就绪,可参与计算 |
locked | 锁定(计算中),不可修改 |
archived | 归档,只读 |
AgentType
| 值 | 说明 |
|---|---|
dispatch | 调度 Agent |
self_healing | 自愈 Agent |
trading | 交易 Agent |
maintenance | 运维 Agent |
planning | 规划 Agent |
AgentStatus
| 值 | 说明 |
|---|---|
idle | 空闲 |
running | 运行中 |
paused | 已暂停 |
error | 错误 |
stopped | 已停止 |
PowerFlowMethod
| 值 | 说明 |
|---|---|
newton_raphson | 牛顿-拉夫逊法(默认) |
fast_decoupled | 快速解耦法(PQ 分解) |
dc | 直流潮流 |
BusType
| 值 | 说明 |
|---|---|
slack | 平衡节点 |
pv | PV 节点(电压可控) |
pq | PQ 节点(负荷节点) |
DeviceType
| 值 | 说明 |
|---|---|
PV | 光伏 |
WIND | 风电 |
BESS | 储能 |
EV | 电动汽车 |
LOAD | 负荷 |
TRANSFORMER | 变压器 |
BREAKER | 断路器 |
批量操作
除时序写入外,REST API 还支持以下批量端点:
| 方法 | 路径 | 说明 | 单批上限 |
|---|---|---|---|
| POST | /api/v1/networks/batch | 批量创建电网 | 20 |
| POST | /api/v1/agents/batch | 批量创建 Agent | 50 |
| POST | /api/v1/devices/batch | 批量创建设备 | 200 |
| DELETE | /api/v1/networks/batch | 批量删除电网 | 50 |
批量请求统一返回每个条目的独立结果:
{
"data": {
"succeeded": [{"index": 0, "id": "net_a"}, {"index": 1, "id": "net_b"}],
"failed": [{"index": 2, "error": {"code": "VALIDATION_FAILED", "message": "invalid bus"}}]
}
}
相关文档
- API 总览 — 四种 API 对比
- GraphQL — 灵活查询替代方案
- 限流与配额 — 速率限制策略
- 版本管理 — API 版本演进
- eneros-api crate — API 服务实现