+++ /dev/null
-# 🎤 真实语音数据验证 VAD 功能指南
-
-## 🎯 目标
-使用真实语音数据验证 VAD 功能,确保语音活动检测的准确性和实时性。
-
-## 📋 完整的 VAD AT 指令集
-
-### 1. 基础指令
-```
-AT^VAD_INIT # 初始化 VAD
-AT^VAD_STATUS # 查询 VAD 状态
-AT^VAD_CLEANUP # 清理 VAD 资源
-AT^VAD_HELP # 显示帮助信息
-```
-
-### 2. 配置指令
-```
-AT^VAD_CONFIG <sil_threshold> <energy_threshold> <min_speech_length> <silence_detect_length> <rule1_min_tailing_silence> <rule2_min_tailing_silence> <rule3_min_tailing_silence>
-```
-
-**参数说明:**
-- `sil_threshold`: 静音阈值 (默认: 63, 建议: 50-70)
-- `energy_threshold`: 能量阈值 (默认: 10000, 建议: 5000-20000)
-- `min_speech_length`: 最小语音长度 (默认: 240, 建议: 120-480)
-- `silence_detect_length`: 静音检测长度 (默认: 300, 建议: 200-500)
-- `rule1_min_tailing_silence`: 规则1最小尾部静音 (默认: 480, 建议: 240-960)
-- `rule2_min_tailing_silence`: 规则2最小尾部静音 (默认: 960, 建议: 480-1920)
-- `rule3_min_tailing_silence`: 规则3最小尾部静音 (默认: 960, 建议: 480-1920)
-
-### 3. 测试指令
-```
-AT^VAD_TEST_AUDIO <audio_type> # 测试音频数据
-AT^VAD_RECORD_START # 开始录音测试
-AT^VAD_RECORD_STOP # 停止录音测试
-```
-
-**audio_type 参数:**
-- `0`: 静音测试
-- `1`: 语音测试
-- `2`: 混合测试(静音+语音)
-
-## 🎵 真实语音数据验证方法
-
-### 方法 1:使用真实麦克风录音
-
-#### 步骤 1:初始化 VAD
-```bash
-AT^VAD_INIT
-```
-**预期输出:**
-```
-=== VAD AT 指令测试 ===
-✓ 日志回调设置成功
-✓ VAD 初始化成功 (状态: 1)
-```
-
-#### 步骤 2:配置优化参数(可选)
-```bash
-AT^VAD_CONFIG 50 5000 120 300 480 960 960
-```
-**参数说明:**
-- 降低静音阈值:63 → 50(更容易检测到语音)
-- 降低能量阈值:10000 → 5000(对低音量语音更敏感)
-- 降低最小语音长度:240 → 120(更快响应短语音)
-
-#### 步骤 3:开始录音测试
-```bash
-AT^VAD_RECORD_START
-```
-**预期输出:**
-```
-=== VAD 录音测试开始 ===
-请对着麦克风说话,系统将实时检测语音活动
-按任意键停止录音测试
-```
-
-#### 步骤 4:进行语音测试
-1. **静音测试**:保持安静 3-5 秒
- - 预期:VAD 状态 = 0(静音)
-
-2. **语音测试**:清晰地说 "你好" 或 "测试"
- - 预期:VAD 状态 = 1(语音)
-
-3. **语音结束测试**:停止说话,保持安静
- - 预期:VAD 状态 = 2(语音结束),然后自动变为 0
-
-#### 步骤 5:停止录音测试
-```bash
-AT^VAD_RECORD_STOP
-```
-
-### 方法 2:使用预录制的语音文件
-
-#### 步骤 1:准备测试音频文件
-- 格式:16kHz, 16bit, 单声道 PCM
-- 内容:包含静音-语音-静音的完整序列
-- 时长:建议 10-30 秒
-
-#### 步骤 2:音频数据处理
-```c
-// 读取音频文件并分帧处理
-FILE *audio_file = fopen("test_audio.pcm", "rb");
-int16_t audio_frame[160]; // 10ms @ 16kHz
-
-while (fread(audio_frame, sizeof(int16_t), 160, audio_file) == 160) {
- // 运行 VAD
- run_vad(audio_frame, 160);
-
- // 获取状态
- int status = vad_detect();
- printf("帧 %d: VAD状态 = %d\n", frame_count++, status);
-
- // 处理语音结束
- if (status == 2) {
- printf("检测到语音结束\n");
- vad_clear();
- }
-}
-```
-
-### 方法 3:实时音频流测试
-
-#### 步骤 1:配置音频采集
-```c
-// 配置音频采集参数
-struct AudioConfig audio_conf = {
- .sample_rate = 16000,
- .bit_depth = 16,
- .channels = 1,
- .frame_size = 160 // 10ms
-};
-```
-
-#### 步骤 2:实时 VAD 处理
-```c
-// 音频采集回调函数
-void audio_callback(int16_t *audio_data, int data_len) {
- // 分帧处理(每帧 160 采样点)
- for (int i = 0; i < data_len; i += 160) {
- int16_t frame[160];
- memcpy(frame, &audio_data[i], 160 * sizeof(int16_t));
-
- // 运行 VAD
- run_vad(frame, 160);
- int status = vad_detect();
-
- // 实时输出状态
- if (status != prev_status) {
- printf("VAD状态变化: %d -> %d\n", prev_status, status);
- prev_status = status;
-
- if (status == 2) {
- printf("语音结束\n");
- vad_clear();
- }
- }
- }
-}
-```
-
-## 🔍 VAD 状态验证要点
-
-### 状态 0:静音
-- **触发条件**:音频能量低,特征不明显
-- **验证方法**:保持安静,观察状态是否稳定为 0
-- **预期行为**:状态稳定,无频繁变化
-
-### 状态 1:语音
-- **触发条件**:检测到语音特征,能量超过阈值
-- **验证方法**:清晰说话,观察状态是否变为 1
-- **预期行为**:语音开始后状态变为 1,持续到语音结束
-
-### 状态 2:语音结束
-- **触发条件**:语音特征消失,静音持续一定时间
-- **验证方法**:停止说话,观察状态是否变为 2
-- **预期行为**:状态变为 2 后自动调用 `vad_clear()`,然后变为 0
-
-## 📊 性能验证指标
-
-### 响应时间
-- **目标**:< 100ms
-- **测试方法**:从说话开始到状态变为 1 的时间
-- **测量工具**:秒表或系统时钟
-
-### 准确率
-- **目标**:> 95%
-- **测试方法**:统计正确检测的语音片段数量
-- **计算公式**:正确检测数 / 总测试数 × 100%
-
-### 误检率
-- **目标**:< 5%
-- **测试方法**:统计误报的语音检测数量
-- **计算公式**:误报数 / 总测试数 × 100%
-
-## 🚀 高级测试场景
-
-### 场景 1:环境噪声测试
-- **背景**:播放环境噪声(空调、风扇、交通等)
-- **目标**:确保 VAD 不会误报环境噪声为语音
-- **方法**:在噪声环境中保持静音,观察状态
-
-### 场景 2:多人语音测试
-- **背景**:多人同时说话
-- **目标**:验证 VAD 对混合语音的处理能力
-- **方法**:2-3 人同时说话,观察状态变化
-
-### 场景 3:音量变化测试
-- **背景**:从轻声到大声的语音变化
-- **目标**:验证 VAD 对不同音量语音的适应性
-- **方法**:逐渐提高说话音量,观察检测效果
-
-## 🛠️ 故障排除
-
-### 问题 1:VAD 状态始终为 0
-**可能原因:**
-- 能量阈值过高
-- 静音阈值过低
-- 音频数据格式不正确
-
-**解决方案:**
-```bash
-AT^VAD_CONFIG 50 3000 120 300 480 960 960
-```
-
-### 问题 2:VAD 状态频繁变化
-**可能原因:**
-- 阈值设置不当
-- 环境噪声干扰
-- 音频质量差
-
-**解决方案:**
-```bash
-AT^VAD_CONFIG 60 8000 240 400 600 1200 1200
-```
-
-### 问题 3:语音结束检测延迟
-**可能原因:**
-- 尾部静音阈值过高
-- 静音检测长度过长
-
-**解决方案:**
-```bash
-AT^VAD_CONFIG 50 5000 120 200 300 600 600
-```
-
-## 🎉 成功验证标志
-
-当 VAD 功能正常工作时,你应该看到:
-
-1. **初始化成功**:`✓ VAD 初始化成功 (状态: 1)`
-2. **状态变化正常**:静音(0) → 语音(1) → 结束(2) → 静音(0)
-3. **响应及时**:语音开始后 100ms 内状态变化
-4. **误检率低**:环境噪声不会误报为语音
-5. **资源管理**:正确调用 `vad_clear()` 和 `free_vad()`
-
-## 📝 测试记录模板
-
-```
-测试时间: _____________
-测试环境: _____________
-测试人员: _____________
-
-测试结果:
-□ 静音检测正常
-□ 语音检测正常
-□ 语音结束检测正常
-□ 响应时间 < 100ms
-□ 误检率 < 5%
-
-备注: _____________
-```
-
-按照这个指南进行测试,你就能全面验证 VAD 功能的正确性和性能了!🎯
-#include "vad_at_cmd.h"
#include "at_cmd_api.h"
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include "imsl_vad.h"
#include "media_thread_adapt.h"
+#include "http_client.h"
+#include "cat1_pub_api.h"
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
#define VAD_MAX_ARGC 8
#define VAD_MAX_ARGV_LEN 64
+#define LN_MAX_ARGC 8
+#define LN_MAX_ARGV_LEN 256
#define VAD_FAILED (-1)
#define VAD_SUCCESS (0)
static int AnalyzePcmFileWithVad(const char *pcm_path)
{
FILE *fp = fopen(pcm_path, "rb");
- if (fp == NULL) {
+ if (fp == NULL)
+ {
printf("open pcm failed: %s\n", pcm_path);
return VAD_FAILED;
}
int count_speech = 0;
int count_end = 0;
- while (1) {
+ while (1)
+ {
size_t n = fread(frame, sizeof(int16_t), 160, fp);
- if (n < 160) {
+ if (n < 160)
+ {
break;
}
run_vad(frame, 160);
int st = vad_detect();
- if (st != prev) {
+ if (st != prev)
+ {
printf("VAD状态变化: %d -> %d 于帧%zu\n", prev, st, total_frames);
prev = st;
}
- if (st == 1) {
+ if (st == 1)
+ {
count_speech++;
- } else if (st == 2) {
+ }
+ else if (st == 2)
+ {
count_end++;
vad_clear();
}
size_t filled = 0;
/* 等待文件可读 */
- while (g_vad_live_running && fp == NULL) {
+ while (g_vad_live_running && fp == NULL)
+ {
fp = fopen(g_vad_live_path, "rb");
- if (fp == NULL) {
+ if (fp == NULL)
+ {
usleep(50 * 1000);
}
}
- if (!g_vad_live_running) {
- if (fp) fclose(fp);
+ if (!g_vad_live_running)
+ {
+ if (fp)
+ fclose(fp);
return NULL;
}
/* 从头开始读,持续尾随追加的数据 */
- while (g_vad_live_running) {
+ while (g_vad_live_running)
+ {
int16_t sample;
size_t n = fread(&sample, sizeof(int16_t), 1, fp);
- if (n == 1) {
+ if (n == 1)
+ {
frame[filled++] = sample;
- if (filled == 160) {
+ if (filled == 160)
+ {
run_vad(frame, 160);
int st = vad_detect();
- if (st != g_vad_prev_status) {
+ if (st != g_vad_prev_status)
+ {
printf("[VAD-LIVE] 状态变化: %d -> %d\n", g_vad_prev_status, st);
g_vad_prev_status = st;
- if (st == 2) {
+ if (st == 2)
+ {
printf("[VAD-LIVE] 检测到语音结束,vad_clear()\n");
vad_clear();
}
}
filled = 0;
}
- } else {
+ }
+ else
+ {
/* 到达当前 EOF,短暂等待数据追加 */
clearerr(fp);
usleep(10 * 1000);
}
}
- if (fp) fclose(fp);
+ if (fp)
+ fclose(fp);
return NULL;
}
/* 确保父目录存在 */
static void EnsureParentDir(const char *file_path)
{
- if (file_path == NULL) {
+ if (file_path == NULL)
+ {
return;
}
const char *slash = strrchr(file_path, '/');
- if (slash == NULL || slash == file_path) {
+ if (slash == NULL || slash == file_path)
+ {
return; // no parent or root
}
char dir[256];
size_t len = (size_t)(slash - file_path);
- if (len >= sizeof(dir)) {
+ if (len >= sizeof(dir))
+ {
return;
}
memcpy(dir, file_path, len);
dir[len] = '\0';
struct stat st;
- if (stat(dir, &st) == 0) {
+ if (stat(dir, &st) == 0)
+ {
return; // exists
}
(void)mkdir(dir, 0777);
}
-static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen, uint8_t argv[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN], uint32_t *argc)
+static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen, uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN], uint32_t *argc)
{
uint32_t pos = 0;
*argc = 0;
for (uint32_t i = 0; i < paraLen; i++)
{
- if ((para[i] == ' ' || para[i] == '\n') && pos != 0)
+ /* 以空格/换行/逗号/等号作为分隔符,兼容 “AT^CMD=arg1,arg2” 或 “AT^CMD arg1 arg2” */
+ if ((para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') && pos != 0)
{
argv[*argc][pos] = '\0';
*argc += 1;
pos = 0;
- if (*argc >= VAD_MAX_ARGC)
+ if (*argc >= LN_MAX_ARGC)
{
return VAD_FAILED;
}
}
else
{
+ if (para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') {
+ continue; /* 连续分隔符跳过 */
+ }
argv[*argc][pos] = para[i];
pos++;
- if (pos >= VAD_MAX_ARGV_LEN)
+ if (pos >= LN_MAX_ARGV_LEN)
{
return VAD_FAILED;
}
static uint32_t vad_analyze_pcm(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
VAD_UNUSED(strCommonCmd);
- if (!g_vad_initialized) {
+ if (!g_vad_initialized)
+ {
printf("VAD not initialized, call AT^VAD_INIT first\n");
return ERRCODE_FAIL;
}
uint8_t argv[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN] = {0};
uint32_t argc = 0;
- if (ConvertCmdToParam(para, paraLen, argv, &argc) != VAD_SUCCESS || argc != 1) {
+ if (ConvertCmdToParam(para, paraLen, argv, &argc) != VAD_SUCCESS || argc != 1)
+ {
printf("Usage: AT^VAD_ANALYZE_PCM <pcm_path>\n");
return ERRCODE_FAIL;
}
- const char *pcm_path = (const char*)argv[0];
+ const char *pcm_path = (const char *)argv[0];
printf("VAD 分析现有 PCM: %s\n", pcm_path);
int ret = AnalyzePcmFileWithVad(pcm_path);
return (ret == VAD_SUCCESS) ? ERRCODE_SUCC : ERRCODE_FAIL;
static uint32_t vad_record_start(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
VAD_UNUSED(strCommonCmd);
- if (!g_vad_initialized) {
+ if (!g_vad_initialized)
+ {
printf("VAD not initialized, call AT^VAD_INIT first\n");
return ERRCODE_FAIL;
}
- if (g_vad_live_running) {
+ if (g_vad_live_running)
+ {
printf("VAD live already running\n");
return ERRCODE_SUCC;
}
/* 可选自定义输出路径 */
- const char *out_path = (const char*)g_vad_live_path;
+ const char *out_path = (const char *)g_vad_live_path;
uint8_t argvbuf[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN] = {0};
uint32_t argc = 0;
- if (para != NULL && paraLen > 0 && ConvertCmdToParam(para, paraLen, argvbuf, &argc) == VAD_SUCCESS && argc >= 1) {
- strncpy(g_vad_live_path, (const char*)argvbuf[0], sizeof(g_vad_live_path) - 1);
+ if (para != NULL && paraLen > 0 && ConvertCmdToParam(para, paraLen, argvbuf, &argc) == VAD_SUCCESS && argc >= 1)
+ {
+ strncpy(g_vad_live_path, (const char *)argvbuf[0], sizeof(g_vad_live_path) - 1);
g_vad_live_path[sizeof(g_vad_live_path) - 1] = '\0';
out_path = g_vad_live_path;
}
g_vad_prev_status = -1;
g_vad_live_running = true;
{
- MediaThreadattr attr = { "VADTail", 0x1000, THREAD_SCHED_INVALID, 0, true };
+ MediaThreadattr attr = {"VADTail", 0x1000, THREAD_SCHED_INVALID, 0, true};
g_vad_tail_thread = MediaThreadCreate(VadTailThread, NULL, &attr);
- if (g_vad_tail_thread == NULL) {
+ if (g_vad_tail_thread == NULL)
+ {
printf("create tail thread failed\n");
g_vad_live_running = false;
return ERRCODE_FAIL;
return ERRCODE_SUCC;
}
+/*
+ * 中文说明:打印签名预览,便于 PC 侧用 curl 验证。
+ * 用法:AT^LN_SIGN_PREVIEW=DEVICE_001,123456...
+ */
+/* 构建签名原始字符串(示例版):按约定拼接关键字段 */
+static void ln_build_sign_data_c(const char *deviceId, const char *iccid, const char *timestampMs, const char *nonce,
+ char *out_buf, size_t out_buf_size)
+{
+ if (out_buf == NULL || out_buf_size == 0)
+ {
+ return;
+ }
+ /* 具体拼接规则以雷鸟后台要求为准;这里采用常见的 key=value&key=value 形式 */
+ (void)snprintf(out_buf, out_buf_size,
+ "deviceId=%s&deviceIccid=%s×tampMs=%s&nonce=%s",
+ (deviceId ? deviceId : ""), (iccid ? iccid : ""),
+ (timestampMs ? timestampMs : ""), (nonce ? nonce : ""));
+}
+
+/* 计算签名(占位实现):真实实现应为 HMAC-SHA256(signData, secret) 输出16进制 */
+static void ln_build_signature_hex_c(const char *sign_data, const char *secret,
+ char *out_hex, size_t out_hex_size)
+{
+ (void)sign_data;
+ (void)secret;
+ if (out_hex == NULL || out_hex_size == 0)
+ {
+ return;
+ }
+ /* TODO: 接入实际加密库后替换此占位实现 */
+ (void)snprintf(out_hex, out_hex_size, "%s", "0000000000000000000000000000000000000000000000000000000000000000");
+}
+
+static uint32_t ln_sign_preview(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)strCommonCmd;
+ uint8_t argv[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN] = {0};
+ uint32_t argc = 0;
+ if (ConvertCmdToParam(para, paraLen, argv, &argc) != 0 || argc != 2)
+ {
+ printf("用法: AT^LN_SIGN_PREVIEW=<deviceId>,<iccid>\n");
+ return ERRCODE_FAIL;
+ }
+ const char *deviceId = (const char *)argv[0];
+ const char *iccid = (const char *)argv[1];
+
+ /* 注意:示例中时间戳应替换为真实毫秒时间戳,nonce 应为随机字符串 */
+ char ts[32];
+ (void)snprintf(ts, sizeof(ts), "%llu", (unsigned long long)0ULL);
+ const char *nonce = "nonce";
+ const char *signSecret = "vDdXVXgPUEUM6_piUjz5AEhMvYTSFzQdPaN-ogKnSus=";
+
+ char signData[256] = {0};
+ ln_build_sign_data_c(deviceId, iccid, ts, nonce, signData, sizeof(signData));
+ char signature_hex[128] = {0};
+ ln_build_signature_hex_c(signData, signSecret, signature_hex, sizeof(signature_hex));
+
+ printf("signData: %s\n", signData);
+ printf("signature(hex): %s\n", signature_hex);
+ printf("timestamp(ms): %s, nonce: %s\n", ts, nonce);
+ return ERRCODE_SUCC;
+}
+
+/* HTTP 回调:下载结果 */
+static void ln_http_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err)
+{
+ (void)arg;
+ printf("HTTP结束: result=%d, bodyLen=%u, http=%u, err=%d\n", (int)httpc_result, (unsigned)rx_content_len, (unsigned)srv_res, (int)err);
+ // 通讯结束:允许 CAT1 休眠
+ cat1_api_remove_cat1_vote();
+ cat1_api_keep_wakeup(0);
+ cat1_api_wakeup_cat1(0);
+ cat1_api_disable_cat1_cmd(0);
+}
+
+/* HTTP 回调:收到响应头 */
+static err_t ln_http_headers(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len)
+{
+ (void)connection;
+ (void)arg;
+ (void)hdr;
+ printf("HTTP头: hdr_len=%u content_len=%u\n", (unsigned)hdr_len, (unsigned)content_len);
+ return 0;
+}
+
+/* HTTP 回调:接收到 body 数据(增量打印前 512 字节以内) */
+static err_t ln_http_body(httpc_state_t *connection, u32_t rx_len, u32_t rx_total_len)
+{
+ (void)connection;
+ (void)rx_len;
+ printf("HTTP body 收到: total=%u\n", (unsigned)rx_total_len);
+ return 0;
+}
+
+/*
+ * 中文说明:获取设备 Token 的 AT 指令。
+ * 用法:AT^LN_GET_TOKEN=<deviceId>,<iccid>
+ * 步骤:
+ * 1) 生成 timestamp(毫秒)、nonce(随机) 和签名 signature
+ * 2) 唤醒 CAT1,发起 HTTP GET(当前走 80 端口便于调试;TLS 需另行使能)
+ * 3) 串口打印 HTTP 状态码与 body 接收进度
+ */
+static uint32_t ln_get_token(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)strCommonCmd;
+ uint8_t argv[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN] = {0};
+ uint32_t argc = 0;
+ if (ConvertCmdToParam(para, paraLen, argv, &argc) != 0 || argc != 2)
+ {
+ printf("用法: AT^LN_GET_TOKEN=<deviceId>,<iccid>\n");
+ return ERRCODE_FAIL;
+ }
+ const char *deviceId = (const char *)argv[0];
+ const char *iccid = (const char *)argv[1];
+
+ // 1) 生成签名参数
+ char ts[32];
+ (void)snprintf(ts, sizeof(ts), "%llu", (unsigned long long)0ULL); // TODO: 替换为真实毫秒
+ const char *nonce = "nonce"; // TODO: 替换为随机数
+ const char *signSecret = "vDdXVXgPUEUM6_piUjz5AEhMvYTSFzQdPaN-ogKnSus=";
+ char signData[256] = {0};
+ ln_build_sign_data_c(deviceId, iccid, ts, nonce, signData, sizeof(signData));
+ char signature_hex[128] = {0};
+ ln_build_signature_hex_c(signData, signSecret, signature_hex, sizeof(signature_hex));
+
+ // 2) 组装 HTTP 请求
+ httpc_connection_t settings = {0};
+ settings.result_fn = ln_http_result;
+ settings.headers_done_fn = ln_http_headers;
+ settings.file_rx_fn = ln_http_body;
+ settings.use_post = 0;
+
+ const char *server = "ambybox-api.test.leiniao.com";
+ uint16_t port = 80; // 调试用;如需 TLS,请切到 443 并配置 altcp_tls
+ const char *uri = "/ambybox-device-api/v1/auth/getDeviceToken";
+
+ printf("开始获取 Token: %s %s\n", deviceId, iccid);
+ cat1_api_add_cat1_vote();
+ cat1_api_wakeup_cat1(1);
+ cat1_api_keep_wakeup(1);
+ cat1_api_disable_cat1_cmd(1);
+
+ httpc_state_t *connection = NULL;
+ err_t rett = httpc_get_file_dns(server, port, uri, &settings, NULL, NULL, &connection);
+ if (rett != ERRCODE_SUCC)
+ {
+ printf("HTTP 启动失败: %d\n", (int)rett);
+ // 失败也释放 CAT1 约束
+ cat1_api_remove_cat1_vote();
+ cat1_api_keep_wakeup(0);
+ cat1_api_wakeup_cat1(0);
+ cat1_api_disable_cat1_cmd(0);
+ return ERRCODE_FAIL;
+ }
+ printf("HTTP 已发起,等待回调...\n");
+ return ERRCODE_SUCC;
+}
+
// AT^VAD_HELP - 显示帮助信息
static uint32_t vad_help(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
return ERRCODE_SUCC;
}
-static const at_cmd_table_t g_vad_cmd[] = {
+static const at_cmd_table_t g_ln_api_cmd[] = {
+ /* ----------------------------------- VAD ---------------------------------- */
{(char *)"AT^VAD_INIT", vad_init, (char *)"初始化 VAD"},
{(char *)"AT^VAD_CONFIG", vad_config, (char *)"配置 VAD 参数"},
{(char *)"AT^VAD_STATUS", vad_status, (char *)"查询 VAD 状态"},
{(char *)"AT^VAD_RECORD_STOP", vad_record_stop, (char *)"停止录音测试"},
{(char *)"AT^VAD_CLEANUP", vad_cleanup, (char *)"清理 VAD 资源"},
{(char *)"AT^VAD_HELP", vad_help, (char *)"显示帮助信息"},
+ /* ---------------------------------- 雷鸟API --------------------------------- */
+ {(char *)"AT^LN_SIGN_PREVIEW", ln_sign_preview, (char *)"签名预览: 参数=deviceId,iccid"},
+ {(char *)"AT^LN_GET_TOKEN", ln_get_token, (char *)"获取设备Token: 参数=deviceId,iccid"},
};
-at_cmd_table_t *get_vad_cmd_table(uint32_t *cmd_count)
+at_cmd_table_t *get_leiniao_api_cmd_table(uint32_t *cmd_count)
{
- *cmd_count = ARRAY_COUNT(g_vad_cmd);
- return (at_cmd_table_t *)g_vad_cmd;
+ *cmd_count = ARRAY_COUNT(g_ln_api_cmd);
+ return (at_cmd_table_t *)g_ln_api_cmd;
}