更新时间:2026-02-05 02:36:49下载pdf
为降低客户开发成本,方便扫地机与 App 面板交互,激光扫地机品类 SDK 把虚拟墙、房间属性等复杂控制,封装成不同的 API,应用开发者使用 API 即可完成数据通信。
当前 API 提供了以下方面的功能:
| 功能 | 命令类型标识 | 发起方向 |
|---|---|---|
| 虚拟墙设置 | VIRTUAL_WALL_SET | 面板->设备 |
| 虚拟墙查询 | VIRTUAL_WALL_QUERY | 面板->设备 |
| 禁区设置 | RESTRICTED_AREA_SET | 面板->设备 |
| 禁区查询 | RESTRICTED_AREA_QUERY | 面板->设备 |
| 房间属性设置 | ROOM_PROPERTY_SET | 面板->设备 |
| 房间属性查询 | ROOM_PROPERTY_QUERY | 面板->设备 |
| 选区清扫设置 | ROOM_CLEAN_SET | 面板->设备 |
| 选区清扫查询 | ROOM_CLEAN_QUERY | 面板->设备 |
| 划区清扫设置 | ZONE_CLEAN_SET | 面板->设备 |
| 划区清扫查询 | ZONE_CLEAN_QUERY | 面板->设备 |
| 定点清扫设置 | SPOT_CLEAN_SET | 面板->设备 |
| 定点清扫查询 | SPOT_CLEAN_QUERY | 面板->设备 |
| 预约定时设置 | SCHEDULE_SET | 面板->设备 |
| 预约定时查询 | SCHEDULE_QUERY | 面板->设备 |
| 勿扰定时设置 | QUIET_HOUR_SET | 面板->设备 |
| 勿扰定时查询 | QUIET_HOUR_QUERY | 面板->设备 |
| 地图分区分割 | PART_DIVI_SET | 面板->设备 |
| 地图分区合并 | PART_MERGE_SET | 面板->设备 |
| 地图分区恢复默认 | PART_DEFAULT_SET | 面板->设备 |
| 地图重置 | RESET_CURR_MAP_SET | 面板->设备 |
| 地图保存 | SAVE_CURR_MAP_SET | 面板->设备 |
| 云端地图删除 | DELETE_CLOUD_MAP_SET | 面板->设备 |
| 语音查询 | VOICE_LANGUAGE_QUERY | 面板->设备 |
| 设备信息查询 | DEV_INFO_QUERY | 面板->设备 |
| 密码状态查询 | PASSWORD_STATE_QUERY | 面板->设备 |
| 密码验证 | PASSWORD_CHECK | 面板->设备 |
| 密码设置 | PASSWORD_SET | 面板->设备 |
| 查询当前房间信息 | MCS_ROOM_INFO_QUERY | 面板->设备 |
SDK 通过注册的回调函数向应用传递命令,命令触发分为以下三种场景:
触发场景:用户在 App 面板上进行操作时触发
| 用户操作 | 触发命令 | 触发时机 |
|---|---|---|
| 进入地图编辑界面,在地图上绘制虚拟墙 | VIRTUAL_WALL_SET |
用户点击并确认后 |
| 进入地图编辑界面,设置禁区区域 | RESTRICTED_AREA_SET |
用户完成禁区绘制并确认后 |
| 进入地图编辑界面,修改房间名称/清扫参数 | ROOM_PROPERTY_SET |
用户修改房间属性后立即触发 |
| 进入首页地图界面,选择房间清扫 | ROOM_CLEAN_SET |
用户选择房间并点击开始清扫 |
| 进入首页地图界面,划区清扫 | ZONE_CLEAN_SET |
用户在地图上划定区域并点击开始清扫 |
| 进入首页地图界面,定点清扫 | SPOT_CLEAN_SET |
用户点击地图上的某个点位并点击开始清扫 |
| 进入设备设置界面,创建/修改预约清扫 | SCHEDULE_SET |
用户设置定时任务后 |
| 进入设备设置界面,设置勿扰时段 | QUIET_HOUR_SET |
用户配置勿扰时间后 |
| 进入地图编辑界面,分割房间 | PART_DIVI_SET |
用户在地图上划分割线 |
| 进入地图编辑界面,合并房间 | PART_MERGE_SET |
用户选择两个房间合并 |
| 进入地图编辑界面,恢复默认分区 | PART_DEFAULT_SET |
用户点恢复默认按钮 |
| 进入地图编辑界面,重置地图 | RESET_CURR_MAP_SET |
用户点击"重置地图"确认后 |
| 进入地图编辑界面,保存地图 | SAVE_CURR_MAP_SET |
用户点击保存当前地图 |
| 进入多地图管理界面,删除云端地图 | DELETE_CLOUD_MAP_SET |
用户选择地图并点击删除 |
| 进入视频通道,验证密码 | PASSWORD_CHECK |
用户输入密码提交验证 |
| 进入视频通道,设置密码 | PASSWORD_SET |
用户设置新密码 |
处理流程:
用户操作 → App 面板 → 云端 → SDK 解析 → FUNC_SET_CB 回调 → 应用处理 → 调用response 接口上报结果
触发场景:用户打开 App 面板或下拉刷新时触发
| 查询命令 | 触发时机 | 预期响应 |
|---|---|---|
VIRTUAL_WALL_QUERY |
进入首页地图页面 | 返回当前地图上所有虚拟墙 |
RESTRICTED_AREA_QUERY |
进入首页地图页面 | 返回当前地图上所有禁区 |
ROOM_PROPERTY_QUERY |
进入首页地图页面 | 返回所有房间的属性信息 |
ROOM_CLEAN_QUERY |
选区清扫页面 | 返回上次选区清扫的配置 |
ZONE_CLEAN_QUERY |
划区清扫页面 | 返回上次划区清扫的参数 |
SPOT_CLEAN_QUERY |
定点清扫页面 | 返回上次定点清扫的配置 |
SCHEDULE_QUERY |
打开定时任务页面 | 返回所有预约清扫任务 |
QUIET_HOUR_QUERY |
打开勿扰设置页面 | 返回勿扰时段配置 |
VOICE_LANGUAGE_QUERY |
进入语音设置页面 | 返回当前语音包状态 |
DEV_INFO_QUERY |
进入设备设置页面 | 返回设备详细信息 |
MAP_EMPTY_QUERY |
App 首页地图加载(备用功能) |
返回是否存在地图数据 |
PASSWORD_STATE_QUERY |
进入密码设置页面 | 返回密码是否已设置 |
MCS_ROOM_INFO_QUERY |
Alexa 语音控制 |
返回设备当前所在房间 |
处理流程:
面板刷新 → 云端 → SDK 解析 → FUNC_QUERY_CB 回调 → 应用查询数据 → 调用response 接口上报结果
功能说明:虚拟墙是在地图上设置的虚拟屏障线,机器人不会跨越该线进行清扫。
数据结构:
```C
/**
* @brief Forbidden modes
*/
typedef enum {
FORBIT_ALL = 0, // All prohibited
FORBIT_SWEEP, // Prohibit mopping
FORBIT_MOP, // Prohibit sweeping
FORBIT_RESERVE, // Not set, reserved
} FORBIT_MODE_E;
/**
* @brief Coordinate point structure
*/
typedef struct {
int x; // X value of the coordinate point
int y; // Y value of the coordinate point
} POINT_COOR_S;
/**
* @brief Virtual line coordinate structure
*/
typedef struct {
FORBIT_MODE_E mode; // Forbidden mode
POINT_COOR_S points[2]; // Endpoints of the line, first element is the starting point of the virtual wall, second element is the ending point of the virtual wall
} VIRTUAL_LINE_S;
/**
* @brief Virtual wall structure
*/
typedef struct {
int num; // Number of virtual walls
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
VIRTUAL_LINE_S* line; // Virtual wall coordinate points and forbidden mode
} VIRTUAL_WALL_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收面板设置的虚拟墙数量 | 填充当前虚拟墙总数 | 填充当前虚拟墙总数 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
line |
数组指针 | 解析每条虚拟墙的坐标和模式 | 填充所有虚拟墙信息 | 填充所有虚拟墙信息 |
line[i].mode |
枚举 | 虚拟墙模式(全禁/禁扫/禁拖) | 填充虚拟墙模式 | 填充虚拟墙模式 |
line[i].points[0] |
坐标 | 虚拟墙起点 (x0, y0) | 填充起点坐标 | 填充起点坐标 |
line[i].points[1] |
坐标 | 虚拟墙终点 (x1, y1) | 填充终点坐标 | 填充终点坐标 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_virtual_wall_set(VIRTUAL_WALL_S* p_virtual_wall)
{
PR_DEBUG("收到虚拟墙设置命令,虚拟墙数量: %d", p_virtual_wall->num);
// 遍历所有虚拟墙
for(int i = 0; i < p_virtual_wall->num; i++) {
PR_DEBUG("虚拟墙[%d] 模式: %d", i, p_virtual_wall->line[i].mode);
PR_DEBUG(" 起点: (%d, %d)",
p_virtual_wall->line[i].points[0].x,
p_virtual_wall->line[i].points[0].y);
PR_DEBUG(" 终点: (%d, %d)",
p_virtual_wall->line[i].points[1].x,
p_virtual_wall->line[i].points[1].y);
// TODO: 将虚拟墙数据保存到设备内存/持久化存储
// save_virtual_wall_to_device(i, &p_virtual_wall->line[i]); //伪代码,需要开发者自行实现
}
// 处理完成后上报结果
VIRTUAL_WALL_S report_data;
report_data.num = p_virtual_wall->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.line = p_virtual_wall->line;
return ty_rvc_virtual_wall_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_virtual_wall_query(void)
{
PR_DEBUG("收到虚拟墙查询命令");
// 从设备获取当前虚拟墙数据
VIRTUAL_WALL_S query_data;
VIRTUAL_LINE_S lines[10]; // 假设最多10条虚拟墙
query_data.num = get_virtual_wall_count(); // 获取虚拟墙数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.line = lines;
// 填充每条虚拟墙数据
for(int i = 0; i < query_data.num; i++) {
// load_virtual_wall_from_device(i, &lines[i]);//伪代码,需要开发者自行实现
lines[i].mode = FORBIT_ALL;
lines[i].points[0].x = 100;
lines[i].points[0].y = 200;
lines[i].points[1].x = 500;
lines[i].points[1].y = 200;
}
return ty_rvc_virtual_wall_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图实际距离 = 栅格数量 × 栅格分辨率line 数组及相关内存由应用自行分配和管理,SDK不会释放该内存功能说明:禁区是地图上的多边形区域(通常为矩形),机器人不会进入该区域清扫。
数据结构:
```c
typedef struct {
int len; // string length
char* name; // string memory points
} STR_ELEMENT_S;
/**
* @brief Area coordinate point structure
*/
typedef struct {
int point_num; // Number of endpoints forming the area
POINT_COOR_S* point; // Endpoint coordinates forming the restricted area
} AREA_S;
/**
* @brief Virtual area structure
*/
typedef struct {
FORBIT_MODE_E mode; // Forbidden mode
AREA_S area; // Endpoint coordinates of the restricted area
STR_ELEMENT_S cur_name; // Name of the restricted area
} VIRTUAL_AREA_S;
/**
* @brief Restricted area structure
*/
typedef struct {
int num; // Number of restricted areas
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
VIRTUAL_AREA_S* restrict_zone; // Coordinates and forbidden mode of the restricted area
} RESTRICTED_AREA_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收面板设置的禁区数量 | 填充当前禁区总数 | 填充当前禁区总数 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图 ID | 必须填充当前地图ID |
restrict_zone |
数组指针 | 解析每个禁区的信息 | 填充所有禁区信息 | 填充所有禁区信息 |
restrict_zone[i].mode |
枚举 | 禁区模式(全禁/禁扫/禁拖) | 填充禁区模式 | 填充禁区模式 |
restrict_zone[i].area |
区域结构 | 禁区的多边形坐标点集合 | 填充区域坐标 | 填充区域坐标 |
restrict_zone[i].area.point_num |
int | 禁区顶点数量(通常为4) |
填充顶点数量 | 填充顶点数量 |
restrict_zone[i].area.point |
坐标数组 | 禁区各顶点坐标 | 填充各顶点坐标 | 填充各顶点坐标 |
restrict_zone[i].cur_name |
字符串 | 禁区名称 | 填充禁区名称 | 填充禁区名称 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_restricted_area_set(RESTRICTED_AREA_S* p_restricted_area)
{
PR_DEBUG("收到禁区设置命令,禁区数量: %d", p_restricted_area->num);
// 遍历所有禁区
for(int i = 0; i < p_restricted_area->num; i++) {
PR_DEBUG("禁区[%d] 模式: %d", i, p_restricted_area->restrict_zone[i].mode);
PR_DEBUG(" 名称: %.*s",
p_restricted_area->restrict_zone[i].cur_name.len,
p_restricted_area->restrict_zone[i].cur_name.name);
PR_DEBUG(" 顶点数量: %d",
p_restricted_area->restrict_zone[i].area.point_num);
// 遍历禁区的所有顶点
for(int j = 0; j < p_restricted_area->restrict_zone[i].area.point_num; j++) {
PR_DEBUG(" 顶点[%d]: (%d, %d)", j,
p_restricted_area->restrict_zone[i].area.point[j].x,
p_restricted_area->restrict_zone[i].area.point[j].y);
}
// TODO: 将禁区数据保存到设备内存/持久化存储
// save_restricted_area_to_device(i, &p_restricted_area->restrict_zone[i]);//伪代码,需要开发者自行实现
}
// 处理完成后上报结果
RESTRICTED_AREA_S report_data;
report_data.num = p_restricted_area->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.restrict_zone = p_restricted_area->restrict_zone;
return ty_rvc_restricted_area_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_restricted_area_query(void)
{
PR_DEBUG("收到禁区查询命令");
// 从设备获取当前禁区数据
RESTRICTED_AREA_S query_data;
VIRTUAL_AREA_S areas[5]; // 假设最多5个禁区
POINT_COOR_S area_points[5][4]; // 每个禁区4个顶点
query_data.num = get_restricted_area_count(); // 获取禁区数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.restrict_zone = areas;
// 填充每个禁区数据
for(int i = 0; i < query_data.num; i++) {
// load_restricted_area_from_device(i, &areas[i]);//伪代码,需要开发者自行实现
// 示例:设置禁区模式
areas[i].mode = FORBIT_ALL;
// 示例:设置禁区名称
areas[i].cur_name.name = "禁区1";
areas[i].cur_name.len = strlen(areas[i].cur_name.name);
// 示例:设置禁区区域(矩形4个顶点)
areas[i].area.point_num = 4;
areas[i].area.point = area_points[i];
// 填充矩形4个顶点坐标(逆时针或顺时针)
area_points[i][0].x = 100; area_points[i][0].y = 100; // 左下
area_points[i][1].x = 200; area_points[i][1].y = 100; // 右下
area_points[i][2].x = 200; area_points[i][2].y = 200; // 右上
area_points[i][3].x = 100; area_points[i][3].y = 200; // 左上
}
return ty_rvc_restricted_area_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图4个顶点)point_num 确定顶点数量实际距离 = 栅格数量 × 栅格分辨率cur_name 字段需要同时填充 name 指针和 len 长度restrict_zone 数组、内部的 point 数组以及 cur_name.name 字符串内存由应用自行分配和管理,SDK不会释放这些内存功能说明:房间属性管理包括房间命名、清扫模式、清扫顺序、地板类型等参数配置。
数据结构:
```C
/**
* @brief Cleaning parameters
*/
typedef struct {
int valid; // Whether the parameter is valid
STR_ELEMENT_S suction; // Suction power setting, specific values should be agreed upon with the project
STR_ELEMENT_S cistern; // Water volume setting, specific values should be agreed upon with the project
bool y_mop; // Y-shaped mopping, TRUE for Y-shaped mopping to take effect
int clean_cnt; // Number of room cleanings
} CLEAN_PARAM_S;
/**
* @brief Room property structure
*/
typedef struct {
int num; // Number of rooms
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
int* ids; // Room ID numbers, each room corresponds to one ID number
STR_ELEMENT_S* sweep_mode; // room sweep mode,each room corresponds to one sweep mode
CLEAN_PARAM_S* param; // Cleaning parameters for rooms, each room corresponds to one cleaning setting parameter, param[0] corresponds to ids[0] area
int* orders; // Cleaning order for rooms, each room corresponds to one cleaning order, cleaning order is represented by non-zero Arabic numerals, smaller values indicate higher cleaning priority, zero represents the lowest priority
STR_ELEMENT_S* cus_name; // Room naming list, each room corresponds to a name, cus_name[0] corresponds to id[0]
int* floor_type; // Room floor types,each room corresponds to one floor type
} ROOM_PROPERTY_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收房间数量 | 填充当前房间总数 | 填充当前房间总数 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
ids |
int数组 | 解析各房间ID | 填充所有房间ID | 填充所有房间ID |
sweep_mode |
字符串数组 | 解析清扫模式(字符串格式) | 填充清扫模式字符串 | 填充清扫模式字符串 |
param |
清扫参数数组 | 解析各房间清扫参数 | 填充各房间清扫参数 | 填充各房间清扫参数 |
param[i].valid |
int | 参数有效标志(备用字段) | 填充有效标志 | 填充有效标志 |
param[i].suction |
字符串 | 吸力档位(字符串格式) | 填充吸力字符串 | 填充吸力字符串 |
param[i].cistern |
字符串 | 水量档位(字符串格式) | 填充水量字符串 | 填充水量字符串 |
param[i].y_mop |
bool | Y字拖地开关 | 填充Y字拖开关 | 填充Y字拖开关 |
param[i].clean_cnt |
int | 清扫次数 | 填充清扫次数 | 填充清扫次数 |
orders |
int数组 | 清扫顺序(数字越小优先级越高) | 填充清扫顺序 | 填充清扫顺序 |
cus_name |
字符串数组 | 房间自定义名称 | 填充房间名称 | 填充房间名称 |
floor_type |
int数组 | 地板类型(备用字段,如需实现,需要与面板对齐地板类型) | 填充地板类型 | 填充地板类型 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_room_property_set(ROOM_PROPERTY_S* p_room_property)
{
PR_DEBUG("收到房间属性设置命令,房间数量: %d", p_room_property->num);
// 遍历所有房间
for(int i = 0; i < p_room_property->num; i++) {
PR_DEBUG("房间[%d] ID: %d", i, p_room_property->ids[i]);
// 解析房间名称
if(p_room_property->cus_name) {
PR_DEBUG(" 名称: %d-%s",
p_room_property->cus_name[i].len,
p_room_property->cus_name[i].name);
}
// 解析清扫模式(字符串格式,需转换为枚举)
if(p_room_property->sweep_mode) {
PR_DEBUG(" 清扫模式: %d-%s",
p_room_property->sweep_mode[i].len,
p_room_property->sweep_mode[i].name);
// TODO: 将字符串转换为枚举值
// int mode_enum = convert_sweep_mode_str_to_enum(&p_room_property->sweep_mode[i]); //伪代码,需要开发者自行实现
}
// 解析清扫参数
if(p_room_property->param) {
PR_DEBUG(" 吸力: %d-%s",
p_room_property->param[i].suction.len,
p_room_property->param[i].suction.name);
PR_DEBUG(" 水量: %d-%s",
p_room_property->param[i].cistern.len,
p_room_property->param[i].cistern.name);
PR_DEBUG(" Y字拖: %d", p_room_property->param[i].y_mop);
PR_DEBUG(" 清扫次数: %d", p_room_property->param[i].clean_cnt);
}
// 解析清扫顺序
if(p_room_property->orders) {
PR_DEBUG(" 清扫顺序: %d", p_room_property->orders[i]);
}
// 解析地板类型
if(p_room_property->floor_type) { //预留功能,如需实现,需要与面板对齐地板类型
PR_DEBUG(" 地板类型: %d", p_room_property->floor_type[i]);
}
// TODO: 将房间属性保存到设备内存/持久化存储
// save_room_property_to_device(i, ...); //伪代码,需要开发者自行实现
}
// 处理完成后上报结果
ROOM_PROPERTY_S report_data;
report_data.num = p_room_property->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.ids = p_room_property->ids;
report_data.sweep_mode = p_room_property->sweep_mode;
report_data.param = p_room_property->param;
report_data.orders = p_room_property->orders;
report_data.cus_name = p_room_property->cus_name;
report_data.floor_type = p_room_property->floor_type;
return ty_rvc_room_property_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_room_property_query(void)
{
PR_DEBUG("收到房间属性查询命令");
// 从设备获取当前房间属性数据
ROOM_PROPERTY_S query_data;
int room_ids[10]; // 房间ID数组
STR_ELEMENT_S sweep_modes[10]; // 清扫模式数组
CLEAN_PARAM_S params[10]; // 清扫参数数组
int orders[10]; // 清扫顺序数组
STR_ELEMENT_S room_names[10]; // 房间名称数组
int floor_types[10]; // 地板类型数组
query_data.num = get_room_count(); // 获取房间数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.ids = room_ids;
query_data.sweep_mode = sweep_modes;
query_data.param = params;
query_data.orders = orders;
query_data.cus_name = room_names;
query_data.floor_type = floor_types;
// 填充每个房间的数据
for(int i = 0; i < query_data.num; i++) {
// 填充房间ID
room_ids[i] = get_room_id(i);
// 填充房间名称
room_names[i].name = get_room_name(i); // 例如: "客厅"
room_names[i].len = strlen(room_names[i].name);
// 填充清扫模式(字符串格式)
sweep_modes[i].name = "only_sweep"; // 例如: "only_sweep","only_mop","both_work"
sweep_modes[i].len = strlen(sweep_modes[i].name);
// 填充清扫参数
params[i].suction.name = "strong"; // 例如: closed","gentle","normal","strong","max
params[i].suction.len = strlen(params[i].suction.name);
params[i].cistern.name = "middle"; // 例如: closed","low","middle","high"
params[i].cistern.len = strlen(params[i].cistern.name);
params[i].y_mop = true;
params[i].clean_cnt = 2;
// 填充清扫顺序(1最高,0最低)
orders[i] = i + 1;
// 填充地板类型(预留字段)
floor_types[i] = 1; // 例如: 0=瓷砖, 1=木地板, 2=地毯
}
return ty_rvc_room_property_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图ty_rvc_room_property_data_response() 上报最新房间属性sweep_mode、cus_name、suction、cistern 均为字符串格式name 指针和 len 长度"only_sweep" / "only_mop" / "both_work""closed" / "gentle" / ""normal"" / "strong" / "max""closed" / "low" / "middle" / "high"ids 数组一一对应ids[0] 对应 cus_name[0]、sweep_mode[0]、param[0]、orders[0]、floor_type[0]ids、sweep_mode、param、orders、floor_material、room_name 等)及字符串内存(suction.name、cistern.name、sweep_mode[i].name 等)由应用自行分配和管理,SDK不会释放这些内存功能说明:选区清扫允许用户选择一个或多个房间进行清扫,可为每个房间配置独立的清扫模式和参数。
数据结构:
```c
/**
* @brief Cleaning parameters
*/
typedef struct {
int valid; // Whether the parameter is valid
STR_ELEMENT_S suction; // Suction power setting, specific values should be agreed upon with the project
STR_ELEMENT_S cistern; // Water volume setting, specific values should be agreed upon with the project
bool y_mop; // Y-shaped mopping, TRUE for Y-shaped mopping to take effect
int clean_cnt; // Number of room cleanings
} CLEAN_PARAM_S;
/**
* @brief Selected area cleaning structure
*/
typedef struct {
int num; // Number of selected areas
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
int* ids; // List of IDs for the selected area rooms
STR_ELEMENT_S* sweep_mode; // sweep mode for the selected area rooms
CLEAN_PARAM_S* param; // Cleaning parameters for selected areas, each room corresponds to one cleaning parameter, param[0] corresponds to ids[0] area, if not set valid is 0
} ROOM_CLEAN_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收选中的房间数量 | 填充上次选区清扫的房间数量 | 填充当前选区清扫的房间数量 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
ids |
int数组 | 解析选中的房间ID列表 | 填充上次选中的房间ID | 填充当前选中的房间ID |
sweep_mode |
字符串数组 | 解析各房间清扫模式(字符串格式) | 填充各房间清扫模式字符串 | 填充各房间清扫模式字符串 |
param |
清扫参数数组 | 解析各房间清扫参数 | 填充各房间清扫参数 | 填充各房间清扫参数 |
param[i].valid |
int | 参数有效标志(备用字段) | 填充有效标志 | 填充有效标志 |
param[i].suction |
字符串 | 吸力档位(字符串格式) | 填充吸力字符串 | 填充吸力字符串 |
param[i].cistern |
字符串 | 水量档位(字符串格式) | 填充水量字符串 | 填充水量字符串 |
param[i].y_mop |
bool | Y字拖地开关 | 填充Y字拖开关 | 填充Y字拖开关 |
param[i].clean_cnt |
int | 清扫次数 | 填充清扫次数 | 填充清扫次数 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_room_clean_set(ROOM_CLEAN_S* p_room_clean)
{
PR_DEBUG("收到选区清扫设置命令,房间数量: %d", p_room_clean->num);
// 遍历所有选中的房间
for(int i = 0; i < p_room_clean->num; i++) {
PR_DEBUG("房间[%d] ID: %d", i, p_room_clean->ids[i]);
// 解析清扫模式(字符串格式,需转换为枚举)
if(p_room_clean->sweep_mode) {
PR_DEBUG(" 清扫模式:%d-%s",
p_room_clean->sweep_mode[i].len,
p_room_clean->sweep_mode[i].name);
// TODO: 将字符串转换为枚举值
// int mode_enum = convert_sweep_mode_str_to_enum(&p_room_clean->sweep_mode[i]);//伪代码,需要开发者自行实现
}
// 解析清扫参数
PR_DEBUG(" 吸力: %d-%s",
p_room_clean->param[i].suction.len,
p_room_clean->param[i].suction.name);
PR_DEBUG(" 水量: %d-%s",
p_room_clean->param[i].cistern.len,
p_room_clean->param[i].cistern.name);
PR_DEBUG(" Y字拖: %d", p_room_clean->param[i].y_mop);
PR_DEBUG(" 清扫次数: %d", p_room_clean->param[i].clean_cnt);
// TODO: 保存选区清扫配置
// save_room_clean_config(i, p_room_clean->ids[i], ...);//伪代码,需要开发者自行实现
}
// 启动选区清扫任务
// start_room_clean_task(p_room_clean->ids, p_room_clean->num);//伪代码,需要开发者自行实现
// 处理完成后上报结果
ROOM_CLEAN_S report_data;
report_data.num = p_room_clean->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.ids = p_room_clean->ids;
report_data.sweep_mode = p_room_clean->sweep_mode;
report_data.param = p_room_clean->param;
return ty_rvc_room_clean_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_room_clean_query(void)
{
PR_DEBUG("收到选区清扫查询命令");
// 从设备获取上次选区清扫配置
ROOM_CLEAN_S query_data;
int room_ids[10]; // 房间ID数组
STR_ELEMENT_S sweep_modes[10]; // 清扫模式数组
CLEAN_PARAM_S params[10]; // 清扫参数数组
// 获取上次选区清扫的配置
query_data.num = get_last_room_clean_count(); // 获取上次选中的房间数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.ids = room_ids;
query_data.sweep_mode = sweep_modes;
query_data.param = params;
// 填充每个房间的数据
for(int i = 0; i < query_data.num; i++) {
// 填充房间ID
room_ids[i] = get_last_clean_room_id(i);
// 填充清扫模式(字符串格式)
sweep_modes[i].name = "both_work"; // 例如: "only_sweep","only_mop","both_work"
sweep_modes[i].len = strlen(sweep_modes[i].name);
// 填充清扫参数
params[i].suction.name = "strong"; // 例如: "closed","gentle","normal","strong","max"
params[i].suction.len = strlen(params[i].suction.name);
params[i].cistern.name = "high"; // 例如: "closed","low","middle","high"
params[i].cistern.len = strlen(params[i].cistern.name);
params[i].y_mop = false;
params[i].clean_cnt = 1;
}
return ty_rvc_room_clean_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图sweep_mode、suction、cistern 均为字符串格式name 指针和 len 长度"only_sweep" / "only_mop" / "both_work""closed" / "gentle" / "normal" / "strong" / "max""closed" / "low" / "middle" / "high"ids 数组一一对应ids[0] 对应 sweep_mode[0]、param[0]ids、param)及字符串内存(suction.name、cistern.name、sweep_mode[i].name等)由应用自行分配和管理,SDK不会释放这些内存功能说明:划区清扫允许用户在地图上框选任意多边形区域进行清扫,每个区域可独立配置清扫参数。
数据结构:
```c
/**
* @brief Area coordinate point structure
*/
typedef struct {
int point_num; // Number of endpoints forming the area
POINT_COOR_S* point; // Endpoint coordinates forming the restricted area
} AREA_S;
/**
* @brief Zone parameters structure
*/
typedef struct {
STR_ELEMENT_S mode; // Cleaning mode
CLEAN_PARAM_S param; // Cleaning parameters
AREA_S area; // Area coordinates
STR_ELEMENT_S cur_name; // Area name
} ZONE_AREA_PARAM_S;
/**
* @brief Zone cleaning structure
*/
typedef struct {
int num; // Number of zones
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
ZONE_AREA_PARAM_S* clean_zone; // Cleaning parameters for zone cleaning, each zone corresponds to one cleaning parameter
} ZONE_CLEAN_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收划区数量 | 填充上次划区清扫的区域数量 | 填充当前划区清扫的区域数量 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
clean_zone |
区域参数数组 | 解析所有划区的参数 | 填充上次划区参数 | 填充当前划区参数 |
clean_zone[i].mode |
字符串 | 清扫模式(字符串格式) | 填充清扫模式字符串 | 填充清扫模式字符串 |
clean_zone[i].param |
清扫参数 | 该区域的清扫参数 | 填充清扫参数 | 填充清扫参数 |
clean_zone[i].param.valid |
int | 参数有效标志(备用字段) | 填充有效标志 | 填充有效标志 |
clean_zone[i].param.suction |
字符串 | 吸力档位(字符串格式) | 填充吸力字符串 | 填充吸力字符串 |
clean_zone[i].param.cistern |
字符串 | 水量档位(字符串格式) | 填充水量字符串 | 填充水量字符串 |
clean_zone[i].param.y_mop |
bool | Y字拖地开关 | 填充Y字拖开关 | 填充Y字拖开关 |
clean_zone[i].param.clean_cnt |
int | 清扫次数 | 填充清扫次数 | 填充清扫次数 |
clean_zone[i].area |
区域结构 | 划区的多边形坐标集合 | 填充区域坐标 | 填充区域坐标 |
clean_zone[i].area.point_num |
int | 多边形顶点数量(通常4个) | 填充顶点数量 | 填充顶点数量 |
clean_zone[i].area.point |
坐标数组 | 多边形各顶点坐标 | 填充各顶点坐标 | 填充各顶点坐标 |
clean_zone[i].cur_name |
字符串 | 划区名称 | 填充划区名称 | 填充划区名称 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_zone_clean_set(ZONE_CLEAN_S* p_zone_clean)
{
PR_DEBUG("收到划区清扫设置命令,划区数量: %d", p_zone_clean->num);
// 遍历所有划区
for(int i = 0; i < p_zone_clean->num; i++) {
PR_DEBUG("划区[%d]:", i);
// 解析划区名称
if(p_zone_clean->clean_zone[i].cur_name.name) {
PR_DEBUG(" 名称: %d-%s",
p_zone_clean->clean_zone[i].cur_name.len,
p_zone_clean->clean_zone[i].cur_name.name);
}
// 解析清扫模式(字符串格式,需转换为枚举)
PR_DEBUG(" 清扫模式: %d-%s",
p_zone_clean->clean_zone[i].mode.len,
p_zone_clean->clean_zone[i].mode.name);
// TODO: 将字符串转换为枚举值
// int mode_enum = convert_sweep_mode_str_to_enum(&p_zone_clean->clean_zone[i].mode);//伪代码,需要开发者自行实现
// 解析清扫参数
CLEAN_PARAM_S* param = &p_zone_clean->clean_zone[i].param;
PR_DEBUG(" 吸力: %d-%s", param->suction.len, param->suction.name);
PR_DEBUG(" 水量: %d-%s", param->cistern.len, param->cistern.name);
PR_DEBUG(" Y字拖: %d", param->y_mop);
PR_DEBUG(" 清扫次数: %d", param->clean_cnt);
// 解析划区区域坐标(多边形顶点)
AREA_S* area = &p_zone_clean->clean_zone[i].area;
PR_DEBUG(" 顶点数量: %d", area->point_num);
for(int j = 0; j < area->point_num; j++) {
PR_DEBUG(" 顶点[%d]: (%d, %d)", j,
area->point[j].x, area->point[j].y);
}
// TODO: 保存划区清扫配置
// save_zone_clean_config(i, &p_zone_clean->clean_zone[i]);//伪代码,需要开发者自行实现
}
// 启动划区清扫任务
// start_zone_clean_task(p_zone_clean->clean_zone, p_zone_clean->num);//伪代码,需要开发者自行实现
// 处理完成后上报结果
ZONE_CLEAN_S report_data;
report_data.num = p_zone_clean->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID
report_data.clean_zone = p_zone_clean->clean_zone;
return ty_rvc_zone_clean_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_zone_clean_query(void)
{
PR_DEBUG("收到划区清扫查询命令");
// 从设备获取上次划区清扫配置
ZONE_CLEAN_S query_data;
ZONE_AREA_PARAM_S zones[5]; // 假设最多5个划区
POINT_COOR_S zone_points[5][4]; // 每个划区4个顶点(矩形)
query_data.num = get_last_zone_clean_count(); // 获取上次划区数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.clean_zone = zones;
// 填充每个划区的数据
for(int i = 0; i < query_data.num; i++) {
// 填充划区名称
zones[i].cur_name.name = "划区1";
zones[i].cur_name.len = strlen(zones[i].cur_name.name);
// 填充清扫模式(字符串格式)
zones[i].mode.name = "both_work"; // 例如: "only_sweep","only_mop","both_work"
zones[i].mode.len = strlen(zones[i].mode.name);
// 填充清扫参数
zones[i].param.suction.name = "normal"; // 例如: "closed","gentle","normal","strong","max"
zones[i].param.suction.len = strlen(zones[i].param.suction.name);
zones[i].param.cistern.name = "middle"; // 例如: "closed","low","middle","high"
zones[i].param.cistern.len = strlen(zones[i].param.cistern.name);
zones[i].param.y_mop = true;
zones[i].param.clean_cnt = 2;
// 填充划区区域坐标(矩形4个顶点)
zones[i].area.point_num = 4;
zones[i].area.point = zone_points[i];
// 填充矩形顶点坐标(顺时针或逆时针)
zone_points[i][0].x = 100; zone_points[i][0].y = 100; // 左下
zone_points[i][1].x = 300; zone_points[i][1].y = 100; // 右下
zone_points[i][2].x = 300; zone_points[i][2].y = 300; // 右上
zone_points[i][3].x = 100; zone_points[i][3].y = 300; // 左上
}
return ty_rvc_zone_clean_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图point_num 确定顶点数量实际距离 = 栅格数量 × 栅格分辨率mode、cur_name、suction、cistern 均为字符串格式name 指针和 len 长度"only_sweep" / "only_mop" / "both_work""closed" / "gentle" / "normal" / "strong" / "max""closed" / "low" / "middle" / "high"buff及嵌套的坐标数组)及字符串内存(mode.name、suction.name、cistern.name、cur_name.name等)由应用自行分配和管理,SDK不会释放这些内存功能说明:定点清扫允许用户在地图上指定一个点位,机器人将清扫以该点为中心的固定区域(通常为1平方米)。
数据结构:
```c
/**
* @brief Spot cleaning structure
*/
typedef struct {
int num; // Number of spot cleanings
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
POINT_COOR_S* points; // List of spot coordinates, each spot area corresponds to one points element
STR_ELEMENT_S* mode; // Cleaning mode for the zone, each area corresponds to one cleaning mode, mode[0] corresponds to point[0] area
CLEAN_PARAM_S* param; // Cleaning parameters for selected areas, param[0] corresponds to point[0] area, if not set valid is 0
} SPOT_CLEAN_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收定点数量(通常为1) | 填充上次定点清扫的数量 | 填充当前定点清扫的数量 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
points |
坐标数组 | 解析定点坐标(中心点) | 填充上次定点坐标 | 填充当前定点坐标 |
mode |
字符串数组 | 解析清扫模式(字符串格式) | 填充清扫模式字符串 | 填充清扫模式字符串 |
param |
清扫参数数组 | 解析清扫参数 | 填充清扫参数 | 填充清扫参数 |
param[i].valid |
int | 参数有效标志(备用字段) | 填充有效标志 | 填充有效标志 |
param[i].suction |
字符串 | 吸力档位(字符串格式) | 填充吸力字符串 | 填充吸力字符串 |
param[i].cistern |
字符串 | 水量档位(字符串格式) | 填充水量字符串 | 填充水量字符串 |
param[i].y_mop |
bool | Y字拖地开关 | 填充Y字拖开关 | 填充Y字拖开关 |
param[i].clean_cnt |
int | 清扫次数 | 填充清扫次数 | 填充清扫次数 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_spot_clean_set(SPOT_CLEAN_S* p_spot_clean)
{
PR_DEBUG("收到定点清扫设置命令,定点数量: %d", p_spot_clean->num);
// 通常定点清扫 num 固定为 1
if(p_spot_clean->num != 1) {
PR_WARN("定点清扫数量异常: %d,预期为1", p_spot_clean->num);
}
// 解析定点坐标
for(int i = 0; i < p_spot_clean->num; i++) {
PR_DEBUG("定点[%d] 坐标: (%d, %d)", i,
p_spot_clean->points[i].x,
p_spot_clean->points[i].y);
// 解析清扫模式(字符串格式,需转换为枚举)
if(p_spot_clean->mode) {
PR_DEBUG(" 清扫模式: %d-%s",
p_spot_clean->mode[i].len,
p_spot_clean->mode[i].name);
// TODO: 将字符串转换为枚举值
// int mode_enum = convert_sweep_mode_str_to_enum(&p_spot_clean->mode[i]);//伪代码,需要开发者自行实现
}
// 解析清扫参数
PR_DEBUG(" 吸力: %d-%s",
p_spot_clean->param[i].suction.len,
p_spot_clean->param[i].suction.name);
PR_DEBUG(" 水量: %d-%s",
p_spot_clean->param[i].cistern.len,
p_spot_clean->param[i].cistern.name);
PR_DEBUG(" Y字拖: %d", p_spot_clean->param[i].y_mop);
PR_DEBUG(" 清扫次数: %d", p_spot_clean->param[i].clean_cnt);
// TODO: 保存定点清扫配置
// save_spot_clean_config(&p_spot_clean->points[i], ...);//伪代码,需要开发者自行实现
}
// 启动定点清扫任务(以该点为中心,清扫1平方米区域)
// start_spot_clean_task(&p_spot_clean->points[0]);//伪代码,需要开发者自行实现
// 处理完成后上报结果
SPOT_CLEAN_S report_data;
report_data.num = p_spot_clean->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.points = p_spot_clean->points;
report_data.mode = p_spot_clean->mode;
report_data.param = p_spot_clean->param;
return ty_rvc_spot_clean_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_spot_clean_query(void)
{
PR_DEBUG("收到定点清扫查询命令");
// 从设备获取上次定点清扫配置
SPOT_CLEAN_S query_data;
POINT_COOR_S spot_point; // 定点坐标
STR_ELEMENT_S spot_mode; // 清扫模式
CLEAN_PARAM_S spot_param; // 清扫参数
// 定点清扫通常只有一个点
query_data.num = 1;
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.points = &spot_point;
query_data.mode = &spot_mode;
query_data.param = &spot_param;
// 填充定点坐标(上次定点清扫的位置)
spot_point.x = get_last_spot_x(); // 例如: 150,伪代码,需要开发者自行实现
spot_point.y = get_last_spot_y(); // 例如: 200,伪代码,需要开发者自行实现
// 填充清扫模式(字符串格式)
spot_mode.name = "only_sweep"; // 例如: "only_sweep","only_mop","both_work"
spot_mode.len = strlen(spot_mode.name);
// 填充清扫参数(面板下发什么参数,即上报什么参数)
spot_param.suction.name = "normal"; // 例如: "closed","gentle","normal","strong","max"
spot_param.suction.len = strlen(spot_param.suction.name);
spot_param.cistern.name = "middle"; // 例如: "closed","low","middle","high"
spot_param.cistern.len = strlen(spot_param.cistern.name);
spot_param.y_mop = false;
spot_param.clean_cnt = 1;
return ty_rvc_spot_clean_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图num 通常固定为 1,表示单个定点points 坐标为中心的 1 平方米区域实际距离 = 栅格数量 × 栅格分辨率mode、suction、cistern 均为字符串格式name 指针和 len 长度"only_sweep" / "only_mop" / "both_work""closed" / "gentle" / "normal" / "strong" / "max""closed" / "low" / "middle" / "high"buff)及字符串内存(mode.name、suction.name、cistern.name等)由应用自行分配和管理,SDK不会释放这些内存功能说明:预约定时允许用户设置定时清扫任务,支持单次执行或循环执行(按周循环),可为每个任务配置清扫房间和清扫参数。
数据结构:
```c
/**
* @brief Scheduled time structure
*/
typedef struct {
char hour; // Scheduled hour value
char min; // Scheduled minute value
} SCHEDULE_TIME_S;
/**
* @brief Scheduled information structure
*/
typedef struct {
unsigned char active; // Scheduled switch, 0 for off, 1 for on
unsigned char cycle; // Whether to loop the schedule, value 0 indicates a one-time schedule, non-zero indicates a looping schedule, cycle's bit0~bit6 correspond to Monday~Sunday
SCHEDULE_TIME_S start_time; // Scheduled effective time
int num; // Number of rooms corresponding to each schedule
bool customed_switch; // the switch of the clean param,when it is true,the clean param of the app send is unvalid
int* ids; // Room ID categories corresponding to each schedule
STR_ELEMENT_S* mode; // List of cleaning modes, mode[0] corresponds to ids[0]
CLEAN_PARAM_S* param; // List of cleaning parameters, param[0] corresponds to ids[0]
} SCHEDULE_PARAM_S;
/**
* @brief Local schedule structure
*/
typedef struct {
int num; // Number of schedules
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
SCHEDULE_PARAM_S* time_sets; // Parameter categories for each schedule
} SCHEDULE_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
num |
int | 接收预约定时任务数量 | 填充当前所有预约任务数量 | 填充当前所有预约任务数量 |
map_id |
int | 面板不下发,忽略该字段 | 必须填充当前地图ID | 必须填充当前地图ID |
time_sets |
预约参数数组 | 解析所有预约任务参数 | 填充所有预约任务 | 填充所有预约任务 |
time_sets[i].active |
unsigned char | 任务开关(0=关闭,1=开启) | 填充任务开关状态 | 填充任务开关状态 |
time_sets[i].cycle |
unsigned char | 循环模式(0=单次,非0=循环) | 填充循环模式 | 填充循环模式 |
time_sets[i].start_time |
时间结构 | 任务执行时间(时:分) | 填充执行时间 | 填充执行时间 |
time_sets[i].num |
int | 该任务要清扫的房间数量 | 填充房间数量 | 填充房间数量 |
time_sets[i].customed_switch |
bool | 自定义参数开关 | 填充自定义开关 | 填充自定义开关 |
time_sets[i].ids |
int数组 | 要清扫的房间ID列表 | 填充房间ID | 填充房间ID |
time_sets[i].mode |
字符串数组 | 各房间清扫模式(字符串) | 填充清扫模式 | 填充清扫模式 |
time_sets[i].param |
清扫参数数组 | 各房间清扫参数 | 填充清扫参数 | 填充清扫参数 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_schedule_set(SCHEDULE_S* p_schedule)
{
PR_DEBUG("收到预约定时设置命令,预约数量: %d", p_schedule->num);
// 遍历所有预约任务
for(int i = 0; i < p_schedule->num; i++) {
SCHEDULE_PARAM_S* task = &p_schedule->time_sets[i];
PR_DEBUG("预约任务[%d]:", i);
PR_DEBUG(" 开关状态: %d", task->active);
PR_DEBUG(" 执行时间: %02d:%02d", task->start_time.hour, task->start_time.min);
// 解析循环模式
if(task->cycle == 0) {
PR_DEBUG(" 执行模式: 单次执行");
} else {
PR_DEBUG(" 执行模式: 循环执行");
// cycle 的 bit0~bit6 对应周一~周日
for(int day = 0; day < 7; day++) {
if(task->cycle & (1 << day)) {
PR_DEBUG(" 周%d", day + 1);
}
}
}
// 解析要清扫的房间
PR_DEBUG(" 清扫房间数: %d", task->num);
for(int j = 0; j < task->num; j++) {
PR_DEBUG(" 房间ID[%d]: %d", j, task->ids[j]);
}
// 检查是否使用自定义清扫参数
if(task->customed_switch) {
PR_DEBUG(" 使用自定义清扫参数:");
// 解析各房间的清扫模式和参数
for(int j = 0; j < task->num; j++) {
if(task->mode) {
PR_DEBUG(" 房间[%d] 清扫模式: %.*s", j,
task->mode[j].len, task->mode[j].name);
}
if(task->param) {
PR_DEBUG(" 房间[%d] 吸力: %.*s", j,
task->param[j].suction.len,
task->param[j].suction.name);
PR_DEBUG(" 房间[%d] 水量: %.*s", j,
task->param[j].cistern.len,
task->param[j].cistern.name);
PR_DEBUG(" 房间[%d] Y字拖: %d", j, task->param[j].y_mop);
PR_DEBUG(" 房间[%d] 清扫次数: %d", j, task->param[j].clean_cnt);
}
}
} else {
PR_DEBUG(" 使用默认清扫参数");
}
// TODO: 保存预约任务到设备存储
// save_schedule_task(i, task);//伪代码,需要开发者自行实现
}
// 处理完成后上报结果
SCHEDULE_S report_data;
report_data.num = p_schedule->num;
report_data.map_id = get_current_map_id(); // 获取当前地图ID,伪代码,需要开发者自行实现
report_data.time_sets = p_schedule->time_sets;
return ty_rvc_schedule_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_schedule_query(void)
{
PR_DEBUG("收到预约定时查询命令");
// 从设备获取所有预约任务
SCHEDULE_S query_data;
SCHEDULE_PARAM_S tasks[10]; // 假设最多10个预约任务
query_data.num = get_schedule_count(); // 获取预约任务数量,伪代码,需要开发者自行实现
query_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
query_data.time_sets = tasks;
// 填充每个预约任务数据
for(int i = 0; i < query_data.num; i++) {
// 填充任务开关和时间
tasks[i].active = 1; // 1=开启
tasks[i].start_time.hour = 9; // 09:00
tasks[i].start_time.min = 0;
// 填充循环模式(bit0~bit6 对应周一~周日)
tasks[i].cycle = 0x1F; // 0b00011111 = 周一到周五
// 填充要清扫的房间
tasks[i].num = 2; // 清扫2个房间
// 分配并填充房间ID数组
static int room_ids[10][10]; // 静态数组,实际应动态分配
tasks[i].ids = room_ids[i];
room_ids[i][0] = 1; // 房间1
room_ids[i][1] = 2; // 房间2
// 自定义参数开关
tasks[i].customed_switch = true;
// 分配并填充清扫模式数组
static STR_ELEMENT_S modes[10][10];
tasks[i].mode = modes[i];
modes[i][0].name = "both_work";
modes[i][0].len = strlen(modes[i][0].name);
modes[i][1].name = "only_sweep";
modes[i][1].len = strlen(modes[i][1].name);
// 分配并填充清扫参数数组
static CLEAN_PARAM_S params[10][10];
tasks[i].param = params[i];
for(int j = 0; j < tasks[i].num; j++) {
params[i][j].suction.name = "strong";
params[i][j].suction.len = strlen(params[i][j].suction.name);
params[i][j].cistern.name = "high";
params[i][j].cistern.len = strlen(params[i][j].cistern.name);
params[i][j].y_mop = false;
params[i][j].clean_cnt = 1;
}
}
return ty_rvc_schedule_data_response(&query_data, 0);
}
注意事项:
map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图cycle = 0:单次执行(执行一次后自动失效)cycle != 0:循环执行,bit0~bit6 对应周一~周日cycle = 0x7F (0b01111111) 表示每天执行cycle = 0x1F (0b00011111) 表示周一到周五执行cycle = 0x60 (0b01100000) 表示周六和周日执行start_time.hour:0-23(24小时制)start_time.min:0-59customed_switch = false:使用设备默认清扫参数,忽略 mode 和 param 字段customed_switch = true:使用面板下发的自定义清扫参数mode、suction、cistern 均为字符串格式name 指针和 len 长度"only_sweep" / "only_mop" / "both_work""closed" / "gentle" / "normal" / "strong" / "max""closed" / "low" / "middle" / "high"ids 数组一一对应ids[0] 对应 mode[0]、param[0]time_sets、ids、mode、param等)及字符串内存(mode[i].name、suction.name、cistern.name等)由应用自行分配和管理,SDK不会释放这些内存功能说明:勿扰模式允许用户设置时间段,在该时间段内机器人如不会自动启动清扫任务(如预约定时任务),声音灯光关闭,避免打扰用户休息。
数据结构:
```c
/**
* @brief Scheduled time structure
*/
typedef struct {
char hour; // Scheduled hour value
char min; // Scheduled minute value
} SCHEDULE_TIME_S;
/**
* @brief Do not disturb settings structure
*/
typedef struct {
unsigned char active; // Do not disturb switch, 0 for off, 1 for on
unsigned char other_day; // Effective time, 0 for today, 1 for the next day
SCHEDULE_TIME_S start_time; // Do not disturb start time
SCHEDULE_TIME_S end_time; // Do not disturb end time
} QUIET_HOURS_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | QUERY命令响应 | 主动上报 |
|---|---|---|---|---|
active |
unsigned char | 勿扰模式开关(0=关闭,1=开启) | 填充勿扰开关状态 | 填充勿扰开关状态 |
other_day |
unsigned char | 结束时间日期(0=当天,1=次日) | 填充日期标志 | 填充日期标志 |
start_time |
时间结构 | 勿扰开始时间(时:分) | 填充开始时间 | 填充开始时间 |
start_time.hour |
char | 开始时间-小时(0-23) | 填充小时 | 填充小时 |
start_time.min |
char | 开始时间-分钟(0-59) | 填充分钟 | 填充分钟 |
end_time |
时间结构 | 勿扰结束时间(时:分) | 填充结束时间 | 填充结束时间 |
end_time.hour |
char | 结束时间-小时(0-23) | 填充小时 | 填充小时 |
end_time.min |
char | 结束时间-分钟(0-59) | 填充分钟 | 填充分钟 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_quiet_hours_set(QUIET_HOURS_S* p_quiet_hours)
{
PR_DEBUG("收到勿扰定时设置命令");
// 解析勿扰开关状态
PR_DEBUG("勿扰模式: %s", p_quiet_hours->active ? "开启" : "关闭");
// 解析勿扰时间段
PR_DEBUG("开始时间: %02d:%02d",
p_quiet_hours->start_time.hour,
p_quiet_hours->start_time.min);
PR_DEBUG("结束时间: %02d:%02d %s",
p_quiet_hours->end_time.hour,
p_quiet_hours->end_time.min,
p_quiet_hours->other_day ? "(次日)" : "(当天)");
// 判断跨天情况
if(p_quiet_hours->other_day == 1) {
// 跨天场景:例如 22:00 ~ 次日 08:00
PR_DEBUG("勿扰时段跨天");
} else {
// 当天场景:例如 12:00 ~ 14:00
PR_DEBUG("勿扰时段在同一天");
}
// 计算勿扰时长(示例)
int start_minutes = p_quiet_hours->start_time.hour * 60 + p_quiet_hours->start_time.min;
int end_minutes = p_quiet_hours->end_time.hour * 60 + p_quiet_hours->end_time.min;
int duration;
if(p_quiet_hours->other_day == 1) {
// 跨天:从开始到午夜 + 午夜到结束
duration = (24 * 60 - start_minutes) + end_minutes;
} else {
duration = end_minutes - start_minutes;
}
PR_DEBUG("勿扰时长: %d分钟 (%d小时%d分钟)",
duration, duration / 60, duration % 60);
// TODO: 保存勿扰设置到设备存储
// save_quiet_hours_config(p_quiet_hours);//伪代码,需要开发者自行实现
// TODO: 启用/禁用勿扰模式
if(p_quiet_hours->active) {
// enable_quiet_mode(p_quiet_hours);//伪代码,需要开发者自行实现
} else {
// disable_quiet_mode();//伪代码,需要开发者自行实现
}
// 处理完成后上报结果
QUIET_HOURS_S report_data = *p_quiet_hours;
return ty_rvc_quiet_hours_data_response(&report_data, 0); // 0表示成功
}
// QUERY命令响应示例
static OPERATE_RET handle_quiet_hours_query(void)
{
PR_DEBUG("收到勿扰定时查询命令");
// 从设备获取当前勿扰设置
QUIET_HOURS_S query_data;
// 填充勿扰开关状态
query_data.active = get_quiet_mode_status(); // 0=关闭,1=开启,伪代码,需要开发者自行实现
// 填充勿扰时间段
query_data.start_time.hour = 22; // 22:00
query_data.start_time.min = 0;
query_data.end_time.hour = 8; // 08:00
query_data.end_time.min = 0;
// 判断是否跨天(结束时间早于开始时间则跨天)
if(query_data.end_time.hour < query_data.start_time.hour ||
(query_data.end_time.hour == query_data.start_time.hour &&
query_data.end_time.min < query_data.start_time.min)) {
query_data.other_day = 1; // 跨天:22:00 ~ 次日 08:00
} else {
query_data.other_day = 0; // 当天:12:00 ~ 14:00
}
return ty_rvc_quiet_hours_data_response(&query_data, 0);
}
注意事项:
hour:0-23(24小时制)min:0-59other_day = 0:同一天,如 12:00 ~ 14:00other_day = 1:跨天,如 22:00 ~ 次日 08:00other_day=0)other_day=1)other_day=0)功能说明:地图分区分割允许用户在地图上通过绘制分割线将一个房间分割成两个独立的房间,便于分区管理和清扫。
数据结构:
```c
/**
* @brief Division line coordinate structure
*/
typedef struct {
POINT_COOR_S points[2]; // Endpoints of the line
} DIVIDE_LINE_S;
/**
* @brief Manual partition structure
*/
typedef struct {
int num; // Number of partitions to be divided
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
int* ids; // List of IDs to be divided
DIVIDE_LINE_S* divi_line; // Partition division line coordinates, each room ID corresponds to one division line, divi_line[0] corresponds to ids[0]
} PART_DIVI_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
num |
int | 接收要分割的房间数量(当前仅支持1) | 通常固定为1,表示单个房间分割 |
map_id |
int | 面板不下发,忽略该字段 | 设备上报时必须填充当前地图ID |
ids |
int数组 | 接收要分割的房间ID | 当前仅支持单个房间ID |
divi_line |
分割线数组 | 接收分割线坐标 | 每个房间ID对应一条分割线 |
divi_line[i].points[0] |
坐标 | 分割线起点坐标 (x0, y0) | 分割线的第一个端点 |
divi_line[i].points[1] |
坐标 | 分割线终点坐标 (x1, y1) | 分割线的第二个端点 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_part_division_set(PART_DIVI_S* p_part_divi)
{
PR_DEBUG("收到地图分区分割命令,分割数量: %d", p_part_divi->num);
// 当前仅支持单个房间分割
if(p_part_divi->num != 1) {
PR_ERR("不支持批量分割,当前仅支持单个房间分割");
return ty_rvc_part_division_data_response(p_part_divi, -1);
}
// 解析要分割的房间ID
int room_id = p_part_divi->ids[0];
PR_DEBUG("要分割的房间ID: %d", room_id);
// 检查房间ID是否有效
if(!is_valid_room_id(room_id)) { //伪代码,需要开发者自行实现
PR_ERR("房间ID无效: %d", room_id);
return ty_rvc_part_division_data_response(p_part_divi, -1);
}
// 解析分割线坐标
DIVIDE_LINE_S* line = &p_part_divi->divi_line[0];
PR_DEBUG("分割线起点: (%d, %d)", line->points[0].x, line->points[0].y);
PR_DEBUG("分割线终点: (%d, %d)", line->points[1].x, line->points[1].y);
// TODO: 执行房间分割算法
// 1. 验证分割线是否穿过房间区域
// 2. 计算分割后的两个新房间区域
// 3. 更新地图数据结构
// 4. 分配新的房间ID
int result = perform_room_division(room_id, line); //房间分割算法(伪代码),开发者自行实现
if(result != 0) {
PR_ERR("房间分割失败");
return ty_rvc_part_division_data_response(p_part_divi, -1);
}
// 分割成功后上报结果
PART_DIVI_S report_data;
report_data.num = p_part_divi->num;
report_data.map_id = get_current_map_id(); // **必须填充地图ID**
report_data.ids = p_part_divi->ids;
report_data.divi_line = p_part_divi->divi_line;
return ty_rvc_part_division_data_response(&report_data, 0);
}
注意事项:
num = 1)map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图实际距离 = 栅格数量 × 栅格分辨率ty_rvc_room_property_data_response() 上报最新的房间属性0:分割成功-1:分割失败功能说明:地图分区合并允许用户将两个相邻的房间合并成一个房间,简化房间管理或修正过度分割的房间。
数据结构:
```c
/**
* @brief Manual area merge structure
*/
typedef struct {
int num; // Number of partitions to be merged
int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
int* ids; // List of IDs to be merged
} PART_MERGE_S;
```
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
num |
int | 接收要合并的房间数量(当前仅支持2) | 通常固定为2,表示两个房间合并 |
map_id |
int | 面板不下发,忽略该字段 | 设备上报时必须填充当前地图ID |
ids |
int数组 | 接收要合并的房间ID列表 | 包含两个相邻房间的ID |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_part_merge_set(PART_MERGE_S* p_part_merge)
{
PR_DEBUG("收到地图分区合并命令,合并数量: %d", p_part_merge->num);
// 当前仅支持两个房间合并
if(p_part_merge->num != 2) {
PR_ERR("不支持的合并数量,当前仅支持两个房间合并");
return ty_rvc_part_merge_data_response(p_part_merge, -1);
}
// 解析要合并的两个房间ID
int room_id1 = p_part_merge->ids[0];
int room_id2 = p_part_merge->ids[1];
PR_DEBUG("要合并的房间: %d + %d", room_id1, room_id2);
// 检查房间ID是否有效
if(!is_valid_room_id(room_id1) || !is_valid_room_id(room_id2)) { //伪代码,需要开发者自行实现
PR_ERR("房间ID无效: %d 或 %d", room_id1, room_id2);
return ty_rvc_part_merge_data_response(p_part_merge, -1);
}
// 检查两个房间是否相邻
if(!are_rooms_adjacent(room_id1, room_id2)) { //伪代码,需要开发者自行实现
PR_ERR("房间不相邻,无法合并: %d 和 %d", room_id1, room_id2);
return ty_rvc_part_merge_data_response(p_part_merge, -1);
}
// TODO: 执行房间合并算法
// 1. 验证两个房间是否相邻(共享边界)
// 2. 合并两个房间的区域
// 3. 更新地图数据结构
// 4. 分配新的房间ID或保留其中一个
int result = perform_room_merge(room_id1, room_id2); //房间合并算法(伪代码),开发者自行实现
if(result != 0) {
PR_ERR("房间合并失败");
return ty_rvc_part_merge_data_response(p_part_merge, -1);
}
// 合并成功后上报结果
PART_MERGE_S report_data;
report_data.num = p_part_merge->num;
report_data.map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
report_data.ids = p_part_merge->ids;
return ty_rvc_part_merge_data_response(&report_data, 0);
}
注意事项:
num = 2)map_id 字段,设备需要自行判断当前地图map_id 字段,否则面板无法匹配地图ty_rvc_room_property_data_response() 上报最新的房间属性0:合并成功-1:合并失败功能说明:地图分区恢复默认用于将手动编辑过的房间信息恢复到初始默认状态,清除所有用户的分割、合并等房间信息操作。
数据结构:
/**
* @brief Manual area reset structure
*/
typedef struct {
int map_id; // Current command operation corresponding map ID
} MAP_PART_RESET_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
map_id |
int | 恢复默认的地图ID(预留字段,面板不下发) | 指定哪个地图需要恢复默认分区(预留功能) |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_map_part_default_set(MAP_PART_RESET_S* p_part_reset)
{
// 执行恢复默认分区操作
// 1. 删除所有手动分割/合并的房间
// 2. 重新加载系统自动分割的原始分区
// 3. 重置房间ID和名称
int map_id = get_current_map_id(); // **必须填充地图ID**,伪代码,需要开发者自行实现
int ret = restore_default_partitions(map_id); //恢复默认分区(伪代码),开发者自行实现
if(ret != 0) {
PR_ERR("恢复默认分区失败");
return ty_rvc_map_part_default_data_response(p_part_reset, -1);
}
// 保存更新后的地图数据,开发者自行实现
save_map_data(map_id);
PR_DEBUG("地图分区恢复默认成功");
return ty_rvc_map_part_default_data_response(p_part_reset, 0);
}
注意事项:
ty_rvc_room_property_data_response() 上报恢复后的房间属性0:恢复成功-1:恢复失败功能说明:地图重置用于清除当前地图缓存的所有数据,设备将重新开始建图,适用于更换使用环境或地图数据损坏的情况。
数据结构:
/**
* @brief Current map reset structure
*/
typedef struct {
int map_id; // Current command operation corresponding map ID
} CURRENT_MAP_RESET_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
map_id |
int | 重置的地图ID(预留字段,面板不下发) | 指定哪个地图需要被清除(预留功能) |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_map_reset_set(CURRENT_MAP_RESET_S* p_map_reset)
{
// 检查是否为当前正在使用的地图
int current_map_id = get_current_map_id(); //获取当前地图id(伪代码),需要开发者自行实现
// 执行地图重置操作
// 1. 清除地图数据
// 2. 清除所有房间信息
// 3. 清除虚拟墙、禁区等配置
// 4. 清除清扫记录
int ret = clear_map_data(current_map_id); //删除首页地图数据(伪代码),需要开发者自行实现
if(ret != 0) {
PR_ERR("清除地图数据失败");
return ty_rvc_map_clear_data_response(p_map_reset, -1);
}
PR_DEBUG("地图重置成功,准备重新建图");
return ty_rvc_map_clear_data_response(p_map_reset, 0);
}
注意事项:
ty_rvc_room_property_data_response() 上报新的房间属性num = 0)0:重置成功-1:重置失败功能说明:地图保存用于将当前地图数据保存到本地或云端,支持多楼层地图管理,保存后的地图可以在不同楼层间切换使用。
数据结构:
typedef enum {
MAP_SAVE_LOCAL = 0, // Save map locally
MAP_SAVE_CLOUD, // Save map to cloud
MAP_SAVE_MAX,
} MAP_SAVE_MODE_E;
/**
* @brief Map save structure
*/
typedef struct {
MAP_SAVE_MODE_E save_mode; // Save mode
} MAP_SAVE_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
save_mode |
枚举 | 接收保存模式 | 指定保存到本地还是云端 |
保存模式说明:
| 模式值 | 枚举名称 | 含义 | 说明 |
|---|---|---|---|
| 0 | MAP_SAVE_LOCAL |
本地保存 | 仅保存到设备本地存储 |
| 1 | MAP_SAVE_CLOUD |
云端保存(预留字段) | 保存到云端,支持多设备同步 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_map_save_set(MAP_SAVE_S* p_map_save)
{
PR_DEBUG("收到地图保存命令,保存模式: %d", p_map_save->save_mode);
// 检查保存模式是否有效
if(p_map_save->save_mode >= MAP_SAVE_MAX) {
PR_ERR("保存模式无效: %d", p_map_save->save_mode);
return ty_rvc_map_save_data_response(p_map_save, -1);
}
// 获取当前地图ID
int current_map_id = get_current_map_id(); //获取当前地图ID(伪代码),开发者自行实现
if(current_map_id <= 0) {
PR_ERR("当前没有有效的地图");
return ty_rvc_map_save_data_response(p_map_save, -1);
}
int ret = 0;
// 保存到本地
ret = save_map_to_local(current_map_id); //保存本地(伪代码),开发者自行实现
if(ret != 0) {
PR_ERR("本地保存失败");
return ty_rvc_map_save_data_response(p_map_save, -1);
}
// 如果需要保存到云端
PR_DEBUG("保存地图到云端");
// 然后上传到云端
ret = upload_map_to_cloud(current_map_id); //保存云端(伪代码),开发者自行实现
if(ret != 0) {
PR_ERR("云端上传失败");
return ty_rvc_map_save_data_response(p_map_save, -1);
}
if(ret != 0) {
PR_ERR("地图保存失败");
return ty_rvc_map_save_data_response(p_map_save, -1);
}
PR_DEBUG("地图保存成功");
return ty_rvc_map_save_data_response(p_map_save, 0);
}
注意事项:
MAP_SAVE_LOCAL:仅本地保存,目前面板仅支持该模式,开发者如需要保存云端,收到该模式后,可自行上报云端。MAP_SAVE_CLOUD:保存到云端,上报的接口可参考多楼层地图及清扫记录传输0:保存成功-1:保存失败功能说明:云端地图删除用于从云端删除指定的地图数据,同时删除本地对应的地图数据(如果有),通常用于删除不再使用的楼层地图。
数据结构:
/**
* @brief Delete cloud map structure
*/
typedef struct {
unsigned int map_id; // Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
} DELETE_CLOUD_MAP_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
map_id |
unsigned int | 接收要删除的云端地图ID | 指定要从云端删除的地图 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_delete_cloud_map_set(DELETE_CLOUD_MAP_S* p_map_delete)
{
PR_DEBUG("收到云端地图删除命令,云端地图ID: %d", p_map_delete->map_id);
// 检查本地是否存在该地图
if(!check_map_exists_in_cloud(p_map_delete->map_id)) { //伪代码,开发者自行实现
PR_ERR("本地不存在该地图: %d", p_map_delete->map_id);
return ty_rvc_map_delete_data_response(p_map_delete, 0);
}
// 删除本地缓存(可选)
ret = delete_local_map_cache(p_map_delete->map_id);
if(ret != 0) {
PR_ERR("本地地图删除失败");
return ty_rvc_map_delete_data_response(p_map_delete, -1);
}
PR_DEBUG("地图删除成功"); //面板收到本地删除成功的回复之后,会自行去删除云端地图数据
return ty_rvc_map_delete_data_response(p_map_delete, 0);
}
注意事项:
0:删除成功-1:删除失败功能说明:语音查询用于查询设备当前使用的语音包状态,支持用户在App中切换不同语言的语音包。
数据结构:
```c
/**
* @brief Voice download status
*/
typedef enum {
RVC_DOWNLOAD_ST_FAILED = 0, // Voice download error
RVC_DOWNLOAD_ST_LOADING, // Voice downloading
RVC_DOWNLOAD_ST_SUCC, // Voice download successful
RVC_DOWNLOAD_ST_USING // Voice in use
} VOICE_DOWNLOAD_ST_E;
/**
* @brief Use voice response structure
*/
typedef struct {
unsigned int id; // Voice ID number
VOICE_DOWNLOAD_ST_E download_status; // Voice download status
int percent; // Voice download progress percentage,range is 0~100
} USE_VOICE_LANGUAGE_RESPONSE_S;
```
结构体使用说明:
| 字段 | 类型 | QUERY命令响应 | 主动上报 |
|---|---|---|---|
id |
unsigned int | 填充当前使用的语音包ID | 填充语音包ID |
download_status |
枚举 | 填充语音包下载状态 | 填充下载状态 |
percent |
int | 填充下载进度(0-100) | 填充下载进度 |
下载状态说明:
| 状态值 | 枚举名称 | 含义 | 使用场景 |
|---|---|---|---|
| 0 | RVC_DOWNLOAD_ST_FAILED |
下载失败 | 语音包下载出错 |
| 1 | RVC_DOWNLOAD_ST_LOADING |
下载中 | 正在下载语音包 |
| 2 | RVC_DOWNLOAD_ST_SUCC |
下载成功 | 语音包下载完成但未启用 |
| 3 | RVC_DOWNLOAD_ST_USING |
使用中 | 当前正在使用的语音包 |
注意事项:
SDK自动处理:
ty_rvc_voice_download_init 接口即可语音包ID:
进度上报:
LOADING 状态:percent 应实时反映下载进度(0-99)SUCC/USING 状态:percent 应为 100FAILED 状态:percent 应为 0功能说明:地图功能支持多楼层地图管理,SDK自动处理楼层地图的下载到设备,由开发者根据进行地图切换。
使用方法:
// 设备初始化时调用
OPERATE_RET ret = ty_rvc_map_download_init("伪代码-这里需要入参");
if(ret != OPRT_OK) {
PR_ERR("地图下载初始化失败: %d", ret);
return ret;
}
PR_DEBUG("地图下载功能初始化成功");
注意事项:
ty_rvc_map_download_init 接口即可ty_rvc_room_property_data_response() 上报该地图的房间属性功能说明:密码验证用于校验用户输入的密码是否正确,验证通过后才能访问受保护的功能。
数据结构:
typedef struct {
int len; // string length
char* name; // string memory points
} STR_ELEMENT_S;
typedef struct {
STR_ELEMENT_S password;
} PASSWORD_CHECK_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
password |
字符串 | 接收用户输入的密码 | 需要与存储的密码进行比对 |
password.name |
char* | 密码字符串指针 | 实际密码内容 |
password.len |
int | 密码字符串长度 | 密码的字节数 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_password_check(PASSWORD_CHECK_S* p_password_check)
{
if(NULL == p_password_check || NULL == p_password_check->password.name) {
PR_ERR("密码验证参数无效");
return ty_rvc_password_check_response(false, 0);
}
PR_DEBUG("收到密码验证请求,密码长度: %d", p_password_check->password.len);
// 获取存储的密码
char stored_password[32] = {0};
int ret = read_password_from_storage(stored_password, sizeof(stored_password)); //伪代码,需要开发者自行实现
if(ret != 0) {
PR_ERR("读取密码失败");
return ty_rvc_password_check_response(false, 0);
}
// 比对密码(注意:实际应用中建议使用加密哈希比对)
if(p_password_check->password.len == strlen(stored_password) &&
memcmp(p_password_check->password.name, stored_password, p_password_check->password.len) == 0) {
PR_DEBUG("密码验证成功");
return ty_rvc_password_check_response(true, 0);
} else {
PR_WARN("密码验证失败");
return ty_rvc_password_check_response(true, 0);
}
}
注意事项:
true:密码正确false:密码错误password 字段需要同时使用 name 和 lenpassword.name)由SDK管理,回调函数返回后SDK会自动释放。如果应用需要异步处理(如在其它线程中使用),必须先将字符串拷贝到应用自己分配的内存中功能说明:密码设置用于首次设置密码或修改已有密码,修改密码时需要提供旧密码验证。
数据结构:
typedef struct {
int len; // string length
char* name; // string memory points
} STR_ELEMENT_S;
typedef struct {
STR_ELEMENT_S password; // 新密码
STR_ELEMENT_S old_password; // 旧密码(修改时需要)
} PASSWORD_SET_S;
结构体使用说明:
| 字段 | 类型 | SET命令处理 | 说明 |
|---|---|---|---|
password |
字符串 | 接收新密码 | 要设置的新密码 |
password.name |
char* | 新密码字符串指针 | 新密码内容 |
password.len |
int | 新密码字符串长度 | 新密码的字节数 |
old_password |
字符串 | 接收旧密码 | 修改密码时需要,首次设置为空 |
old_password.name |
char* | 旧密码字符串指针 | 旧密码内容 |
old_password.len |
int | 旧密码字符串长度 | 旧密码的字节数 |
使用示例:
// SET命令处理示例
static OPERATE_RET handle_password_set(PASSWORD_SET_S* p_password_set)
{
if(NULL == p_password_set || NULL == p_password_set->password.name) {
PR_ERR("密码设置参数无效");
return ty_rvc_password_set_response(false, 0);
}
PR_DEBUG("收到密码设置请求,新密码长度: %d", p_password_set->password.len);
// 检查当前是否已设置密码
bool password_exists = is_password_configured(); //伪代码,需要开发者自行实现
if(password_exists) {
// 修改密码场景:需要验证旧密码
if(NULL == p_password_set->old_password.name || p_password_set->old_password.len == 0) {
PR_ERR("修改密码需要提供旧密码");
return ty_rvc_password_set_response(false, 0);
}
// 验证旧密码
char stored_password[32] = {0};
int ret = read_password_from_storage(stored_password, sizeof(stored_password)); //伪代码,需要开发者自行实现
if(ret != 0 ||
p_password_set->old_password.len != strlen(stored_password) ||
memcmp(p_password_set->old_password.name, stored_password, p_password_set->old_password.len) != 0) {
PR_ERR("旧密码验证失败");
return ty_rvc_password_set_response(false, 0);
}
PR_DEBUG("旧密码验证成功,开始更新密码");
} else {
// 首次设置密码场景
PR_DEBUG("首次设置密码");
}
// 保存新密码(实际应用中应加密存储)
char new_password[32] = {0};
memcpy(new_password, p_password_set->password.name, p_password_set->password.len);
new_password[p_password_set->password.len] = '\0';
int ret = save_password_to_storage(new_password); //伪代码,需要开发者自行实现
if(ret != 0) {
PR_ERR("保存密码失败");
return ty_rvc_password_set_response(false, 0);
}
PR_DEBUG("密码设置成功");
return ty_rvc_password_set_response(true, 0);
}
注意事项:
true:密码设置成功false:密码设置失败old_password 为空,直接设置新密码old_password 不为空,需要先验证旧密码password 和 old_password 都需要使用 name 和 lenpassword.name、old_password.name)由SDK管理,回调函数返回后SDK会自动释放。如果应用需要异步处理(如在其它线程中使用),必须先将字符串拷贝到应用自己分配的内存中功能说明:查询当前房间信息用于获取设备当前所在房间的位置信息,主要用于Alexa语音控制场景,注意涂鸦公版App面板不支持该功能。
数据结构:
```c
typedef struct {
int len; // string length
char* name; // string memory points
} STR_ELEMENT_S;
/**
* @brief MCS Room info structure
*/
typedef struct {
unsigned int map_id; //Current command operation corresponding map ID, when the device reports, it's the map ID where the device currently is, the panel uses this field to confirm whether the reported parameters and the parameters set are on the same map
unsigned int curr_name_id; //The current room ID where the machine is located.
STR_ELEMENT_S curr_name; //The current room name where the machine is located.
} MCS_ROOM_INFO_S;
```
结构体使用说明:
| 字段 | 类型 | QUERY命令响应 | 主动上报 |
|---|---|---|---|
map_id |
unsigned int | 填充当前地图ID | 填充当前地图ID |
curr_name_id |
unsigned int | 填充当前所在房间ID | 填充当前所在房间ID |
curr_name |
字符串 | 填充当前所在房间名称 | 填充当前所在房间名称 |
curr_name.name |
char* | 房间名称字符串指针 | 房间名称字符串指针 |
curr_name.len |
int | 房间名称字符串长度 | 房间名称字符串长度 |
使用示例:
// QUERY命令响应示例
static OPERATE_RET handle_mcs_room_info_query(void)
{
PR_DEBUG("收到当前房间信息查询命令");
// 准备上报数据
MCS_ROOM_INFO_S room_info;
// 填充当前地图ID
room_info.map_id = get_current_map_id(); //伪代码,需要开发者自行实现
// 填充当前所在房间ID
room_info.curr_name_id = get_current_room_id(); //伪代码,需要开发者自行实现
// 填充当前所在房间名称
char* room_name = get_current_room_name(); // 例如: "客厅", "卧室", "厨房"
if(room_name) {
room_info.curr_name.name = room_name;
room_info.curr_name.len = strlen(room_name);
} else {
// 如果无法获取房间名称,使用默认名称
room_info.curr_name.name = "未知房间";
room_info.curr_name.len = strlen("未知房间");
}
PR_DEBUG("当前位置: 地图ID=%d, 房间ID=%d, 房间名称=%.*s",
room_info.map_id,
room_info.curr_name_id,
room_info.curr_name.len,
room_info.curr_name.name);
return ty_rvc_mcs_room_info_response(&room_info, 0); // 0表示查询成功
}
注意事项:
curr_name 需要同时填充 name 指针和 len 长度FUNC_SET_CB 回调对应的处理命令后,需要异步处理该事件,以保证频繁点击面板进行命令下发时,不对后续命令解析造成阻塞,异步处理时需要将命令参数先进行数据复制,然后使用复制后的数据进行命令事件处理。命令处理回调函数的注册接口。回调函数注册成功后,SDK 在收到云端下发的命令协议并成功解析后会调用注册的回调函数执行业务功能。需要注意的是回调函数中的 param 入参变量会在回调函数被调用后释放掉,如果回调函数有异步操作,需要将该入参的参数数据复制到应用自己申请的变量空间中。
/**
* @brief Sweeper advanced function setting callback function pointer
* @param [ADVANCE_CMD_E] cmd, protocol command, the SDK uses this parameter to notify the application of the current setting command to be processed, see the list for setting commands, all ending with SET
* @param [void *] param, parameters corresponding to the command, the application converts the param parameter into the command corresponding parameter structure based on the cmd command field, the structure correspondence can refer to the accompanying demo
*/
typedef OPERATE_RET (*FUNC_SET_CB)(IN ADVANCE_CMD_E cmd, IN void* param);
/**
* @brief Sweeper advanced function query callback function pointer
* @param [ADVANCE_CMD_E] cmd, protocol command, the SDK uses this parameter to notify the application of the current query command to be processed, see the list for query commands, all ending with QUERY
* @param [void *] param, parameters corresponding to the command, current query command, its parameters are meaningless and do not need to be processed
* @note When the application gets the corresponding command parameters in the query callback function and needs to report, please call the corresponding response reporting function, for example, after processing the VIRTUAL_WALL_QUERY command, when needing to report parameters, use the ty_rvc_virtual_wall_data_response interface to report
*/
typedef OPERATE_RET (*FUNC_QUERY_CB)(IN ADVANCE_CMD_E cmd, IN void* param);
/**
* @brief Register advanced capability setting and query callback functions
* @param[in] sets_handler: Command setting callback function that the application needs to implement
* @param[in] query_handler: Command query callback function that the application needs to implement
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_advance_func_register(IN FUNC_SET_CB sets_handler, IN FUNC_QUERY_CB query_handler);
| 参数 | 说明 |
|---|---|
| sets_handler | 入参,设置命令的处理回调函数,由业务应用实现。通过该接口注册到 SDK,回调函数的 param 入参为命令参数,应用应根据命令类型将该参数转换成对应的命令参数结构体,再进行使用 |
| query_handler | 入参,查询命令的处理回调函数,由业务应用实现。通过该接口注册到 SDK,回调函数的 param 入参当前未使用,应用无需关心 |
| OPERATE_RET | 返回值,OPRT_OK 代表执行成功,其它值代表执行失败,错误码含义参见 TuyaOS_SDK 对应头文件定义 |
设备端数据上报接口,用于完成与涂鸦 App 的数据同步,各接口完成的数据上报功能列表如下:
| 接口名称 | 接口功能 | 备注 |
|---|---|---|
| ty_rvc_virtual_wall_data_response | 虚拟墙数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_restricted_area_data_response | 禁区数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_room_property_data_response | 房间属性数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_room_clean_data_response | 选区清扫数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_spot_clean_data_response | 定点清扫数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_zone_clean_data_response | 划区清扫数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_schedule_data_response | 预约定时数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_quiet_hours_data_response | 勿扰定时数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_voice_language_data_response | 语种切换数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_device_info_data_response | 设备信息数据上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
| ty_rvc_part_division_data_response | 地图分区分割设置结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_part_merge_data_response | 地图分区合并设置结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_map_part_default_data_response | 地图分区恢复默认数据上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_map_clear_data_response | 地图重置命令设置结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_map_save_data_response | 地图保存命令设置结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_map_delete_data_response | 地图删除命令设置结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_map_empty_response | 空地图查询命令结果上报 | 该功能仅用于查询命令执行后的结果回复,面板无查询命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_password_check_response | 密码验证命令结果上报 | 该功能仅用于查询命令执行后的结果回复,面板无查询命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_password_state_response | 密码状态命令结果上报 | 该功能仅用于设置或者查询命令执行后的结果回复,面板无设置或者查询命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_password_set_response | 设置密码命令结果上报 | 该功能仅用于设置命令执行后的结果回复,面板无设置命令下发时设备无需调用该接口进行数据同步 |
| ty_rvc_mcs_room_info_response | 查询当前房间信息结果上报 | 设备端有相应数据变化时应主动调用该接口进行数据上报 |
/**
* @brief Report virtual wall information
* @param[in] p_virtual_wall: Virtual wall data, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Command execution result, 0 for success, other values for failure
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_virtual_wall_data_response(VIRTUAL_WALL_S* p_virtual_wall, int errcode);
/**
* @brief Report restricted area data
* @param[in] p_restricted_area: Restricted area data input parameter, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution result corresponding to the parameter setting, 0 for success, other values for failure
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_restricted_area_data_response(RESTRICTED_AREA_S* p_restricted_area, int errcode);
/**
* @brief Report room property data
* @param[in] p_room_clean: Room property data, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution result corresponding to the parameter setting, 0 for success, other values for failure
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_room_property_data_response(ROOM_PROPERTY_S* p_room_clean, int errcode);
/**
* @brief Report selected area cleaning parameter values
* @param[in] p_room_clean: Cleaning parameter input parameter, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code, no error, input parameter is 0
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_room_clean_data_response(ROOM_CLEAN_S* p_room_clean, int errcode);
/**
* @brief Report spot cleaning data
* @param[in] spot_clean_data: Spot cleaning data input parameter, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code, input 0 when no error
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_spot_clean_data_response(SPOT_CLEAN_S* spot_clean_data, int errcode);
/**
* @brief Report zone cleaning data
* @param[in] p_zone_area: Zone cleaning data input parameter, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code, input 0 when no error
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_zone_clean_data_response(ZONE_CLEAN_S* p_zone_area, int errcode);
/**
* @brief Partition setting reply
* @param[in] p_part_division: Partition parameters, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code, input 0 when no error
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_part_division_data_response(PART_DIVI_S* p_part_division, PART_DIV_ST_E errcode);
/**
* @brief Partition merge command reply
* @param[in] p_part_merge: Partition setting reply parameters, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code, input 0 when no error
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_part_merge_data_response(PART_MERGE_S* p_part_merge, PART_MERGE_ST_E errcode);
/**
* @brief Partition restore default command response
* @param[in] p_part_merge: Structure parameters, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_map_part_default_data_response(MAP_PART_RESET_S* p_part_merge, PART_RESET_ST_E errcode);
/**
* @brief Clear home map reply
* @param[in] p_map_reset: Map reset structure, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_map_clear_data_response(CURRENT_MAP_RESET_S* p_map_reset, MAP_RESET_ST_E errcode);
/**
* @brief Map save command reply
* @param[in] p_map_save: Map save reply parameter input, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_map_save_data_response(MAP_SAVE_S* p_map_save, MAP_SAVE_ST_E errcode);
/**
* @brief Map delete command reply
* @param[in] p_map_delete: Map delete reply parameters, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_map_delete_data_response(DELETE_CLOUD_MAP_S* p_map_delete, MAP_DELETE_ST_E errcode);
/**
* @brief Scheduled data report
* @param[in] p_schedule: Scheduled data, passed in by the application, parameters are defined in the structure
* @param[in] current_map_id:
* @param[in] errcode:
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_schedule_data_response(SCHEDULE_S* p_schedule, int errcode);
/**
* @brief Do not disturb scheduled data report
* @param[in] p_quiet_hours: Do not disturb scheduled data input, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_quiet_hours_data_response(QUIET_HOURS_S* p_quiet_hours, int errcode);
/**
* @brief Voice use parameter report
* @param[in] p_voice_language_res: Voice use parameter report, passed in by the application, parameters are defined in the structure
* @param[in] errcode: Execution error code
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_voice_language_data_response(USE_VOICE_LANGUAGE_RESPONSE_S* p_voice_language_res, VOICE_USE_ST_E errcode);
/**
* @brief Device information report, info field is concatenated by the customer in key:value format in JSON, when the app panel displays device information, it shows each value in the order of the key list
* The panel needs to correctly configure multilingual support for each key value
* This interface is responsible for completing data reporting via the MQTT channel
*
* @param[char*] info: Application's JSON format string
* @param [int] len: String length
* @return OPERATE_RET, OPRT_OK indicates success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_device_info_data_response(char* info, int len);
/**
* @brief Report dev room info
* @param[in] room_info: Room information parameters, passed in by the application, are defined in the structure.
* @param[in] errcode: Execution result corresponding to the parameter setting, 0 for success, other values for failure
* @return OPERATE_RET: 0 success, other error codes indicate failure
*/
OPERATE_RET ty_rvc_mcs_room_info_response(MCS_ROOM_INFO_S* room_info, int errcode);
static OPERATE_RET __sweeper_advance_function_set(OUT ADVANCE_CMD_E cmd, OUT void *param)
{
OPERATE_RET ret = 0;
int i=0,j=0;
switch (cmd) {
case VIRTUAL_WALL_SET: {
VIRTUAL_WALL_S* p_virtual_wall = (VIRTUAL_WALL_S*)param;
PR_DEBUG("virtual wall num:%d", p_virtual_wall->num);
for(i = 0; i < p_virtual_wall->num;i++){
PR_DEBUG("mode:%d", p_virtual_wall->line[i].mode);
PR_DEBUG("line:%d", p_virtual_wall->line[i].points[0].x);
PR_DEBUG("line:%d", p_virtual_wall->line[i].points[0].y);
PR_DEBUG("line:%d", p_virtual_wall->line[i].points[1].x);
PR_DEBUG("line:%d", p_virtual_wall->line[i].points[1].y);
}
........
//此处仅演示接口用法,实际使用时应在异步事件处理函数中获取设备实际数据,并进行数据上报
current_map_id = 8;
errcode = 0;
ty_rvc_virtual_wall_data_response(p_virtual_wall, current_map_id, errcode);
}break;
.......
default:
PR_DEBUG("cmd not support now");
break;
}
}
static OPERATE_RET __sweeper_advance_function_query(OUT ADVANCE_CMD_E cmd, OUT void *param)
{
OPERATE_RET ret = OPRT_OK;
uint16_t cmd_index = 0;
switch(cmd){
case VIRTUAL_WALL_QUERY:{
// 使用测试数据进行数据上报演示
VIRTUAL_WALL_S test_virtual_wall;
VIRTUAL_LINE_S virtual_line[10] = {0};
OPERATE_RET ret = OPRT_OK;
test_virtual_wall.num = 1;
for (int i = 0; i < test_virtual_wall.num; i++) {
virtual_line[i].mode = FORBIT_ALL;
virtual_line[i].points[0].x = 100;
virtual_line[i].points[0].y = 200;
virtual_line[i].points[1].x = 50;
virtual_line[i].points[1].y = 60;
}
test_virtual_wall.line = virtual_line;
int current_map_id = 7;
ty_rvc_virtual_wall_data_response(&test_virtual_wall, current_map_id, errcode);
}break;
default:
PR_DEBUG("cmd not support now");
break;
}
return ret;
}
// 上电主流程
int main(int argc, char* argv[])
{
OPERATE_RET ret = 0;
....
ret = ty_sys_start();
if (ret != OPRT_OK) {
PR_ERR("[%s, %d] sys start failed", __FUNCTION__, __LINE__);
return ret;
}
ty_rvc_advance_func_register(__sweeper_advance_function_set, __sweeper_advance_function_query);
....
}
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈