API 总览
EnerOS 提供四种 API 接口,满足不同场景的接入需求。所有 API 均通过 eneros-api 与 eneros-graphql crate 暴露,并由 eneros-gateway 进行统一鉴权、限流与安全审计。无论选择哪种协议,底层共享同一套内核系统调用,因此数据一致性、约束校验、审计日志均得到保证。
API 类型对比
EnerOS 提供四种 API 接口,分别对应不同的接入场景与通信模型:
| 类型 | 协议 | 传输方向 | 适用场景 | 实时性 | 浏览器原生 | 自动重连 | 典型用途 |
|---|---|---|---|---|---|---|---|
| REST | HTTP/1.1 或 HTTP/2 | 请求-响应 | CRUD 操作、配置管理、批量任务 | 同步 | 是(fetch) | 否 | 网络/Agent/设备管理 |
| GraphQL | HTTP/1.1 或 HTTP/2 | 请求-响应 | 灵活查询、按需取数、聚合分析 | 同步 | 是(fetch) | 否 | 跨资源聚合查询 |
| WebSocket | WS/WSS(基于 HTTP 升级) | 双向全双工 | 实时事件推送、远程指令下发 | 实时(毫秒级) | 是(WebSocket) | 需手动实现 | Agent 状态、控制指令 |
| SSE | HTTP/1.1 长连接 | 服务端→客户端 | 单向实时推送、轻量订阅 | 实时(秒级) | 是(EventSource) | 是 | 告警看板、事件大屏 |
选型决策树
是否需要服务端主动推送?
├── 否 → 是否需要灵活字段选取或跨资源聚合?
│ ├── 是 → GraphQL
│ └── 否 → REST
└── 是 → 是否需要客户端向服务端发送指令?
├── 是(双向) → WebSocket
└── 否(单向) → 是否运行在浏览器中?
├── 是 → SSE(自动重连)
└── 否 → WebSocket(更高效)
并发与资源占用
| 维度 | REST | GraphQL | WebSocket | SSE |
|---|---|---|---|---|
| 单连接内存 | ~50 KB | ~50 KB | ~80 KB | ~30 KB |
| 单连接 CPU(空闲) | 0% | 0% | 0.1% | 0% |
| 单连接 CPU(活跃) | 0.5% | 0.5% | 1.0% | 0.3% |
| 单租户最大连接 | 不限 | 不限 | 20 | 50 |
| 协议开销 | 中 | 中 | 低(首包后) | 低 |
基础信息
Base URL
EnerOS API 的根 URL 取决于部署模式:
| 部署模式 | Base URL | 说明 |
|---|---|---|
| 单机本地 | http://localhost:8080/api/v1 | 开发与测试 |
| 单机生产 | https://api.example.com/api/v1 | 单实例对外 |
| 多区域 | https://{region}.api.eneros.io/api/v1 | 如 cn-east.api.eneros.io |
| 内网网格 | http://eneros-api.nerve.svc:8080/api/v1 | Kubernetes 内部 |
各协议端点:
| 协议 | 端点 | 说明 |
|---|---|---|
| REST | http://<host>:8080/api/v1 | 资源 CRUD |
| GraphQL | http://<host>:8080/graphql | Query / Mutation |
| GraphQL Subscription | ws://<host>:8080/graphql | 实时订阅 |
| WebSocket | ws://<host>:8080/ws | 双向事件流 |
| SSE | http://<host>:8080/api/v1/events/stream | 单向推送 |
生产环境强制启用 HTTPS / WSS,由 eneros-trust 签发证书。
通用约定
| 项目 | 取值 |
|---|---|
| 内容类型 | application/json; charset=utf-8 |
| 字符编码 | UTF-8 |
| 时间格式 | RFC 3339 / UTC(如 2026-07-06T08:30:00Z) |
| 时区 | 所有时间戳默认 UTC,可查询时附带 ?tz=Asia/Shanghai 转换显示 |
| 数值精度 | 浮点数采用 IEEE 754 double,电气量默认 6 位有效数字 |
| ID 格式 | 字符串,前缀标识类型(net_、agent_、dev_、evt_) |
| 资源命名 | 复数形式(/networks、/agents、/devices) |
| 字段命名 | 后端 snake_case,REST 响应保留 snake_case,GraphQL 转为 camelCase |
鉴权方式
EnerOS 支持三种鉴权方式,可单独或组合使用:
1. Bearer Token
最常用的鉴权方式。Token 由 eneros-trust 签发,包含租户、角色、过期时间与权限范围。Token 默认有效期 1 小时,可通过刷新机制续期。
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
Authorization | string | 是 | — | 固定前缀 Bearer + JWT |
| Token 格式 | JWT (RS256) | — | — | Header.Payload.Signature |
| Token 有效期 | int (秒) | — | 3600 | 可在 eneros.toml 中配置 |
| 刷新 Token | string | 否 | — | 有效期 30 天,仅可使用一次 |
2. mTLS 双向认证
生产环境推荐使用。客户端与网关互相验证 X.509 证书,由内部 CA 签发。mTLS 可与 Bearer Token 叠加使用,实现双重校验。
curl --cert client.crt --key client.key --cacert ca.crt \
https://api.example.com/api/v1/networks
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| 客户端证书 | X.509 PEM | 是 | — | CN 必须为 agent-{id} 或 service-{name} |
| 客户端私钥 | RSA/EC PEM | 是 | — | 至少 2048 位 |
| CA 证书 | X.509 PEM | 是 | — | EnerOS 内部 CA |
| 证书有效期 | int (天) | — | 365 | 到期前 30 天告警 |
3. API Key(仅限服务间调用)
用于内部服务调用的长期凭证,不能用于面向终端用户的场景。API Key 绑定到特定服务账号,权限范围受限。
X-API-Key: sk-internal-xxxxxxxxxxxxxxxxxxxx
鉴权方式对比
| 方式 | 安全等级 | 适用场景 | 过期管理 | 双向身份验证 |
|---|---|---|---|---|
| Bearer Token | 中 | Web/App 终端、短期会话 | 自动过期 + 刷新 | 否 |
| mTLS | 高 | 服务间、Agent ↔ 网关 | 证书轮换 | 是 |
| API Key | 低 | 内部受信任服务 | 手动轮换 | 否 |
通用请求头
| Header | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
Authorization | string | 是* | — | Bearer <token>,公开端点除外 |
Content-Type | string | 是 | application/json | POST/PUT/PATCH 必填 |
Accept | string | 否 | application/json | 可指定 application/json 或 application/graphql-response+json |
X-Tenant-Id | string | 否 | 自动从 Token 解析 | 显式指定租户,需有跨租户权限 |
X-Request-Id | string | 否 | 自动生成 UUID | 链路追踪 ID,将透传至审计日志 |
X-Trace-Id | string | 否 | — | OpenTelemetry trace ID |
User-Agent | string | 否 | eneros-client/0.1 | 客户端标识 |
Accept-Language | string | 否 | zh-CN | 错误消息语言 |
通用响应格式
成功响应
所有 REST 成功响应均为 JSON,顶层字段约定如下:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
data | object/array | 是 | 业务数据本体 |
meta | object | 否 | 分页、版本等元信息 |
request_id | string | 是 | 请求追踪 ID |
timestamp | string | 是 | 响应生成时间(RFC 3339) |
示例:
{
"data": {
"id": "net_8f3a2b",
"name": "IEEE-14"
},
"meta": {
"version": "v1",
"deprecated": false
},
"request_id": "req_20260706_8f3a2b",
"timestamp": "2026-07-06T08:30:00Z"
}
错误响应
错误响应统一格式:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error.code | string | 是 | 大写下划线错误码 |
error.message | string | 是 | 人类可读错误描述 |
error.details | object | 否 | 结构化补充信息 |
error.trace_id | string | 是 | 链路追踪 ID |
error.doc_url | string | 否 | 文档链接 |
request_id | string | 是 | 请求追踪 ID |
示例:
{
"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_8f3a2b"
}
错误码总表
EnerOS 错误码分为五类:客户端错误(4xx)、服务端错误(5xx)、网关错误、安全错误、业务错误。
客户端错误(4xx)
| HTTP | 错误码 | 含义 | 处理建议 |
|---|---|---|---|
| 400 | INVALID_REQUEST | 请求参数错误、JSON 格式错误 | 检查请求体与参数 |
| 400 | INVALID_FIELD | 字段值非法(如枚举不匹配) | 查看字段说明 |
| 401 | UNAUTHORIZED | 未认证或 token 失效 | 重新获取 token |
| 401 | TOKEN_EXPIRED | Token 已过期 | 刷新 token |
| 403 | FORBIDDEN | 权限不足 | 联系管理员调整角色 |
| 403 | TENANT_MISMATCH | 跨租户访问被拒 | 检查 X-Tenant-Id |
| 404 | NOT_FOUND | 资源不存在 | 核对资源 ID |
| 405 | METHOD_NOT_ALLOWED | HTTP 方法不支持 | 检查端点定义 |
| 409 | CONFLICT | 资源状态冲突 | 重读后重试 |
| 409 | CONSTRAINT_VIOLATION | 违反安全约束 | 修正电气参数 |
| 413 | PAYLOAD_TOO_LARGE | 请求体超过 1MB | 减小批量大小 |
| 422 | VALIDATION_FAILED | 业务校验失败 | 查看错误详情 |
| 429 | RATE_LIMITED | 触发限流 | 按 Retry-After 重试 |
服务端错误(5xx)
| HTTP | 错误码 | 含义 | 处理建议 |
|---|---|---|---|
| 500 | INTERNAL_ERROR | 内核未捕获错误 | 联系运维,附 trace_id |
| 501 | NOT_IMPLEMENTED | 端点尚未实现 | 等待版本更新 |
| 502 | BAD_GATEWAY | 上游服务异常 | 重试或检查依赖 |
| 503 | SERVICE_UNAVAILABLE | 服务过载或维护中 | 退避后重试 |
| 504 | GATEWAY_TIMEOUT | 网关等待上游超时 | 检查任务是否异步执行 |
安全错误
| HTTP | 错误码 | 含义 | 处理建议 |
|---|---|---|---|
| 401 | CERT_INVALID | mTLS 证书无效 | 检查证书链 |
| 401 | CERT_EXPIRED | 证书已过期 | 轮换证书 |
| 403 | IP_BLOCKED | IP 被拉黑 | 联系管理员解封 |
| 403 | AUDIT_REQUIRED | 操作需审计留痕 | 添加审计上下文 |
业务错误
| HTTP | 错误码 | 含义 | 处理建议 |
|---|---|---|---|
| 409 | POWERFLOW_DIVERGED | 潮流不收敛 | 调整初值或方法 |
| 409 | NETWORK_LOCKED | 网络被锁定(计算中) | 等待或释放锁 |
| 422 | TOPOLOGY_INVALID | 拓扑不合法(孤岛/环网) | 修正拓扑 |
| 422 | PARAM_OUT_OF_RANGE | 电气参数越界 | 检查上下限 |
| 422 | AGENT_BUSY | Agent 处于忙状态 | 排队或等待 |
版本管理
EnerOS API 采用 URL 路径版本 + 语义化版本双重策略:
| 版本 | 状态 | 发布时间 | 废弃时间 | 说明 |
|---|---|---|---|---|
v1 | 稳定 | 2026-01 | — | 当前主版本 |
v2 | 预览 | 2026-09(计划) | — | 下一主版本 |
详细策略见 版本管理。
限流策略
EnerOS 采用分层限流,详见 限流与配额:
| 维度 | 速率 | 说明 |
|---|---|---|
| 全局(IP) | 600 req/min | 防恶意刷接口 |
| 租户 | 5000 req/h | 公平调度 |
| 计算类端点 | 30 req/min | 保护内核算力 |
| 时序写入 | 1000 req/min | 高吞吐场景 |
所有限流响应都附带 X-RateLimit-* 响应头,便于客户端自适应降速。
SDK 列表
EnerOS 官方提供以下 SDK,封装鉴权、重试、序列化等通用逻辑:
| 语言 | 包名 | 版本 | 维护状态 | 仓库 |
|---|---|---|---|---|
| Rust | eneros-sdk | 0.47.0 | 官方主线 | eneros/crates/eneros-sdk |
| Python | eneros-sdk-python | 0.47.0 | 官方同步 | eneros/sdks/python |
| JavaScript/TypeScript | @eneros/sdk | 0.47.0 | 官方同步 | eneros/sdks/js |
| Go | eneros-sdk-go | 0.47.0 | 社区贡献 | github.com/eneros/go-sdk |
| Java | eneros-sdk-java | 0.45.0 | 社区贡献 | github.com/eneros/java-sdk |
SDK 选型建议
// Rust SDK 示例
use eneros_sdk::ApiClient;
let client = ApiClient::builder()
.endpoint("http://localhost:8080")
.api_version("v1")
.token("<bearer-token>")
.build()?;
let networks = client.networks().list().await?;
# Python SDK 示例
from eneros_sdk import ApiClient
client = ApiClient(
endpoint="http://localhost:8080",
api_version="v1",
token="<bearer-token>",
)
networks = client.networks.list()
// JavaScript SDK 示例
import { ApiClient } from '@eneros/sdk';
const client = new ApiClient({
endpoint: 'http://localhost:8080',
apiVersion: 'v1',
token: '<bearer-token>',
});
const networks = await client.networks.list();
快速验证
使用 cURL 快速验证 API 可用性:
# 1. 健康检查(无需认证)
curl http://localhost:8080/api/v1/health
# 2. 获取 Token(开发环境)
curl -X POST http://localhost:8080/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# 3. 获取网络列表
curl -H "Authorization: Bearer <token>" \
http://localhost:8080/api/v1/networks
# 4. 创建 Agent
curl -X POST http://localhost:8080/api/v1/agents \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"type":"dispatch","config":{}}'
# 5. GraphQL 查询
curl -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"query":"{ networks { id name } }"}'
# 6. SSE 订阅告警
curl -N -H "Authorization: Bearer <token>" \
"http://localhost:8080/api/v1/events/stream?topics=alarm&severity=critical"
通用响应字段枚举
资源状态枚举
| 资源 | 状态值 | 说明 |
|---|---|---|
| Network | draft / ready / locked / archived | 草稿/就绪/锁定/归档 |
| Agent | idle / running / paused / error / stopped | 空闲/运行/暂停/错误/停止 |
| Device | online / offline / maintenance / fault | 在线/离线/维护/故障 |
| Task | queued / running / completed / failed / cancelled | 排队/运行/完成/失败/取消 |
| Alarm | active / acknowledged / cleared | 活跃/已确认/已清除 |
严重级别枚举
| 值 | 数值 | 说明 |
|---|---|---|
info | 0 | 信息 |
warn | 1 | 警告 |
error | 2 | 错误 |
critical | 3 | 严重,需立即处置 |