endpointhash 1.0
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# softbus_daemon API 接口表
|
||||
|
||||
本文档汇总 `src/api/ipc_dbus` 当前对外接口,分为:
|
||||
本文档汇总 `src/api` 当前对外接口,分为:
|
||||
- D-Bus 直接方法
|
||||
- `executeCommand` JSON 命令接口
|
||||
- HTTP REST 接口
|
||||
|
||||
## 1) D-Bus 服务基础信息
|
||||
|
||||
@@ -53,15 +54,49 @@
|
||||
|
||||
| action | params 关键字段 | 成功 code | 失败 code | 说明 |
|
||||
|---|---|---:|---:|---|
|
||||
| `add_filter` | `id`, `endpoint?`, `deviceId?`, `stableKey?`, `condition?` | `0` | `4001` | 添加过滤规则 |
|
||||
| `add_filter` | `id`, `endpointHash?`, `deviceId?`, `stableKey?`, `condition?` | `0` | `4001` | 添加过滤规则 |
|
||||
| `remove_filter` | `id` | `0` | `4041` | 删除过滤规则 |
|
||||
| `add_transform_rule` | `id`, `endpoint?`, `deviceId?`, `stableKey?`, `scale?`, `offset?`, `unit?` | `0` | `4002` | 添加转换规则 |
|
||||
| `add_transform_rule` | `id`, `endpointHash?`, `deviceId?`, `stableKey?`, `scale?`, `offset?`, `unit?` | `0` | `4002` | 添加转换规则 |
|
||||
| `remove_transform_rule` | `id` | `0` | `4042` | 删除转换规则 |
|
||||
| `add_mapping_rule` | `compositeKey`, `domPath`, `scale?`, `offset?`, `unit?` | `0` | `4004` | 新增/更新映射规则 |
|
||||
| `remove_mapping_rule` | `compositeKey` | `0` | `4043` | 删除映射规则 |
|
||||
| `list_mapping_rules` | 无 | `0` | - | 返回映射规则列表 |
|
||||
| `discovery_start` | `ttlMs?` | `0` | - | 开启嗅探模式 |
|
||||
| `discovery_stop` | 无 | `0` | - | 关闭嗅探模式 |
|
||||
| `discovery_clear` | 无 | `0` | - | 清空发现池 |
|
||||
| `list_rules` | 无 | `0` | - | 返回规则计数状态 |
|
||||
| `get_status` | 无 | `0` | - | 返回规则计数状态 |
|
||||
| `get_status` | 无 | `0` | - | 返回规则计数 + discovery/mapping 状态 |
|
||||
| 其他未知 action | - | - | `4040` | 未知动作 |
|
||||
|
||||
## 5) 通用错误码约定(当前实现)
|
||||
## 5) HTTP REST 路由表(RestApiRoutes)
|
||||
|
||||
### 5.1 通用路由
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| `GET` | `/health` | 健康检查,返回 `{"ok": true}` |
|
||||
| `GET` | `/v1/status` | 透传 `get_status` 的状态响应 |
|
||||
| `POST` | `/v1/command` | 统一命令入口(请求体为 executeCommand JSON) |
|
||||
|
||||
### 5.2 Discovery 路由
|
||||
|
||||
| 方法 | 路径 | 请求参数 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `POST` | `/api/v1/discovery/start` | body: `ttlMs?` | 开启嗅探;可设置自动关闭 TTL |
|
||||
| `POST` | `/api/v1/discovery/stop` | 无 | 关闭嗅探 |
|
||||
| `GET` | `/api/v1/discovery/status` | 无 | 获取发现池运行状态 |
|
||||
| `POST` | `/api/v1/discovery/clear` | 无 | 清空发现池样本 |
|
||||
| `GET` | `/api/v1/discovery/samples` | query: `offset?`, `limit?`, `endpointHash?`, `protocol?` | 拉取样本(按更新时间倒序,且过滤已映射 key) |
|
||||
|
||||
### 5.3 Mapping 路由
|
||||
|
||||
| 方法 | 路径 | 请求参数 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `POST` | `/api/v1/mapping/bind` | body: `compositeKey`, `domPath`, `scale?`, `offset?`, `unit?` | 绑定或更新映射规则 |
|
||||
| `POST` | `/api/v1/mapping/unbind` | body: `compositeKey` | 删除映射规则 |
|
||||
| `GET` | `/api/v1/mapping/list` | 无 | 列出当前映射规则 |
|
||||
|
||||
## 6) 通用错误码约定(当前实现)
|
||||
|
||||
| code | message | 说明 |
|
||||
|---:|---|---|
|
||||
@@ -70,14 +105,19 @@
|
||||
| `4001` | `invalid_filter_rule` | 过滤规则参数非法 |
|
||||
| `4002` | `invalid_transform_rule` | 转换规则参数非法 |
|
||||
| `4003` | `invalid_action` | action 为空或分发器不可用 |
|
||||
| `4004` | `invalid_mapping_rule` | 映射规则参数非法 |
|
||||
| `4040` | `unknown_action` | action 未注册 |
|
||||
| `4041` | `filter_not_found` | 删除过滤规则时未找到 |
|
||||
| `4042` | `transform_rule_not_found` | 删除转换规则时未找到 |
|
||||
| `4043` | `mapping_rule_not_found` | 删除映射规则时未找到 |
|
||||
|
||||
## 6) 维护建议
|
||||
## 7) 维护建议
|
||||
|
||||
- 新增 action 时,同时更新:
|
||||
- `CommandDispatcher::dispatch(...)`
|
||||
- 本文档第 4 节 action 表
|
||||
- 新增 REST 路由时,同时更新:
|
||||
- `RestApiRoutes.cpp`
|
||||
- 本文档第 5 节路由表
|
||||
- 若扩展返回结构,保持 `code/message/data` 三元组不变,避免客户端兼容性问题。
|
||||
|
||||
|
||||
@@ -1,18 +1,164 @@
|
||||
#include "api/http/RestApiRoutes.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QHttpServer>
|
||||
#include <QHttpServerRequest>
|
||||
#include <QHttpServerResponse>
|
||||
#include <QHttpServerResponder>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QUrlQuery>
|
||||
#include <utility>
|
||||
|
||||
#include "api/http/RestApiCommandHttp.h"
|
||||
#include "api/ipc_dbus/CommandDispatcher.h"
|
||||
#include "message_bus/pipeline/discovery/DiscoveryPool.h"
|
||||
#include "message_bus/pipeline/mapping/MappingRegistry.h"
|
||||
|
||||
namespace softbus::api::http
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
softbus::core::models::ProtocolType protocolFromString(const QString& s)
|
||||
{
|
||||
const QString x = s.trimmed().toUpper();
|
||||
if (x == QStringLiteral("MODBUS_RTU")) {
|
||||
return softbus::core::models::ProtocolType::MODBUS_RTU;
|
||||
}
|
||||
if (x == QStringLiteral("MODBUS_ASCII")) {
|
||||
return softbus::core::models::ProtocolType::MODBUS_ASCII;
|
||||
}
|
||||
if (x == QStringLiteral("MODBUS_TCP")) {
|
||||
return softbus::core::models::ProtocolType::MODBUS_TCP;
|
||||
}
|
||||
if (x == QStringLiteral("CAN_RAW")) {
|
||||
return softbus::core::models::ProtocolType::CAN_RAW;
|
||||
}
|
||||
if (x == QStringLiteral("CAN_OPEN")) {
|
||||
return softbus::core::models::ProtocolType::CAN_OPEN;
|
||||
}
|
||||
if (x == QStringLiteral("UDP_CUSTOM")) {
|
||||
return softbus::core::models::ProtocolType::UDP_CUSTOM;
|
||||
}
|
||||
return softbus::core::models::ProtocolType::UNKNOWN;
|
||||
}
|
||||
|
||||
QJsonObject parseJsonBody(const QHttpServerRequest& request)
|
||||
{
|
||||
QJsonParseError err;
|
||||
const auto doc = QJsonDocument::fromJson(request.body(), &err);
|
||||
if (err.error != QJsonParseError::NoError || !doc.isObject()) {
|
||||
return {};
|
||||
}
|
||||
return doc.object();
|
||||
}
|
||||
|
||||
void registerDiscoveryRoutes(QHttpServer* server, QObject* routeContext)
|
||||
{
|
||||
server->route(QStringLiteral("/api/v1/discovery/start"), QHttpServerRequest::Method::Post, routeContext,
|
||||
[](const QHttpServerRequest& request) {
|
||||
auto& pool = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
const auto payload = parseJsonBody(request);
|
||||
const std::int64_t ttlMs = payload.value(QStringLiteral("ttlMs")).toInteger(0);
|
||||
pool.startSniffing(ttlMs);
|
||||
return QHttpServerResponse(pool.status(), QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/discovery/stop"), QHttpServerRequest::Method::Post, routeContext, []() {
|
||||
auto& pool = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
pool.stopSniffing();
|
||||
return QHttpServerResponse(pool.status(), QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/discovery/status"), QHttpServerRequest::Method::Get, routeContext, []() {
|
||||
auto& pool = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
pool.tick();
|
||||
return QHttpServerResponse(pool.status(), QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/discovery/clear"), QHttpServerRequest::Method::Post, routeContext, []() {
|
||||
auto& pool = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
pool.clear();
|
||||
return QHttpServerResponse(pool.status(), QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/discovery/samples"), QHttpServerRequest::Method::Get, routeContext,
|
||||
[](const QHttpServerRequest& request) {
|
||||
auto& pool = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
auto& mappingReg = softbus::message_bus::pipeline::MappingRegistry::instance();
|
||||
pool.tick();
|
||||
const QUrlQuery query(request.url().query());
|
||||
const std::size_t offset =
|
||||
static_cast<std::size_t>(std::max(0, query.queryItemValue(QStringLiteral("offset")).toInt(0)));
|
||||
bool limitOk = false;
|
||||
const int limitCandidate = query.queryItemValue(QStringLiteral("limit")).toInt(&limitOk, 10);
|
||||
const int limitRaw = limitOk ? limitCandidate : 200;
|
||||
const std::size_t limit = static_cast<std::size_t>(std::clamp(limitRaw, 1, 500));
|
||||
const std::uint32_t endpointHash = static_cast<std::uint32_t>(
|
||||
query.queryItemValue(QStringLiteral("endpointHash")).toUInt(nullptr, 10));
|
||||
const auto protocol = protocolFromString(query.queryItemValue(QStringLiteral("protocol")));
|
||||
|
||||
QJsonObject o;
|
||||
o.insert(QStringLiteral("items"),
|
||||
pool.listSamples(offset, limit, endpointHash, protocol, mappingReg.snapshotMappedKeys()));
|
||||
o.insert(QStringLiteral("offset"), static_cast<qint64>(offset));
|
||||
o.insert(QStringLiteral("limit"), static_cast<qint64>(limit));
|
||||
o.insert(QStringLiteral("status"), pool.status());
|
||||
return QHttpServerResponse(o, QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
}
|
||||
|
||||
void registerMappingRoutes(QHttpServer* server, QObject* routeContext)
|
||||
{
|
||||
server->route(QStringLiteral("/api/v1/mapping/bind"), QHttpServerRequest::Method::Post, routeContext,
|
||||
[](const QHttpServerRequest& request) {
|
||||
const auto payload = parseJsonBody(request);
|
||||
softbus::message_bus::pipeline::MappingRule rule;
|
||||
rule.compositeKey = payload.value(QStringLiteral("compositeKey")).toString().toULongLong();
|
||||
rule.domPath = payload.value(QStringLiteral("domPath")).toString();
|
||||
rule.scale = payload.value(QStringLiteral("scale")).toDouble(1.0);
|
||||
rule.offset = payload.value(QStringLiteral("offset")).toDouble(0.0);
|
||||
rule.unit = payload.value(QStringLiteral("unit")).toString();
|
||||
|
||||
auto& mappingReg = softbus::message_bus::pipeline::MappingRegistry::instance();
|
||||
if (!mappingReg.upsert(rule)) {
|
||||
return QHttpServerResponse(
|
||||
QJsonObject{{QStringLiteral("error"), QStringLiteral("invalid_mapping_rule")}},
|
||||
QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
return QHttpServerResponse(QJsonObject{{QStringLiteral("ok"), true},
|
||||
{QStringLiteral("compositeKey"),
|
||||
QString::number(rule.compositeKey)}},
|
||||
QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/mapping/unbind"), QHttpServerRequest::Method::Post, routeContext,
|
||||
[](const QHttpServerRequest& request) {
|
||||
const auto payload = parseJsonBody(request);
|
||||
const std::uint64_t compositeKey =
|
||||
payload.value(QStringLiteral("compositeKey")).toString().toULongLong();
|
||||
auto& mappingReg = softbus::message_bus::pipeline::MappingRegistry::instance();
|
||||
const bool ok = mappingReg.remove(compositeKey);
|
||||
return QHttpServerResponse(QJsonObject{{QStringLiteral("ok"), ok},
|
||||
{QStringLiteral("compositeKey"),
|
||||
QString::number(compositeKey)}},
|
||||
ok ? QHttpServerResponse::StatusCode::Ok
|
||||
: QHttpServerResponse::StatusCode::NotFound);
|
||||
});
|
||||
|
||||
server->route(QStringLiteral("/api/v1/mapping/list"), QHttpServerRequest::Method::Get, routeContext, []() {
|
||||
auto& mappingReg = softbus::message_bus::pipeline::MappingRegistry::instance();
|
||||
return QHttpServerResponse(QJsonObject{{QStringLiteral("items"), mappingReg.list()}},
|
||||
QHttpServerResponse::StatusCode::Ok);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void registerSoftbusRestApiRoutes(QHttpServer* server,
|
||||
QObject* routeContext,
|
||||
softbus::api::ipc::CommandDispatcher* dispatcher)
|
||||
@@ -33,6 +179,8 @@ void registerSoftbusRestApiRoutes(QHttpServer* server,
|
||||
[dispatcher](const QHttpServerRequest& request) {
|
||||
return handleExecuteCommandHttpBody(request.body(), *dispatcher);
|
||||
});
|
||||
registerDiscoveryRoutes(server, routeContext);
|
||||
registerMappingRoutes(server, routeContext);
|
||||
|
||||
server->setMissingHandler(routeContext, [](const QHttpServerRequest&, QHttpServerResponder& responder) {
|
||||
QHttpServerResponse resp(QJsonObject{{QStringLiteral("error"), QStringLiteral("not_found")}},
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "api/ipc_dbus/CommandDispatcher.h"
|
||||
|
||||
#include "message_bus/pipeline/DynamicRuleRegistry.h"
|
||||
#include "message_bus/pipeline/rules/DynamicRuleRegistry.h"
|
||||
#include "message_bus/pipeline/discovery/DiscoveryPool.h"
|
||||
#include "message_bus/pipeline/mapping/MappingRegistry.h"
|
||||
|
||||
namespace softbus::api::ipc
|
||||
{
|
||||
@@ -22,6 +24,8 @@ softbus::message_bus::pipeline::RuleScope parseScope(const QJsonObject& params)
|
||||
DispatchResult CommandDispatcher::dispatch(const QString& action, const QJsonObject& params) const
|
||||
{
|
||||
auto& reg = softbus::message_bus::pipeline::DynamicRuleRegistry::instance();
|
||||
auto& mappingReg = softbus::message_bus::pipeline::MappingRegistry::instance();
|
||||
auto& discovery = softbus::message_bus::pipeline::DiscoveryPool::instance();
|
||||
if (action == QStringLiteral("add_filter")) {
|
||||
softbus::message_bus::pipeline::FilterRule rule;
|
||||
rule.id = params.value(QStringLiteral("id")).toString();
|
||||
@@ -57,7 +61,45 @@ DispatchResult CommandDispatcher::dispatch(const QString& action, const QJsonObj
|
||||
QJsonObject{{QStringLiteral("id"), id}}};
|
||||
}
|
||||
if (action == QStringLiteral("list_rules") || action == QStringLiteral("get_status")) {
|
||||
return {0, QStringLiteral("ok"), reg.status()};
|
||||
QJsonObject status = reg.status();
|
||||
status.insert(QStringLiteral("discovery"), discovery.status());
|
||||
status.insert(QStringLiteral("mapping"), mappingReg.status());
|
||||
return {0, QStringLiteral("ok"), status};
|
||||
}
|
||||
if (action == QStringLiteral("add_mapping_rule")) {
|
||||
softbus::message_bus::pipeline::MappingRule rule;
|
||||
const QString keyText = params.value(QStringLiteral("compositeKey")).toString();
|
||||
rule.compositeKey = keyText.toULongLong();
|
||||
rule.domPath = params.value(QStringLiteral("domPath")).toString();
|
||||
rule.scale = params.value(QStringLiteral("scale")).toDouble(1.0);
|
||||
rule.offset = params.value(QStringLiteral("offset")).toDouble(0.0);
|
||||
rule.unit = params.value(QStringLiteral("unit")).toString();
|
||||
if (!mappingReg.upsert(rule)) {
|
||||
return {4004, QStringLiteral("invalid_mapping_rule"), {}};
|
||||
}
|
||||
return {0, QStringLiteral("ok"), QJsonObject{{QStringLiteral("compositeKey"), keyText}}};
|
||||
}
|
||||
if (action == QStringLiteral("remove_mapping_rule")) {
|
||||
const QString keyText = params.value(QStringLiteral("compositeKey")).toString();
|
||||
const bool ok = mappingReg.remove(keyText.toULongLong());
|
||||
return {ok ? 0 : 4043, ok ? QStringLiteral("ok") : QStringLiteral("mapping_rule_not_found"),
|
||||
QJsonObject{{QStringLiteral("compositeKey"), keyText}}};
|
||||
}
|
||||
if (action == QStringLiteral("list_mapping_rules")) {
|
||||
return {0, QStringLiteral("ok"), QJsonObject{{QStringLiteral("items"), mappingReg.list()}}};
|
||||
}
|
||||
if (action == QStringLiteral("discovery_start")) {
|
||||
const auto ttlMs = params.value(QStringLiteral("ttlMs")).toInteger(0);
|
||||
discovery.startSniffing(ttlMs);
|
||||
return {0, QStringLiteral("ok"), discovery.status()};
|
||||
}
|
||||
if (action == QStringLiteral("discovery_stop")) {
|
||||
discovery.stopSniffing();
|
||||
return {0, QStringLiteral("ok"), discovery.status()};
|
||||
}
|
||||
if (action == QStringLiteral("discovery_clear")) {
|
||||
discovery.clear();
|
||||
return {0, QStringLiteral("ok"), discovery.status()};
|
||||
}
|
||||
return {4040, QStringLiteral("unknown_action"), {}};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user