xross_platform_sdk
v1.0.4
Published
xross平台SDK
Readme
Xross Platform SDK
园区巡检平台机器狗侧通信 SDK,封装 MQTT 控制面 + HTTP 数据面的协议交互。
安装
npm install xross_platform_sdk通信架构
┌──────────────┐ MQTT ┌──────────────┐ MQTT ┌──────────────┐
│ 巡检平台 │ ◄────────► │ MQTT Broker │ ◄────────► │ 机器狗 Agent │
│ │ │ │ │ (本 SDK) │
└──────┬───────┘ └──────────────┘ └──────┬───────┘
│ │
│ HTTP(设备注册 / 媒体上传) │
└────────────────────────────────────────────────────────┘| 通道 | 协议 | 用途 | QoS | |---|---|---|---| | 控制面 | MQTT | 心跳、任务上下行、状态上报、故障、AI 事件、远程控制 | 上行 QoS 0/1,下行 QoS 1 | | 数据面 | HTTP | 设备注册、图片/视频上传 | — |
快速开始
import { RobotSDK } from 'xross_platform_sdk'
const sdk = new RobotSDK({
robotId: 'robot-001',
model: 'donkey-run-fast-S95',
firmwareVersion: '1.0.0',
mqtt: {
brokerUrl: 'mqtt://192.168.1.100:1883',
username: '',
password: '',
reconnectDelays: [10_000, 30_000, 60_000],
},
http: {
baseUrl: 'http://192.168.1.200:8080',
deviceToken: 'your-device-token',
},
logPath: 'logs/robot.log',
reconnectLogPath: 'logs/reconnect.log',
})
// 监听下行指令
sdk.onTaskDispatch((msg) => { /* 处理任务下发 */ })
sdk.onTaskStop((msg) => { /* 处理任务停止 */ })
sdk.onPathQuery((msg) => { /* 处理路径查询 */ })
sdk.onControl((msg) => { /* 处理远程控制 */ })
// 连接 → 注册
await sdk.connect()
// 开始上报心跳
setInterval(() => {
sdk.sendHeartbeat({
businessState: 'patrolling',
battery: 85,
position: { x: 12.34, y: 56.78, z: 0, yaw: 1.57 },
})
}, 3000)完整示例见 examples/basic-usage.ts。
配置
RobotSDKConfig
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| robotId | string | ✅ | — | 机器狗唯一编号,需与平台建档一致 |
| model | string | ❌ | — | 设备型号 |
| firmwareVersion | string | ❌ | — | 固件版本 |
| mqtt | MQTTConfig | ✅ | — | MQTT 连接配置 |
| http | HTTPConfig | ✅ | — | HTTP 连接配置 |
| logPath | string \| null | ❌ | logs/robot.log | 业务日志路径,null 关闭 |
| logMaxSize | number | ❌ | 10485760 (10 MB) | 单日志文件最大字节 |
| logMaxFiles | number | ❌ | 3 | 归档保留份数 |
| reconnectLogPath | string \| null | ❌ | logs/reconnect.log | 重连日志路径,null 关闭 |
MQTTConfig
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| brokerUrl | string | ✅ | — | MQTT Broker 地址,如 mqtt://192.168.1.100:1883 |
| username | string | ❌ | — | 鉴权用户名 |
| password | string | ❌ | — | 鉴权密码 |
| reconnectDelays | number[] | ❌ | [10000, 30000, 60000] | 重连退避间隔 (ms),轮转到末尾后保持 |
HTTPConfig
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| baseUrl | string | ✅ | 平台后端地址 |
| deviceToken | string | ✅ | 设备长期凭证,平台管理员生成 |
API 参考
连接与生命周期
const registeredAt = await sdk.connect() // 连接 MQTT → HTTP 注册,返回注册时间戳
await sdk.disconnect() // 断开连接,停止重连
sdk.isConnected // boolean重连机制:断线后自动按 reconnectDelays 退避重连。重连成重置计数器,主动 disconnect() 不触发重连。
事件:
sdk.on('reconnect', () => { /* 开始重连 */ })
sdk.on('reconnect_done', () => { /* 重连成功 */ })
sdk.on('disconnect', () => { /* 连接断开 */ })
sdk.on('error', (err) => { /* 错误 */ })
sdk.on('msg_ack', (msg) => { /* 平台已收到某条上行消息 */ })心跳
sdk.sendHeartbeat({
businessState: 'patrolling', // idle | patrolling | charging | fault
battery: 85, // 0–100
position: { x: 12, y: 56, z: 0, yaw: 1.57 },
task: { // 可选:有任务时附带进度
taskId: 'TASK-001',
status: 'running',
currentWaypointId: 'WP-003',
completedWaypointCount: 2,
},
})任务状态上报
sdk.reportTaskStatus({
taskId: 'TASK-001',
status: 'running', // pending | running | completed | failed | stopped
currentWaypointId: 'WP-002', // 可选
message: '已到达第2个巡检点', // 可选
})点位动作结果
sdk.reportWaypointResult({
taskId: 'TASK-001',
waypointId: 'WP-002',
actionType: 'capture_photo', // stay | capture_photo | record_video | broadcast | detect
result: 'success', // success | failed | skipped
startedAt: 1712500000,
finishedAt: 1712500005,
medias: [ // 可选
{ mediaId: 'MEDIA-001', mediaType: 'image', fileUrl: 'http://...', fileSize: 204800 },
],
errorCode: null, // 可选
errorMessage: null, // 可选
})AI 检测事件
sdk.reportDetectionEvent({
eventId: `evt_${Date.now()}`,
eventType: 'intrusion', // garbage_overflow | intrusion | equipment_abnormal | vehicle_inspection
eventName: '人员闯入',
confidence: 0.95,
taskId: 'TASK-001', // 可选
waypointId: 'WP-003', // 可选
position: { x: 15, y: 22, z: 0, yaw: 0 }, // 可选
medias: [...], // 可选
description: '检测到未授权人员', // 可选
})故障上报
sdk.reportFault({
faultCode: 'BAT_001', // NAV_001/002 | HW_001/002 | NET_001 | BAT_001
faultMessage: '电池电量过低',
canContinue: false, // 故障后能否继续执行
taskId: 'TASK-001', // 可选
position: { x: 12, y: 56, z: 0, yaw: 0 }, // 可选
})路径查询回复
sdk.reportPathResult({
msgType: 'path_result',
requestId: 'REQ-PATH-001',
robotId: 'robot-001',
timestamp: 1712500000,
result: 'success', // success | failed
path: [
{ x: 0, y: 0, z: 0 },
{ x: 2.5, y: 5, z: 0 },
],
pathLengthM: 22.36, // 可选
})下行指令监听
// 任务下发
sdk.onTaskDispatch((msg) => {
// msg: { commandId, taskId, routeId, routeName?, sceneId?
// waypoints: TaskWaypoint[], forbiddenZones?: ForbiddenZone[], path?: PathPoint[] }
sdk.sendCommandAck(msg.commandId)
})
// 任务停止
sdk.onTaskStop((msg) => {
// msg: { commandId, taskId, reason? }
sdk.sendCommandAck(msg.commandId)
})
// 路径规划查询
sdk.onPathQuery((msg) => {
// msg: { requestId, waypoints: PathWaypoint[], startPosition?, forbiddenZones? }
// 计算路径后调用 reportPathResult 回复
})
// 远程控制(6.7 协议)
sdk.onControl((msg) => {
// msg: { command: ControlCommand, speed: SpeedLevel }
})远程控制指令(6.7)
Topic:platform/{robotId}/control
| 指令 | 交互方式 | 说明 |
|---|---|---|
| forward / backward | 按持 | 前进 / 后退,松开自动 stop |
| left / right | 按持 | 左移 / 右移,松开自动 stop |
| turn_left / turn_right | 按持 | 左转 / 右转,松开自动 stop |
| speed_up / speed_down | 点按 | 加速 / 减速,速度档位 1-5 |
| stop | 点按 / 松开自动触发 | 停止 |
import { HOLD_COMMANDS, TAP_COMMANDS } from 'xross_platform_sdk'
sdk.onControl((msg) => {
if (HOLD_COMMANDS.has(msg.command)) {
// 按持:持续移动
chassis.move(msg.command, msg.speed)
} else if (msg.command === 'stop') {
chassis.stop()
} else {
// speed_up / speed_down:调速
adjustSpeed(msg.command)
}
})指令 ACK
sdk.sendCommandAck('command-id-xxx')媒体上传 + 上报
import { readFileSync } from 'node:fs'
// 上传图片 + 上报点位结果
await sdk.uploadAndReportWaypointResult(
readFileSync('./photo.jpg'), 'photo.jpg',
{
taskId: 'TASK-001',
waypointId: 'WP-001',
actionType: 'capture_photo',
result: 'success',
startedAt: 1712500000,
finishedAt: 1712500002,
},
)
// 上传截图 + 上报检测事件
await sdk.uploadAndReportDetectionEvent(
readFileSync('./detection.jpg'), 'detection.jpg',
{
eventId: 'evt_001',
eventType: 'intrusion',
eventName: '人员闯入',
confidence: 0.95,
taskId: 'TASK-001',
waypointId: 'WP-003',
},
)自动根据扩展名判断媒体类型:
.mp4/.avi/.mov/.mkv→video,其他 →image
查询当前任务
const job = await sdk.getCurrentJob('robot-001')
if (job) {
console.log(`当前任务: ${job.task.taskId}, 状态: ${job.task.status}`)
} else {
console.log('无当前任务')
}日志
const logger = sdk.getLogger() // Logger 实例,null 表示日志已关闭
logger?.info('自定义日志')
logger?.warn('警告')
logger?.error('错误')
logger?.debug('调试')| 日志文件 | 内容 |
|---|---|
| logs/robot.log | 业务日志(SDK 内部 + 自定义) |
| logs/reconnect.log | 重连日志(连接/断开/重连尝试) |
超过 logMaxSize(默认 10 MB)自动归档为 .1、.2、.3,循环覆盖。
底层客户端
不需要 SDK 封装时,可直接用底层客户端:
import { HTTPClient, MQTTClient } from 'xross_platform_sdk'
// HTTP
const http = new HTTPClient({ baseUrl: '...', deviceToken: '...' })
await http.registerRobot('robot-001', { model: 'X', firmwareVersion: '1.0' })
await http.uploadMedia('robot-001', buffer, 'photo.jpg', 'image', 'TASK-001', 'WP-001')
// MQTT
const mqtt = new MQTTClient('robot-001', { brokerUrl: 'mqtt://...' })
await mqtt.connect()
mqtt.on('task_dispatch', (msg) => { ... })
mqtt.on('control', (msg) => { ... })
mqtt.publishHeartbeat({ businessState: 'idle', battery: 90 })环境变量
应用层自行从环境变量读取配置(非 SDK 内置),约定如下:
XYZ_ROBOT_PLATFORM_BASEURL= # 平台 HTTP 地址
XYZ_ROBOT_PLATFORM_BROKERURL= # MQTT Broker 地址
XYZ_ROBOT_DEVICE_ID= # 机器人 ID
XYZ_ROBOT_DEVICE_TOKEN= # 设备凭证目录结构
xross_platform_sdk/
src/ # TypeScript 源码(不发布到 npm)
index.ts # 入口
robot-sdk.ts # RobotSDK 主类
mqtt-client.ts # MQTT 客户端
http-client.ts # HTTP 客户端
logger.ts # 循环写日志
types.ts # 类型定义
utils.ts # 坐标转换工具
test.ts # 开发自测(不编译)
dist/ # 编译产物(发布到 npm)
examples/ # 使用示例(发布到 npm)
basic-usage.ts坐标系约定
| 项 | 约定 | |---|---| | 朝向 | ROS 右手系:X 前、Y 左、Z 上 | | 单位 | 米 (m) | | yaw | 弧度,0 = +X 方向,逆时针为正 | | 所有时间字段 | Unix 时间戳(秒) |
