6.3 KiB
softbus_edge_agent
独立边缘进程:连接核心 softbus_daemon 的 edgeIngress TCP 端口,发送 HELLO、DATA_RAWBUS,以及通过极简 本地 HTTP(GET /、GET /ui、POST /propose 等)触发 TREE_PROPOSE 反向同步。
目录布局(与 softbus_daemon 的 src/ 对齐)
| 路径 | 说明 |
|---|---|
src/device_bus/tree/ |
与核心同源的 DeviceTreeModel(本地子树、TREE_FULL 落盘加载) |
src/device_bus/monitor/ |
udev 串口发现、EdgeDiscoveryCoordinator(防抖后组 TREE_PROPOSE / upsert 向核心注册) |
src/device_bus/manager/ |
SerialDeviceManager、CanDeviceManager(无 Registry / Pipeline,仅 IIngressPort + 内存池) |
src/device_bus/EdgeDeviceBus.* |
边缘总线编排:加载本地树、reconcile 串口与 SocketCAN 实例 |
src/devices/、src/hardware/ |
与核心同源的 SerialDevice、SerialQtDriver 等 |
src/message_bus/ingress/ |
EdgeSession、EdgeUplinkWire、EdgeTcpUplinkPort(RawBusMessage → SBUP 上行) |
协议与核心侧文档对齐:
- 核心权威说明:softbus_daemon/docs/EDGE_UPLINK_PROTOCOL_v1.md(若仓库路径不同请自行调整相对链接)。
构建
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64
cmake --build build
./build/bin/softbus_edge_agent config/edge_manifest.example.json
依赖 Qt6 Core、Network、SerialPort;若 Qt 安装包含 SerialBus 模块,CMake 会自动检测并链接,从而在边缘启用 SocketCAN reconcile(设备树 can:... 节点)。未安装时仍可完整构建,CAN 节点将被忽略。
配置 edge_manifest.json(可选)
若默认路径 config/edge_manifest.json 不存在、或传入的 manifest 路径无法打开、或 JSON 非法,进程会使用内置默认值启动(等价于示例 manifest 的字段),并在日志中提示。
仍可通过命令行指定路径覆盖默认文件位置:
./build/bin/softbus_edge_agent /path/to/edge_manifest.json
见 config/edge_manifest.schema.json 与示例 config/edge_manifest.example.json。
要点:
coreHost/corePort:与daemon_config.json中edgeIngress一致。edgeId:HELLO 与会话绑定;TREE_PROPOSE必须相同。edgeDiscoveryEnabled(bool,默认true):在 TCP 连接且 HELLO 成功 后启动 udev 发现协调器,将串口以op: upsert写入核心设备树(需 Linux +libudev)。设为false可仅依赖手工TREE_PROPOSE或核心下发树。endpoint:用于计算endpointHash(与核心一致:qHash(endpoint)即 Qt 默认字符串哈希)。fakeDeviceId:组装routingKey = (endpointHash << 32) | deviceId与核心makeRoutingKey一致。fakeIntervalMs:设为0可关闭假数据定时器;真实串口由核心下发的设备树节点驱动(type/endpoint可识别为 Serial,且params.online为 true)。节点params.deviceId会写入上行RawBusMessage::deviceId(未设则-1)。
运维 HTTP
若 opsListenPort > 0,监听 127.0.0.1:opsListenPort:
GET /:返回localTreePath文件内容(无文件则返回占位 HTML,含指向配置页的链接)。GET /ui:阶段 5 简易配置页——从GET /discovered同源列表选择已发现串口节点,填写params.protocol(如modbus_rtu)、波特率等,提交后由边缘组装op: upsert的TREE_PROPOSE发往核心(使用当前会话的baseTreeRevision,须已 HELLO 且收到过TREE_RESULT)。POST /register_discovered:可由浏览器表单(application/x-www-form-urlencoded)或 JSON 调用;字段含nodeId(必填,一般为edges/<edgeId>/discovered/<stableKey>)、devnode(可选,若不在发现列表中需填/dev/tty…)、protocol、baudRate、name。表单提交成功返回简短 HTML 确认页;JSON 请求返回{"accepted":true,"sentNodeId":...}。若尚未拿到有效treeRevision,返回 503。GET /discovered:返回最近 udev 发现事件 JSON({ "items": [ ... ] }),便于无核心时调试;与EdgeDiscoveryCoordinator内存环缓冲一致(最多约 64 条)。POST /propose:body 为 完整CTRL_TREE_PROPOSEJSON(含edgeId、baseTreeRevision、entries),将原样经 TCP 发往核心。
示例:
curl -s http://127.0.0.1:9080/
curl -s http://127.0.0.1:9080/ui
curl -s http://127.0.0.1:9080/discovered
curl -s -X POST http://127.0.0.1:9080/register_discovered \
-H 'Content-Type: application/json' \
-d '{"nodeId":"edges/edge-dev-1/discovered/12345","protocol":"modbus_rtu","baudRate":115200}'
curl -s -X POST http://127.0.0.1:9080/propose \
-H 'Content-Type: application/json' \
-d '{"edgeId":"edge-dev-1","baseTreeRevision":1,"entries":[{"id":"edges/edge-dev-1/gw","patch":{"name":"gw"}}]}'
(entries 中节点 id 必须满足核心 DeviceTreeModel::nodeBelongsToEdge 规则。)
本地树文件
TREE_FULL 落盘格式为 { "treeRevision", "edgeId", "tree": [ ... ] }。EdgeDeviceBus 会将其中的 tree 当作 device_tree 加载,并对 Serial 与 CAN(endpoint 形如 can:vcan0,type/endpoint 推断为 CAN)执行 reconcile:打开设备后读到的数据经 EdgeTcpUplinkPort 编码为 DATA_RAWBUS 发往核心。与核心真源同步仍通过 TREE_PROPOSE(含边缘 upsert 自动注册)、核心侧 D-Bus patch_device_tree_node 或运维 push_edge_tree。
发现 → 注册流程(简要)
- 边缘连接核心并 HELLO;核心下发
TREE_FULL,本地落盘并 reconcile 已有节点。 edgeDiscoveryEnabled为真时,EdgeDiscoveryCoordinator扫描/监听 udev 串口 add/remove,在拿到有效baseTreeRevision(来自TREE_RESULT)后发送TREE_PROPOSE:op: upsert注册edges/<edgeId>/discovered/<stableKey>,remove 时patchparams.online: false。- 核心
applyEdgePropose成功后再次TREE_FULL;边缘 reload 树文件后对 Serial/CAN 执行 reconcile,raw 仅上行。