LISA WebSocket 组件
基于 nopoll 库的 WebSocket 客户端组件,为 ARCS 平台提供统一的 WebSocket 通信接口,支持安全和非安全连接、事件驱动架构和异步数据处理。
功能特性
连接支持: 支持 ws:// 和 wss:// 协议,提供安全和非安全连接
数据传输: 支持文本、二进制和 TTS 三种数据类型传输
事件驱动: 完整的事件回调机制,包括连接状态、错误处理和数据接收
异步处理: 独立线程处理网络通信,支持消息队列和重试机制
心跳检测: 可配置的 Ping/Pong 机制,实时监测连接状态
线程安全: 支持多线程环境,内部使用互斥锁保护
配置灵活: 丰富的配置选项,支持超时、重试、队列大小等参数调整
内存管理: 自动内存管理,支持分片传输和大文件处理
配置选项
在 prj.conf 中启用组件:
CONFIG_LISA_WEBSOCKET=y # 启用 WebSocket 组件
CONFIG_LISA_WEBSOCKET_SEND_RETRY_DELAY_NS=10000 # 发送重试延迟(纳秒)
CONFIG_LISA_WEBSOCKET_SEND_RETRY_COUNT=10 # 发送重试次数
CONFIG_LISA_WEBSOCKET_THREAD_STACK_SIZE=12288 # WebSocket 线程栈大小
CONFIG_LISA_WEBSOCKET_QUEUE_COUNT=150 # 消息队列大小
CONFIG_LISA_WEBSOCKET_PING_PONG_MSG=y # 启用心跳检测
CONFIG_LISA_WEBSOCKET_PING_PONG_TIMEOUT_MS=2000 # 心跳超时时间(毫秒)
CONFIG_LISA_WEBSOCKET_PING_PONG_RETRY_CNT=5 # 心跳重试次数
CONFIG_LISA_WEBSOCKET_FRAGMENT_RECV_TIMEOUT_MS=10000 # 分片接收超时时间
CONFIG_LISA_WEBSOCKET_FRAGMENT_SIZE=512 # 消息分片大小
根据应用需求调整相关参数。
API 接口
生命周期管理
lisa_ws_t *lisa_ws_init(lisa_ws_request_t *req);
lisa_ws_err_e lisa_ws_connect(lisa_ws_t *ins);
lisa_ws_err_e lisa_ws_disconnect(lisa_ws_t *ins);
lisa_ws_err_e lisa_ws_cleanup(lisa_ws_t *ins);
数据传输接口
lisa_ws_err_e lisa_ws_send_text(lisa_ws_t *ins, const uint8_t *text);
lisa_ws_err_e lisa_ws_send_binary(lisa_ws_t *ins, const void *buf, uint32_t len);
配置管理接口
lisa_ws_err_e lisa_ws_cfg_get(lisa_ws_t *ws, lisa_ws_request_t *req);
lisa_ws_err_e lisa_ws_cfg_set(lisa_ws_t *ws, lisa_ws_request_t *req);
便利函数
static inline lisa_ws_t *lisa_ws_new(void);
static inline lisa_ws_err_e lisa_ws_delete(lisa_ws_t *ins);
使用示例
基础 WebSocket 连接
#include "lisa_websocket.h"
// WebSocket 事件回调函数
static void on_websocket_event(lisa_ws_event_t *event)
{
switch (event->what) {
case LISA_WS_ON_CONNECTED:
LISA_INFO("WebSocket 连接成功");
break;
case LISA_WS_ON_DISCONNECTED:
LISA_INFO("WebSocket 连接断开");
break;
case LISA_WS_ON_ERROR:
LISA_INFO("WebSocket 发生错误");
break;
default:
break;
}
}
// WebSocket 数据接收回调函数
static void on_websocket_data(lisa_ws_data_t *data)
{
switch (data->type) {
case LISA_WS_TEXT:
LISA_INFO("收到文本消息: %s", (char *)data->buf);
break;
case LISA_WS_BIN:
LISA_INFO("收到二进制数据,长度: %d", data->len);
break;
default:
break;
}
}
int websocket_basic_example(void)
{
// 1. 配置 WebSocket 连接参数
lisa_ws_request_t req = {
.scheme = (uint8_t *)"wss",
.host = (uint8_t *)"echo.websocket.org",
.path = (uint8_t *)"/",
.port = (uint8_t *)"443",
.timeout = 10000,
.extra_header = NULL,
.user = NULL,
.on_event = on_websocket_event,
.on_data = on_websocket_data,
};
// 2. 创建 WebSocket 实例
lisa_ws_t *ws = lisa_ws_init(&req);
if (!ws) {
LISA_ERR("WebSocket 实例创建失败");
return -1;
}
// 3. 连接到 WebSocket 服务器
lisa_ws_err_e ret = lisa_ws_connect(ws);
if (ret != LISA_WS_OK) {
LISA_ERR("WebSocket 连接失败: %d", ret);
lisa_ws_delete(ws);
return -1;
}
// 4. 发送文本消息
const char *message = "Hello, WebSocket!";
ret = lisa_ws_send_text(ws, (const uint8_t *)message);
if (ret != LISA_WS_OK) {
LISA_ERR("发送文本消息失败: %d", ret);
}
// 5. 发送二进制数据
uint8_t binary_data[] = {0x01, 0x02, 0x03, 0x04};
ret = lisa_ws_send_binary(ws, binary_data, sizeof(binary_data));
if (ret != LISA_WS_OK) {
LISA_ERR("发送二进制数据失败: %d", ret);
}
// 6. 等待一段时间接收服务器的响应
lisa_thread_delay(5000); // 等待 5 秒
// 7. 断开连接并清理资源
lisa_ws_disconnect(ws);
lisa_ws_delete(ws);
return 0;
}
动态配置示例
#include "lisa_websocket.h"
int dynamic_config_example(void)
{
// 1. 使用默认配置创建实例
lisa_ws_t *ws = lisa_ws_new();
if (!ws) {
return -1;
}
// 2. 动态设置配置
lisa_ws_request_t new_config = {
.scheme = (uint8_t *)"wss",
.host = (uint8_t *)"api.example.com",
.path = (uint8_t *)"/websocket",
.port = (uint8_t *)"443",
.timeout = 5000,
.extra_header = "Authorization: Bearer token123\r\n",
.user = NULL,
.on_event = your_event_handler,
.on_data = your_data_handler,
};
lisa_ws_err_e ret = lisa_ws_cfg_set(ws, &new_config);
if (ret != LISA_WS_OK) {
LISA_ERR("设置配置失败");
lisa_ws_delete(ws);
return -1;
}
// 3. 连接并使用
ret = lisa_ws_connect(ws);
if (ret == LISA_WS_OK) {
// 发送消息
lisa_ws_send_text(ws, (const uint8_t *)"Hello from dynamic config");
// 获取当前配置(用于验证或调试)
lisa_ws_request_t current_config;
if (lisa_ws_cfg_get(ws, ¤t_config) == LISA_WS_OK) {
LISA_INFO("当前主机: %s", current_config.host);
}
// 断开连接
lisa_ws_disconnect(ws);
}
// 4. 清理
lisa_ws_delete(ws);
return 0;
}
事件类型说明
WebSocket 连接事件
事件类型 |
说明 |
触发时机 |
|---|---|---|
|
发生错误 |
网络错误、协议错误等 |
|
收到头部信息 |
WebSocket 握手期间(可能多次) |
|
连接建立成功 |
WebSocket 握手完成 |
|
连接进行中 |
开始建立连接 |
|
连接断开 |
连接关闭或超时 |
数据传输类型
数据类型 |
说明 |
编码格式 |
|---|---|---|
|
文本数据 |
UTF-8 字符串 |
|
二进制数据 |
原始字节数据 |
错误代码说明
错误代码 |
说明 |
处理建议 |
|---|---|---|
|
操作成功 |
- |
|
一般错误 |
检查参数和网络状态 |
|
连接断开 |
重新建立连接 |
注意事项
必须设置回调函数:
on_event和on_data回调函数必须设置,否则无法处理连接事件和接收数据连接超时设置: 合理设置
timeout参数,避免连接时间过长影响应用响应内存管理: 发送的数据在函数返回后即可释放,内部会自动管理内存复制
心跳检测: 启用 Ping/Pong 机制可以及时检测连接状态,但会增加网络开销
队列大小: 根据应用消息频率调整
QUEUE_COUNT,避免消息丢失分片大小:
FRAGMENT_SIZE应根据网络环境调整,建议在 512-1024 字节之间线程安全: WebSocket 组件内部使用独立线程处理网络通信,API 调用是线程安全的
错误处理: 所有 API 调用都应检查返回值,并进行相应的错误处理
资源清理: 应用退出前必须调用
lisa_ws_delete()清理资源,避免内存泄漏重连机制: 连接断开后需要应用层实现重连逻辑,组件不提供自动重连功能
大文件传输: 大于分片大小的消息会自动分片发送,确保网络稳定性
SSL/TLS: 使用 wss:// 协议时,确保设备时间正确,避免证书验证失败
文件说明
lisa_websocket.h- WebSocket 组件头文件,包含 API 接口和数据结构定义lisa_websocket.c- WebSocket 组件实现文件,基于 nopoll 库Kconfig- 组件配置选项定义文件CMakeLists.txt- 组件构建配置文件