Commit af551a9d authored by 957dd's avatar 957dd

Merge branch 'feature/add_aboard_tts' into 'master'

加入了音频播放的英文播放 See merge request !125
parents 822c019d 29e01fc4
...@@ -130,7 +130,7 @@ int connect_wifi(const char* ssid, const char* password) { ...@@ -130,7 +130,7 @@ int connect_wifi(const char* ssid, const char* password) {
char output[512] = {0}; char output[512] = {0};
size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp); size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp);
if (bytes_read == 0){ if (bytes_read == 0){
my_zlog_info("success"); my_zlog_debug("success");
} }
pclose(fp); pclose(fp);
...@@ -161,7 +161,7 @@ int connect_wifi_with_fallback(const char* ssid, const char* password, const cha ...@@ -161,7 +161,7 @@ int connect_wifi_with_fallback(const char* ssid, const char* password, const cha
size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp); size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp);
if (bytes_read == 0){ if (bytes_read == 0){
my_zlog_info("fread success"); my_zlog_debug("fread success");
} }
pclose(fp); pclose(fp);
......
...@@ -25,7 +25,10 @@ char *device_inspect() { ...@@ -25,7 +25,10 @@ char *device_inspect() {
else { else {
// 尝试读取文件内容 // 尝试读取文件内容
if (fgets(s_buffer_device, sizeof(s_buffer_device), file) != NULL) { if (fgets(s_buffer_device, sizeof(s_buffer_device), file) != NULL) {
// 如果文件内容不为空 size_t len = strlen(s_buffer_device);
if (len > 0 && s_buffer_device[len - 1] == '\n') {
s_buffer_device[len - 1] = '\0';
}
fclose(file); fclose(file);
my_zlog_info("读取到文件内容: %s", s_buffer_device); my_zlog_info("读取到文件内容: %s", s_buffer_device);
return s_buffer_device; return s_buffer_device;
......
#include "wifi_autoconfig.h" #include "wifi_autoconfig.h"
#include "main.h" #include "main.h"
#include "http_config_mqtt.h"
#include "cJSON.h" #include "cJSON.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -7,62 +8,207 @@ ...@@ -7,62 +8,207 @@
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#define AUDIO_BASE_URL "https://fcrs-1367068685.cos.ap-guangzhou.myqcloud.com/car/audio/"
static const char *s_audio_files[] = { static const char *s_audio_files[] = {
"noCameraDetected.mp3", "noCameraDetected.mp3",
"connectionFailed.mp3", "connectionFailed.mp3",
"connectionSuccessful.mp3", "connectionSuccessful.mp3",
"scanSuccessful.mp3", "scanSuccessful.mp3",
"toScanQRCode.mp3" "toScanQRCode.mp3",
"Speedupforoneminute.mp3",
};
#define AUDIO_FILE_COUNT (sizeof(s_audio_files) / sizeof(s_audio_files[0]))
/* COS 已上传 DrivingLevel1~15,预留至 30;未上传的级别下载失败则跳过 */
#define AUDIO_DRIVING_LEVEL_MAX 30
// 外语子目录(中文走旧平铺路径,不在此列表)
static const char *s_foreign_langs[] = {
AUDIO_LANG_EN,
AUDIO_LANG_JA,
AUDIO_LANG_KO,
AUDIO_LANG_ES,
}; };
#define FOREIGN_LANG_COUNT (sizeof(s_foreign_langs) / sizeof(s_foreign_langs[0]))
// 检查命令是否存在 (前置声明)
static int is_command_available(const char *cmd); static int is_command_available(const char *cmd);
static int ensure_audio_dir(const char *dir);
// 播放 ~/audio/ 下的音频文件 static char s_current_lang[8] = AUDIO_LANG_ZH;
// 播放 ~/audio/ 下的音频文件,如果不存在则回退系统音
void play_audio_file(const char *filename) {
char cmd[512];
const char *audio_dir = "/home/orangepi/audio"; // 固定路径
char filepath[256]; static int is_cn_lang(const char *lang) {
snprintf(filepath, sizeof(filepath), "%s/%s", audio_dir, filename); return lang != NULL && (strcmp(lang, AUDIO_LANG_ZH) == 0 || strcmp(lang, "cn") == 0);
}
static int is_en_lang(const char *lang) {
return lang != NULL &&
(strcmp(lang, AUDIO_LANG_EN) == 0 || strcmp(lang, "en") == 0 || strcmp(lang, "EN") == 0);
}
my_zlog_debug("尝试播放音频: %s", filename); static void audio_save_offline_language(void) {
ensure_audio_dir(AUDIO_LOCAL_BASE);
FILE *fp = fopen(AUDIO_OFFLINE_LANG_FILE, "w");
if (fp == NULL) {
my_zlog_warn("保存离线语言配置失败: %s", AUDIO_OFFLINE_LANG_FILE);
return;
}
fprintf(fp, "%s\n", s_current_lang);
fclose(fp);
my_zlog_debug("离线语言已保存: %s", s_current_lang);
}
// 1. 检查自定义文件是否存在 void audio_init_offline_language(void) {
if (access(filepath, F_OK) == 0) { FILE *fp = fopen(AUDIO_OFFLINE_LANG_FILE, "r");
// 文件存在,优先使用 ffplay if (fp == NULL) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_ZH);
my_zlog_debug("离线语言配置不存在,默认中文");
return;
}
char buf[16] = {0};
if (fgets(buf, sizeof(buf), fp) == NULL) {
fclose(fp);
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_ZH);
return;
}
fclose(fp);
buf[strcspn(buf, "\r\n")] = '\0';
if (is_cn_lang(buf)) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_ZH);
} else if (is_en_lang(buf)) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_EN);
} else {
for (size_t i = 0; i < FOREIGN_LANG_COUNT; i++) {
if (strcmp(buf, s_foreign_langs[i]) == 0) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", s_foreign_langs[i]);
my_zlog_debug("离线语言已加载: %s", s_current_lang);
return;
}
}
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_ZH);
my_zlog_warn("离线语言配置无效: %s,回退中文", buf);
return;
}
my_zlog_debug("离线语言已加载: %s", s_current_lang);
}
void audio_set_language(const char *lang_code) {
if (lang_code == NULL || lang_code[0] == '\0') {
return;
}
if (is_cn_lang(lang_code)) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_ZH);
my_zlog_info("离线音频语言已切换为: 中文");
audio_save_offline_language();
return;
}
if (is_en_lang(lang_code)) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", AUDIO_LANG_EN);
my_zlog_debug("离线音频语言已切换为: %s", s_current_lang);
audio_save_offline_language();
return;
}
for (size_t i = 0; i < FOREIGN_LANG_COUNT; i++) {
if (strcmp(lang_code, s_foreign_langs[i]) == 0) {
snprintf(s_current_lang, sizeof(s_current_lang), "%s", lang_code);
my_zlog_debug("离线音频语言已切换为: %s", s_current_lang);
audio_save_offline_language();
return;
}
}
my_zlog_warn("未知语言代码: %s,保持当前语言: %s", lang_code, s_current_lang);
}
const char *audio_toggle_cn_en(void) {
if (is_cn_lang(s_current_lang)) {
audio_set_language(AUDIO_LANG_EN);
} else {
audio_set_language(AUDIO_LANG_ZH);
}
return s_current_lang;
}
const char *audio_get_language(void) {
return s_current_lang;
}
static int ensure_audio_dir(const char *dir) {
struct stat st = {0};
if (stat(dir, &st) == 0) {
return 0;
}
if (mkdir(dir, 0755) != 0) {
my_zlog_warn("创建音频目录失败: %s", dir);
return -1;
}
my_zlog_debug("已创建音频目录: %s", dir);
return 0;
}
// 中文旧路径:/home/orangepi/audio/xxx.mp3
static void build_cn_filepath(char *filepath, size_t size, const char *filename) {
snprintf(filepath, size, "%s/%s", AUDIO_LOCAL_BASE, filename);
}
// 外语子目录:/home/orangepi/audio/{lang}/xxx.mp3
static void build_lang_filepath(char *filepath, size_t size, const char *lang, const char *filename) {
snprintf(filepath, size, "%s/%s/%s", AUDIO_LOCAL_BASE, lang, filename);
}
static int try_play_filepath(const char *filepath) {
char cmd[512];
if (access(filepath, F_OK) != 0) {
return 0;
}
if (is_command_available("ffplay")) { if (is_command_available("ffplay")) {
snprintf(cmd, sizeof(cmd), "ffplay -nodisp -autoexit -loglevel quiet \"%s\"", filepath); snprintf(cmd, sizeof(cmd), "ffplay -nodisp -autoexit -loglevel quiet \"%s\"", filepath);
if (system(cmd) == 0) { if (system(cmd) == 0) {
my_zlog_debug("ffplay 播放成功"); my_zlog_debug("ffplay 播放成功: %s", filepath);
return; return 1;
} }
} }
// 其次 paplay
if (is_command_available("paplay")) { if (is_command_available("paplay")) {
snprintf(cmd, sizeof(cmd), "paplay \"%s\"", filepath); snprintf(cmd, sizeof(cmd), "paplay \"%s\"", filepath);
if (system(cmd) == 0) { if (system(cmd) == 0) {
my_zlog_debug("paplay 播放成功"); my_zlog_debug("paplay 播放成功: %s", filepath);
return; return 1;
}
} }
my_zlog_warn("音频播放失败: %s", filepath);
return 0;
}
// 播放离线本地音频(无网络场景;按 audio_get_language 选择中文或 EN)
void play_audio_file(const char *filename) {
char cmd[512];
char filepath[256];
my_zlog_debug("尝试播放音频: %s (语言: %s)", filename, s_current_lang);
if (is_cn_lang(s_current_lang)) {
build_cn_filepath(filepath, sizeof(filepath), filename);
if (try_play_filepath(filepath)) {
return;
} }
my_zlog_warn("自定义音频播放失败,尝试回退系统音..."); my_zlog_warn("中文音频不存在: %s,准备播放系统回退音。", filepath);
} else { } else {
my_zlog_warn("音频文件 %s 不存在,准备播放系统回退音。", filepath); build_lang_filepath(filepath, sizeof(filepath), s_current_lang, filename);
if (try_play_filepath(filepath)) {
return;
} }
build_cn_filepath(filepath, sizeof(filepath), filename);
// 2. 文件不存在,或者播放工具缺失 -> 回退到系统默认声音 if (try_play_filepath(filepath)) {
// 根据文件名映射一下大概的系统音 my_zlog_debug("外语音频缺失,已回退中文: %s", filepath);
const char *sys_sound = "dialog-information"; // 默认 return;
}
my_zlog_warn("音频文件不存在 (%s 及中文回退路径),准备播放系统回退音。",
s_current_lang);
}
const char *sys_sound = "dialog-information";
if (strstr(filename, "noCamera")) sys_sound = "software-error"; if (strstr(filename, "noCamera")) sys_sound = "software-error";
else if (strstr(filename, "Failed")) sys_sound = "dialog-error"; else if (strstr(filename, "Failed")) sys_sound = "dialog-error";
else if (strstr(filename, "Success")) sys_sound = "service-login"; else if (strstr(filename, "Success")) sys_sound = "service-login";
else if (strstr(filename, "toScan")) sys_sound = "dialog-question"; else if (strstr(filename, "toScan")) sys_sound = "dialog-question";
// 尝试播放系统音
if (is_command_available("paplay")) { if (is_command_available("paplay")) {
snprintf(cmd, sizeof(cmd), "paplay /usr/share/sounds/ubuntu/stereo/%s.ogg", sys_sound); snprintf(cmd, sizeof(cmd), "paplay /usr/share/sounds/ubuntu/stereo/%s.ogg", sys_sound);
if (system(cmd) == 0) { if (system(cmd) == 0) {
...@@ -87,37 +233,82 @@ void play_audio_file(const char *filename) { ...@@ -87,37 +233,82 @@ void play_audio_file(const char *filename) {
my_zlog_error("所有播放尝试均失败!"); my_zlog_error("所有播放尝试均失败!");
} }
// 下载音频文件 static void download_cn_audio(const char *filename, int optional) {
static void download_audio_files() { char filepath[512];
const char *audio_dir = "/home/orangepi/audio"; // 固定路径 build_cn_filepath(filepath, sizeof(filepath), filename);
if (access(filepath, F_OK) == 0) {
return;
}
// 1. 检查并创建目录 my_zlog_debug("正在下载中文音频: %s", filename);
struct stat st = {0}; char cmd[1024];
if (stat(audio_dir, &st) == -1) { snprintf(cmd, sizeof(cmd), "wget -q -P \"%s\" \"%s%s\"",
my_zlog_info("正在创建音频目录: %s", audio_dir); AUDIO_LOCAL_BASE, AUDIO_COS_BASE, filename);
mkdir(audio_dir, 0755); if (system(cmd) != 0) {
if (optional) {
my_zlog_debug("中文音频暂未上传,跳过: %s", filename);
} else {
my_zlog_warn("下载失败 [zh]: %s", filename);
} }
}
}
static void download_lang_audio(const char *lang, const char *filename) {
char lang_dir[128];
snprintf(lang_dir, sizeof(lang_dir), "%s/%s", AUDIO_LOCAL_BASE, lang);
ensure_audio_dir(lang_dir);
// 2. 检查并下载每个文件
for (int i = 0; i < 5; i++) {
char filepath[512]; char filepath[512];
snprintf(filepath, sizeof(filepath), "%s/%s", audio_dir, s_audio_files[i]); build_lang_filepath(filepath, sizeof(filepath), lang, filename);
if (access(filepath, F_OK) == 0) {
return;
}
if (access(filepath, F_OK) != 0) {
my_zlog_info("正在下载音频文件: %s", s_audio_files[i]);
char cmd[1024]; char cmd[1024];
// 使用 wget -q (安静模式) -P (指定目录) snprintf(cmd, sizeof(cmd), "wget -q -P \"%s\" \"%s%s/%s\"",
snprintf(cmd, sizeof(cmd), "wget -q -P \"%s\" \"%s%s\"", audio_dir, AUDIO_BASE_URL, s_audio_files[i]); lang_dir, AUDIO_COS_BASE, lang, filename);
if (system(cmd) != 0) { if (system(cmd) != 0) {
my_zlog_warn("下载失败: %s", s_audio_files[i]); my_zlog_debug("预留语言音频暂未上传 [%s]: %s", lang, filename);
}
} else { } else {
// my_zlog_debug("文件已存在: %s", s_audio_files[i]); my_zlog_debug("已下载 [%s]: %s", lang, filename);
}
}
// 下载音频:中文走旧平铺路径;外语走子目录(COS 未上传则跳过)
static void download_audio_files() {
ensure_audio_dir(AUDIO_LOCAL_BASE);
for (size_t i = 0; i < AUDIO_FILE_COUNT; i++) {
download_cn_audio(s_audio_files[i], 0);
}
for (int level = 1; level <= AUDIO_DRIVING_LEVEL_MAX; level++) {
char filename[48];
snprintf(filename, sizeof(filename), "DrivingLevel%d.mp3", level);
download_cn_audio(filename, 1);
}
for (size_t l = 0; l < FOREIGN_LANG_COUNT; l++) {
const char *lang = s_foreign_langs[l];
for (size_t i = 0; i < AUDIO_FILE_COUNT; i++) {
download_lang_audio(lang, s_audio_files[i]);
}
for (int level = 1; level <= AUDIO_DRIVING_LEVEL_MAX; level++) {
char filename[48];
snprintf(filename, sizeof(filename), "DrivingLevel%d.mp3", level);
download_lang_audio(lang, filename);
} }
} }
} }
// 有网后:先 getConfig 定区域语言,再下载离线音频(在其它语音播放之前)
static void prepare_offline_audio_after_network(void) {
if (device_fetch_region_language() != 0) {
my_zlog_warn("拉取区域语言失败,使用本地已保存语言: %s", audio_get_language());
}
download_audio_files();
}
// 检查命令是否存在 // 检查命令是否存在
static int is_command_available(const char *cmd) { static int is_command_available(const char *cmd) {
char check_cmd[256]; char check_cmd[256];
...@@ -170,7 +361,7 @@ static void check_and_install_dependencies() { ...@@ -170,7 +361,7 @@ static void check_and_install_dependencies() {
my_zlog_error("依赖安装失败,自动配网功能可能无法正常使用。"); my_zlog_error("依赖安装失败,自动配网功能可能无法正常使用。");
} }
} else { } else {
my_zlog_info("所需依赖 (fswebcam, zbar-tools, audio) 已就绪。"); my_zlog_debug("所需依赖 (fswebcam, zbar-tools, audio) 已就绪。");
} }
} }
...@@ -287,15 +478,16 @@ static int try_connect_wifi(const char *ssid, const char *password) { ...@@ -287,15 +478,16 @@ static int try_connect_wifi(const char *ssid, const char *password) {
// 自动配网主逻辑 // 自动配网主逻辑
void check_and_autoconfig_wifi() { void check_and_autoconfig_wifi() {
my_zlog_info("开始检查网络连接状态..."); audio_init_offline_language();
my_zlog_debug("开始检查网络连接状态...");
// 1. 检查并处理依赖 // 1. 检查并处理依赖
check_and_install_dependencies(); check_and_install_dependencies();
// 2. 检查网络 // 2. 检查网络
if (has_internet_connection()) { if (has_internet_connection()) {
my_zlog_info("网络连接正常,正在检查音频资源..."); my_zlog_info("网络连接正常,正在确定区域语言并检查音频资源...");
download_audio_files(); prepare_offline_audio_after_network();
return; return;
} }
...@@ -313,9 +505,8 @@ void check_and_autoconfig_wifi() { ...@@ -313,9 +505,8 @@ void check_and_autoconfig_wifi() {
// 0. 优先检查网络是否已恢复 (比如插上了网线) // 0. 优先检查网络是否已恢复 (比如插上了网线)
if (has_internet_connection()) { if (has_internet_connection()) {
my_zlog_info("检测到网络已恢复,退出扫码模式。"); my_zlog_info("检测到网络已恢复,退出扫码模式。");
// 补一声连接成功的提示,让用户知道好了 prepare_offline_audio_after_network();
play_audio_file("connectionSuccessful.mp3"); play_audio_file("connectionSuccessful.mp3");
download_audio_files();
break; break;
} }
...@@ -376,12 +567,12 @@ void check_and_autoconfig_wifi() { ...@@ -376,12 +567,12 @@ void check_and_autoconfig_wifi() {
if (cJSON_IsString(ssid_item) && ssid_item->valuestring && if (cJSON_IsString(ssid_item) && ssid_item->valuestring &&
cJSON_IsString(pwd_item) && pwd_item->valuestring) { cJSON_IsString(pwd_item) && pwd_item->valuestring) {
my_zlog_info("解析成功,SSID: %s", ssid_item->valuestring); my_zlog_debug("解析成功,SSID: %s", ssid_item->valuestring);
play_audio_file("scanSuccessful.mp3"); play_audio_file("scanSuccessful.mp3");
if (try_connect_wifi(ssid_item->valuestring, pwd_item->valuestring)) { if (try_connect_wifi(ssid_item->valuestring, pwd_item->valuestring)) {
my_zlog_info("WiFi 连接成功!"); my_zlog_info("WiFi 连接成功!");
download_audio_files(); prepare_offline_audio_after_network();
play_audio_file("connectionSuccessful.mp3"); play_audio_file("connectionSuccessful.mp3");
cJSON_Delete(json); cJSON_Delete(json);
scan_success = 1; scan_success = 1;
...@@ -404,5 +595,5 @@ void check_and_autoconfig_wifi() { ...@@ -404,5 +595,5 @@ void check_and_autoconfig_wifi() {
// 清理临时文件 // 清理临时文件
unlink(img_path); unlink(img_path);
my_zlog_info("配网流程结束。"); my_zlog_debug("配网流程结束。");
} }
#ifndef WIFI_AUTOCONFIG_H__ #ifndef WIFI_AUTOCONFIG_H__
#define WIFI_AUTOCONFIG_H__ #define WIFI_AUTOCONFIG_H__
// 本地音频根目录
#define AUDIO_LOCAL_BASE "/home/orangepi/audio"
// 腾讯云 COS 音频根 URL
// 中文(已上线设备):car/audio/xxx.mp3(平铺,无子目录)
// 其他语言(预留): car/audio/{lang}/xxx.mp3
#define AUDIO_COS_BASE "https://fcrs-1367068685.cos.ap-guangzhou.myqcloud.com/car/audio/"
// 语言代码
#define AUDIO_LANG_ZH "zh" // 中文(默认,使用旧平铺路径,无子目录)
#define AUDIO_LANG_EN "EN" // 英语(COS/本地子目录均为 EN)
#define AUDIO_LANG_JA "ja" // 日语(预留子目录)
#define AUDIO_LANG_KO "ko" // 韩语(预留子目录)
#define AUDIO_LANG_ES "es" // 西班牙语(预留子目录)
// 离线本地音频语言配置(无网络时 play_audio_file 使用;有网络远程音频由后端接口控制,后续接入)
#define AUDIO_OFFLINE_LANG_FILE AUDIO_LOCAL_BASE "/offline_lang.txt"
// 启动断网自动配网流程 // 启动断网自动配网流程
void check_and_autoconfig_wifi(); void check_and_autoconfig_wifi();
// 播放指定名称的音频文件 (位于 ~/audio/ 目录下) // 启动时加载离线语言配置(默认中文)
void audio_init_offline_language(void);
// 设置/获取离线播放语言("zh"/"cn" 中文,"EN"/"en" 英语)
void audio_set_language(const char *lang_code);
const char *audio_get_language(void);
// 中英文切换(zh <-> EN),返回切换后的语言
const char *audio_toggle_cn_en(void);
// 播放离线本地音频(按当前语言;中文 ~/audio/xxx.mp3,英语 ~/audio/EN/xxx.mp3)
void play_audio_file(const char *filename); void play_audio_file(const char *filename);
#endif #endif
No preview for this file type
...@@ -199,7 +199,7 @@ int pg0403_serial_init_send(){ ...@@ -199,7 +199,7 @@ int pg0403_serial_init_send(){
return -1; return -1;
} }
serial_send(&s_pg_serial, start_continuous, sizeof(start_continuous)); serial_send(&s_pg_serial, start_continuous, sizeof(start_continuous));
my_zlog_info("串口发送成功,长度:%d",sizeof(start_continuous)); my_zlog_debug("串口发送成功,长度:%d",sizeof(start_continuous));
return 0; return 0;
} }
...@@ -301,7 +301,7 @@ void pg0403_serial_gpssend_mqtt_json(int id, uint16_t x, uint16_t y) { ...@@ -301,7 +301,7 @@ void pg0403_serial_gpssend_mqtt_json(int id, uint16_t x, uint16_t y) {
return; return;
} }
my_zlog_info("[MQTT Payload]: %s", json_str); my_zlog_debug("[MQTT Payload]: %s", json_str);
char mqtt_topic_pg[256]; char mqtt_topic_pg[256];
......
...@@ -27,7 +27,7 @@ void free_device_tasks_memory() { ...@@ -27,7 +27,7 @@ void free_device_tasks_memory() {
pthread_mutex_lock(&s_self_device_control_data_mutex); pthread_mutex_lock(&s_self_device_control_data_mutex);
free(s_self_device_control_data); free(s_self_device_control_data);
s_self_device_control_data=NULL; s_self_device_control_data=NULL;
my_zlog_info("free s_self_device_control_data"); my_zlog_debug("free s_self_device_control_data");
pthread_mutex_unlock(&s_self_device_control_data_mutex); pthread_mutex_unlock(&s_self_device_control_data_mutex);
} else return; } else return;
...@@ -41,7 +41,7 @@ void malloc_device_tasks_memory() { ...@@ -41,7 +41,7 @@ void malloc_device_tasks_memory() {
if(s_self_device_control_data==NULL){ if(s_self_device_control_data==NULL){
s_self_device_control_data=(devicecontroltask_t*)malloc(sizeof(devicecontroltask_t)); s_self_device_control_data=(devicecontroltask_t*)malloc(sizeof(devicecontroltask_t));
memset(s_self_device_control_data, 0, sizeof(devicecontroltask_t)); // 清零内存 memset(s_self_device_control_data, 0, sizeof(devicecontroltask_t)); // 清零内存
my_zlog_info("malloc s_self_device_control_data"); my_zlog_debug("malloc s_self_device_control_data");
} }
pthread_mutex_unlock(&s_self_device_control_data_mutex); pthread_mutex_unlock(&s_self_device_control_data_mutex);
} }
...@@ -115,7 +115,7 @@ static bool s_selfcontrol_task_index=true; ...@@ -115,7 +115,7 @@ static bool s_selfcontrol_task_index=true;
* @brief 自控线程 * @brief 自控线程
*/ */
void self_device_control_task_function(){ void self_device_control_task_function(){
my_zlog_info("自控线程池循环开始"); my_zlog_debug("自控线程池循环开始");
static int s_status =0; static int s_status =0;
while(s_selfcontrol_task_index){ while(s_selfcontrol_task_index){
if(s_self_control_switch==true){ if(s_self_control_switch==true){
...@@ -130,7 +130,7 @@ void self_device_control_task_function(){ ...@@ -130,7 +130,7 @@ void self_device_control_task_function(){
} }
} }
free_device_tasks_memory(); free_device_tasks_memory();
my_zlog_info("自控线程池循环终止"); my_zlog_debug("自控线程池循环终止");
return ; return ;
} }
...@@ -141,7 +141,7 @@ void self_device_pthrpoll_task_init(){ ...@@ -141,7 +141,7 @@ void self_device_pthrpoll_task_init(){
s_self_devicecontrol_task=thread_pool_init(1,1); s_self_devicecontrol_task=thread_pool_init(1,1);
thread_pool_add_task(s_self_devicecontrol_task, self_device_control_task_function, NULL); thread_pool_add_task(s_self_devicecontrol_task, self_device_control_task_function, NULL);
my_zlog_info("自控线程池打开"); my_zlog_debug("自控线程池打开");
} }
/* /*
...@@ -164,12 +164,12 @@ bool get_self_control_index(){ ...@@ -164,12 +164,12 @@ bool get_self_control_index(){
*/ */
void self_control_thread_close(){ void self_control_thread_close(){
if(get_self_control_index()==true){ if(get_self_control_index()==true){
my_zlog_info("Destroy the thread of the automatic control device"); my_zlog_debug("Destroy the thread of the automatic control device");
s_selfcontrol_task_index=false; s_selfcontrol_task_index=false;
thread_pool_destroy(s_self_devicecontrol_task); thread_pool_destroy(s_self_devicecontrol_task);
return ; return ;
} }
my_zlog_info("The thread of the automatic control device is not opened"); my_zlog_debug("The thread of the automatic control device is not opened");
} }
/* /*
...@@ -193,7 +193,7 @@ void send_self_contorl_mqtt(){ ...@@ -193,7 +193,7 @@ void send_self_contorl_mqtt(){
// 将cJSON对象转换为字符串 // 将cJSON对象转换为字符串
char *json_str = cJSON_PrintUnformatted(root); char *json_str = cJSON_PrintUnformatted(root);
my_zlog_info("%s",json_str); my_zlog_debug("%s",json_str);
mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0); mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0);
...@@ -222,7 +222,7 @@ void send_self_contorl_date_mqtt(){ ...@@ -222,7 +222,7 @@ void send_self_contorl_date_mqtt(){
// 将cJSON对象转换为字符串 // 将cJSON对象转换为字符串
char *json_str = cJSON_PrintUnformatted(root); char *json_str = cJSON_PrintUnformatted(root);
my_zlog_info("%s",json_str); my_zlog_debug("%s",json_str);
mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0); mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0);
......
...@@ -4,12 +4,129 @@ ...@@ -4,12 +4,129 @@
#include "mqtt_init.h" #include "mqtt_init.h"
#include "http_config_mqtt.h" #include "http_config_mqtt.h"
#include "audiotts_play.h" #include "audiotts_play.h"
#include "wifi_autoconfig.h"
#include <strings.h>
#include <unistd.h>
static int s_audio_status=7; static int s_audio_status=7;
static char s_urlbuf[512]; static char s_urlbuf[512];
static char s_keybuf[256]; static char s_keybuf[256];
static double s_audio_volume=0.8; static double s_audio_volume=0.8;
#define AUDIO_DRIVING_LEVEL_MAX 30
static int s_local_play_pending = 0;
static char s_local_filepath[512];
static int local_is_cn_lang(const char *lang) {
return lang != NULL && (strcmp(lang, AUDIO_LANG_ZH) == 0 || strcmp(lang, "cn") == 0);
}
static int local_is_en_lang(const char *lang) {
return lang != NULL &&
(strcmp(lang, AUDIO_LANG_EN) == 0 || strcmp(lang, "en") == 0 || strcmp(lang, "EN") == 0);
}
static void local_resolve_lang(const char *language_override, char *out, size_t size) {
if (language_override == NULL || language_override[0] == '\0' ||
strcasecmp(language_override, "default") == 0) {
snprintf(out, size, "%s", audio_get_language());
return;
}
if (local_is_cn_lang(language_override)) {
snprintf(out, size, "%s", AUDIO_LANG_ZH);
return;
}
if (local_is_en_lang(language_override)) {
snprintf(out, size, "%s", AUDIO_LANG_EN);
return;
}
snprintf(out, size, "%s", audio_get_language());
my_zlog_warn("2017 未知 language: %s,使用当前语言: %s", language_override, out);
}
static int local_resolve_filepath(const char *filename, const char *language_override,
char *out, size_t size) {
char lang[8];
int use_default_lang = (language_override == NULL || language_override[0] == '\0' ||
strcasecmp(language_override, "default") == 0);
local_resolve_lang(language_override, lang, sizeof(lang));
if (local_is_cn_lang(lang)) {
snprintf(out, size, "%s/%s", AUDIO_LOCAL_BASE, filename);
return access(out, F_OK) == 0;
}
snprintf(out, size, "%s/%s/%s", AUDIO_LOCAL_BASE, lang, filename);
if (access(out, F_OK) == 0) {
return 1;
}
if (use_default_lang) {
snprintf(out, size, "%s/%s", AUDIO_LOCAL_BASE, filename);
return access(out, F_OK) == 0;
}
return 0;
}
static void local_queue_play(const char *filename, const char *language) {
if (!local_resolve_filepath(filename, language, s_local_filepath, sizeof(s_local_filepath))) {
my_zlog_warn("2017 本地音频不存在: %s", filename);
return;
}
s_local_play_pending = 1;
my_zlog_info("2017 已排队本地音频: %s", s_local_filepath);
}
void audioplay_local_mqtt_receive(cJSON *body) {
if (!cJSON_IsObject(body)) {
my_zlog_warn("2017 body 无效");
return;
}
cJSON *status = cJSON_GetObjectItemCaseSensitive(body, "status");
cJSON *level_item = cJSON_GetObjectItemCaseSensitive(body, "level");
cJSON *language = cJSON_GetObjectItemCaseSensitive(body, "language");
if (!cJSON_IsString(status) || status->valuestring == NULL) {
my_zlog_warn("2017 缺少 status");
return;
}
const char *lang = "default";
if (cJSON_IsString(language) && language->valuestring != NULL) {
lang = language->valuestring;
}
if (strcmp(status->valuestring, "speed") == 0) {
local_queue_play("Speedupforoneminute.mp3", lang);
return;
}
if (strcmp(status->valuestring, "drivinglevel") == 0) {
int level = 0;
if (cJSON_IsString(level_item) && level_item->valuestring != NULL) {
level = atoi(level_item->valuestring);
} else if (cJSON_IsNumber(level_item)) {
level = level_item->valueint;
} else {
my_zlog_warn("2017 drivinglevel 缺少 level");
return;
}
if (level < 1 || level > AUDIO_DRIVING_LEVEL_MAX) {
my_zlog_warn("2017 drivinglevel level 无效: %d (1-%d)",
level, AUDIO_DRIVING_LEVEL_MAX);
return;
}
char filename[48];
snprintf(filename, sizeof(filename), "DrivingLevel%d.mp3", level);
local_queue_play(filename, lang);
return;
}
my_zlog_warn("2017 未知 status: %s", status->valuestring);
}
static double audioplay_volume_clamp(double v) { static double audioplay_volume_clamp(double v) {
if (v < 0.0) { if (v < 0.0) {
return 0.0; return 0.0;
...@@ -103,7 +220,7 @@ void audioplay_cycle(){ ...@@ -103,7 +220,7 @@ void audioplay_cycle(){
s_audio_volume,urlmoddle); s_audio_volume,urlmoddle);
my_zlog_debug("播放地址: %s", s_urlbuf); my_zlog_debug("播放地址: %s", s_urlbuf);
my_zlog_info("执行播放命令: %s", command); my_zlog_debug("执行播放命令: %s", command);
ret = system(command); ret = system(command);
if (ret != 0) { if (ret != 0) {
my_zlog_error("播放失败"); my_zlog_error("播放失败");
...@@ -120,6 +237,19 @@ void audioplay_cycle(){ ...@@ -120,6 +237,19 @@ void audioplay_cycle(){
audioplay_send_mqtt(); audioplay_send_mqtt();
} }
if (s_local_play_pending) {
s_local_play_pending = 0;
snprintf(command, sizeof(command),
"ffplay -nodisp -autoexit -loglevel quiet \"%s\"", s_local_filepath);
my_zlog_debug("播放本地音频: %s", s_local_filepath);
ret = system(command);
if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) {
my_zlog_debug("本地音频播放完成: %s", s_local_filepath);
} else {
my_zlog_warn("本地音频播放失败: %s", s_local_filepath);
}
}
video_tts_play(); video_tts_play();
delay_ms(100); delay_ms(100);
...@@ -218,7 +348,7 @@ int audio_config_init() { ...@@ -218,7 +348,7 @@ int audio_config_init() {
// 检查是否包含完整配置块 // 检查是否包含完整配置块
if (strstr(buffer, s_yundea_block) != NULL) { if (strstr(buffer, s_yundea_block) != NULL) {
my_zlog_info("配置文件中已包含指定配置,跳过添加。"); my_zlog_debug("配置文件中已包含指定配置,跳过添加。");
free(buffer); free(buffer);
return 0; return 0;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <cjson/cJSON.h> #include <cjson/cJSON.h>
void audioplay_mqtt_receive(cJSON *body); //接收音频mqtt播放函数 void audioplay_mqtt_receive(cJSON *body); //接收音频mqtt播放函数
void audioplay_local_mqtt_receive(cJSON *body); // 2017 有人驾驶本地音频
void audioplay_cycle();//音频播放线程中函数 void audioplay_cycle();//音频播放线程中函数
int audio_wheat_init(); int audio_wheat_init();
......
...@@ -108,7 +108,7 @@ static int save_audio_file(const void *data, size_t len, const char *filepath) { ...@@ -108,7 +108,7 @@ static int save_audio_file(const void *data, size_t len, const char *filepath) {
return 1; return 1;
} }
my_zlog_info("Success! Audio saved to: %s (%zu bytes)", filepath, written); my_zlog_debug("Success! Audio saved to: %s (%zu bytes)", filepath, written);
return 0; return 0;
} }
...@@ -170,7 +170,7 @@ int audio_tts(const char *text) { ...@@ -170,7 +170,7 @@ int audio_tts(const char *text) {
// 2. 生成唯一 reqid(每次调用必须不同) // 2. 生成唯一 reqid(每次调用必须不同)
char reqid[33] = {0}; char reqid[33] = {0};
generate_uuid(reqid, sizeof(reqid)); generate_uuid(reqid, sizeof(reqid));
my_zlog_info("Generated ReqID: %s", reqid); my_zlog_debug("Generated ReqID: %s", reqid);
// 3. 构建请求 JSON(严格遵循接口参数格式) // 3. 构建请求 JSON(严格遵循接口参数格式)
cJSON *root = cJSON_CreateObject(); cJSON *root = cJSON_CreateObject();
...@@ -220,7 +220,7 @@ int audio_tts(const char *text) { ...@@ -220,7 +220,7 @@ int audio_tts(const char *text) {
free(uid); free(uid);
return 1; return 1;
} }
my_zlog_info("Request Payload: %s", payload); my_zlog_debug("Request Payload: %s", payload);
// 4. 初始化 curl 并配置 HTTP 请求 // 4. 初始化 curl 并配置 HTTP 请求
curl_global_init(CURL_GLOBAL_DEFAULT); curl_global_init(CURL_GLOBAL_DEFAULT);
...@@ -259,7 +259,7 @@ int audio_tts(const char *text) { ...@@ -259,7 +259,7 @@ int audio_tts(const char *text) {
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // 连接超时 10 秒 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // 连接超时 10 秒
// 5. 执行 HTTP 请求 // 5. 执行 HTTP 请求
my_zlog_info("Sending request to %s...", endpoint); my_zlog_debug("Sending request to %s...", endpoint);
CURLcode res = curl_easy_perform(curl); CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
my_zlog_error("curl_easy_perform failed: %s", curl_easy_strerror(res)); my_zlog_error("curl_easy_perform failed: %s", curl_easy_strerror(res));
...@@ -272,7 +272,7 @@ int audio_tts(const char *text) { ...@@ -272,7 +272,7 @@ int audio_tts(const char *text) {
} }
// 6. 解析 HTTP 响应(JSON 格式) // 6. 解析 HTTP 响应(JSON 格式)
my_zlog_info("Response Length: %zu bytes", s_http_response_len); my_zlog_debug("Response Length: %zu bytes", s_http_response_len);
if (s_http_response_len == 0) { if (s_http_response_len == 0) {
my_zlog_error("Empty response from server"); my_zlog_error("Empty response from server");
free(uid); free(uid);
...@@ -317,7 +317,7 @@ int audio_tts(const char *text) { ...@@ -317,7 +317,7 @@ int audio_tts(const char *text) {
curl_global_cleanup(); curl_global_cleanup();
return 1; return 1;
} }
my_zlog_info("Request succeeded! Code: %d, Message: %s", code->valueint, message->valuestring); my_zlog_debug("Request succeeded! Code: %d, Message: %s", code->valueint, message->valuestring);
// 关键:直接提取 data 字段的 Base64 音频字符串(接口实际返回格式) // 关键:直接提取 data 字段的 Base64 音频字符串(接口实际返回格式)
cJSON *audio_base64 = cJSON_GetObjectItem(response_json, "data"); cJSON *audio_base64 = cJSON_GetObjectItem(response_json, "data");
...@@ -332,7 +332,7 @@ int audio_tts(const char *text) { ...@@ -332,7 +332,7 @@ int audio_tts(const char *text) {
curl_global_cleanup(); curl_global_cleanup();
return 1; return 1;
} }
my_zlog_info("Audio Base64 Length: %zu bytes", strlen(audio_base64->valuestring)); my_zlog_debug("Audio Base64 Length: %zu bytes", strlen(audio_base64->valuestring));
// 7. Base64 解码音频数据 // 7. Base64 解码音频数据
size_t audio_len = 0; size_t audio_len = 0;
...@@ -348,7 +348,7 @@ int audio_tts(const char *text) { ...@@ -348,7 +348,7 @@ int audio_tts(const char *text) {
curl_global_cleanup(); curl_global_cleanup();
return 1; return 1;
} }
my_zlog_info("Decoded Audio Length: %zu bytes", audio_len); my_zlog_debug("Decoded Audio Length: %zu bytes", audio_len);
if(save_audio_file(audio_data, audio_len, TTS_ADUINO_PTAH) != 0) {//保存文件 if(save_audio_file(audio_data, audio_len, TTS_ADUINO_PTAH) != 0) {//保存文件
my_zlog_error("save_audio_file fail"); my_zlog_error("save_audio_file fail");
...@@ -440,7 +440,7 @@ int mqtt_audio_tts(cJSON *body){ ...@@ -440,7 +440,7 @@ int mqtt_audio_tts(cJSON *body){
cJSON* date = cJSON_GetObjectItem(body, "date"); cJSON* date = cJSON_GetObjectItem(body, "date");
if(date!=NULL){ if(date!=NULL){
get_audio_text_tts(date->valuestring,0); get_audio_text_tts(date->valuestring,0);
my_zlog_info("text:%s",date->valuestring); my_zlog_debug("text:%s",date->valuestring);
}else { }else {
return 1; return 1;
} }
...@@ -503,7 +503,7 @@ void video_tts_play() { ...@@ -503,7 +503,7 @@ void video_tts_play() {
int status; int status;
waitpid(pid, &status, WNOHANG); // 不阻塞的等待 waitpid(pid, &status, WNOHANG); // 不阻塞的等待
my_zlog_info("启动独立播放进程 PID: %d", pid); my_zlog_debug("启动独立播放进程 PID: %d", pid);
s_audio_tts_index = 0; s_audio_tts_index = 0;
} }
else { else {
......
...@@ -145,7 +145,7 @@ int go_deploy_check_and_update(void) { ...@@ -145,7 +145,7 @@ int go_deploy_check_and_update(void) {
char target_dir[256]; char target_dir[256];
snprintf(target_dir, sizeof(target_dir), "%s/go_video", home_dir); snprintf(target_dir, sizeof(target_dir), "%s/go_video", home_dir);
my_zlog_info("target_dir: %s", target_dir); my_zlog_debug("target_dir: %s", target_dir);
// 确保目录存在 // 确保目录存在
struct stat st = {0}; struct stat st = {0};
...@@ -153,7 +153,7 @@ int go_deploy_check_and_update(void) { ...@@ -153,7 +153,7 @@ int go_deploy_check_and_update(void) {
if (mkdir(target_dir, 0777) != 0) { if (mkdir(target_dir, 0777) != 0) {
my_zlog_error("Failed to create directory: %s", target_dir); my_zlog_error("Failed to create directory: %s", target_dir);
} else { } else {
my_zlog_info("Created directory: %s", target_dir); my_zlog_debug("Created directory: %s", target_dir);
} }
} }
// 确保目录权限正确 // 确保目录权限正确
...@@ -161,7 +161,7 @@ int go_deploy_check_and_update(void) { ...@@ -161,7 +161,7 @@ int go_deploy_check_and_update(void) {
char target_file_path[512]; char target_file_path[512];
snprintf(target_file_path, sizeof(target_file_path), "%s/%s", target_dir, GO_VIDEO_FILENAME); snprintf(target_file_path, sizeof(target_file_path), "%s/%s", target_dir, GO_VIDEO_FILENAME);
my_zlog_info("target_file_path: %s", target_file_path); my_zlog_debug("target_file_path: %s", target_file_path);
// 1. 请求 Config // 1. 请求 Config
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
...@@ -180,7 +180,7 @@ int go_deploy_check_and_update(void) { ...@@ -180,7 +180,7 @@ int go_deploy_check_and_update(void) {
} }
snprintf(url, sizeof(url), "https://fcrs-api.yd-ss.com/device/getConfig?deviceNo=%s", device_no); snprintf(url, sizeof(url), "https://fcrs-api.yd-ss.com/device/getConfig?deviceNo=%s", device_no);
//snprintf(url, sizeof(url), "http://192.168.0.100:8111/device/getConfig?deviceNo=%s", device_no); //snprintf(url, sizeof(url), "http://192.168.0.100:8111/device/getConfig?deviceNo=%s", device_no);
my_zlog_info("Requesting URL: %s", url); my_zlog_debug("Requesting URL: %s", url);
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
...@@ -190,7 +190,7 @@ int go_deploy_check_and_update(void) { ...@@ -190,7 +190,7 @@ int go_deploy_check_and_update(void) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
my_zlog_info("curl_easy_perform result: %d", res); my_zlog_debug("curl_easy_perform result: %d", res);
if (res != CURLE_OK) { if (res != CURLE_OK) {
my_zlog_error("curl_easy_perform() failed: %s", curl_easy_strerror(res)); my_zlog_error("curl_easy_perform() failed: %s", curl_easy_strerror(res));
...@@ -207,7 +207,7 @@ int go_deploy_check_and_update(void) { ...@@ -207,7 +207,7 @@ int go_deploy_check_and_update(void) {
cJSON *data = cJSON_GetObjectItem(root, "data"); cJSON *data = cJSON_GetObjectItem(root, "data");
char *data_str = cJSON_Print(data); char *data_str = cJSON_Print(data);
if (data_str) { if (data_str) {
my_zlog_info("Got config data: %s", data_str); my_zlog_debug("Got config data: %s", data_str);
free(data_str); free(data_str);
} }
if (!data) { if (!data) {
...@@ -261,7 +261,7 @@ int go_deploy_check_and_update(void) { ...@@ -261,7 +261,7 @@ int go_deploy_check_and_update(void) {
my_zlog_info("Hash mismatch. Local: %s, Cloud: %s. Re-downloading...", local_hash, goHash->valuestring); my_zlog_info("Hash mismatch. Local: %s, Cloud: %s. Re-downloading...", local_hash, goHash->valuestring);
need_download = 1; need_download = 1;
} else { } else {
my_zlog_info("File hash verified. No update needed."); my_zlog_debug("File hash verified. No update needed.");
} }
} else { } else {
my_zlog_error("Failed to calculate local hash"); my_zlog_error("Failed to calculate local hash");
...@@ -301,7 +301,7 @@ int go_deploy_check_and_update(void) { ...@@ -301,7 +301,7 @@ int go_deploy_check_and_update(void) {
int need_download_7z = 0; int need_download_7z = 0;
// 检查文件是否存在 // 检查文件是否存在
my_zlog_info("target_7z_path:%s",target_7z_path); my_zlog_debug("target_7z_path:%s",target_7z_path);
if (access(target_7z_path, F_OK) != 0) { if (access(target_7z_path, F_OK) != 0) {
my_zlog_info("video_proxy.7z not found, need download."); my_zlog_info("video_proxy.7z not found, need download.");
need_download_7z = 1; need_download_7z = 1;
...@@ -315,7 +315,7 @@ int go_deploy_check_and_update(void) { ...@@ -315,7 +315,7 @@ int go_deploy_check_and_update(void) {
my_zlog_info("7z Hash mismatch. Local: %s, Cloud: %s. Re-downloading...", local_hash, goHash->valuestring); my_zlog_info("7z Hash mismatch. Local: %s, Cloud: %s. Re-downloading...", local_hash, goHash->valuestring);
need_download_7z = 1; need_download_7z = 1;
} else { } else {
my_zlog_info("7z Hash verified."); my_zlog_debug("7z Hash verified.");
} }
} else { } else {
my_zlog_error("Failed to calculate 7z local hash"); my_zlog_error("Failed to calculate 7z local hash");
...@@ -349,7 +349,7 @@ int go_deploy_check_and_update(void) { ...@@ -349,7 +349,7 @@ int go_deploy_check_and_update(void) {
char cmd[1024]; char cmd[1024];
// 使用密码 fcrs2025606 解压, -y 自动覆盖, -o 指定输出目录 // 使用密码 fcrs2025606 解压, -y 自动覆盖, -o 指定输出目录
snprintf(cmd, sizeof(cmd), "7z x \"%s\" -o\"%s\" -pfcrs2025606 -y", target_7z_path, target_dir); snprintf(cmd, sizeof(cmd), "7z x \"%s\" -o\"%s\" -pfcrs2025606 -y", target_7z_path, target_dir);
my_zlog_info("Executing: %s", cmd); my_zlog_debug("Executing: %s", cmd);
int extract_ret = system(cmd); int extract_ret = system(cmd);
if (extract_ret == 0) { if (extract_ret == 0) {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include "http_config_mqtt.h" #include "http_config_mqtt.h"
#include "common.h" #include "common.h"
#include "http_request.h" #include "http_request.h"
#include "wifi_autoconfig.h"
#include <strings.h>
static DEVICE_MQTTCONFIG s_mqtt_cam_config; static DEVICE_MQTTCONFIG s_mqtt_cam_config;
DEVICE_MQTTCONFIG *g_mqtt_cam_config_t = &s_mqtt_cam_config; DEVICE_MQTTCONFIG *g_mqtt_cam_config_t = &s_mqtt_cam_config;
...@@ -16,6 +18,138 @@ void default_device_mqtt_cam(){ ...@@ -16,6 +18,138 @@ void default_device_mqtt_cam(){
g_mqtt_cam_config_t->videourl[sizeof(g_mqtt_cam_config_t->videourl) - 1] = '\0'; g_mqtt_cam_config_t->videourl[sizeof(g_mqtt_cam_config_t->videourl) - 1] = '\0';
} }
// 联调前可临时改为 "EN" 强制英语;正式环境留空,走接口 moreInfo.language
#ifndef DEVICE_LANGUAGE_MOCK
#define DEVICE_LANGUAGE_MOCK ""
#endif
static void apply_region_language_code(const char *region) {
if (region == NULL || region[0] == '\0') {
audio_set_language(AUDIO_LANG_ZH);
my_zlog_debug("区域语言未指定,默认中文");
return;
}
if (strcasecmp(region, "CN") == 0 || strcasecmp(region, "ZH") == 0 ||
strcasecmp(region, "zh") == 0) {
audio_set_language(AUDIO_LANG_ZH);
my_zlog_info("区域语言: 中文 (CN)");
return;
}
if (strcasecmp(region, "EN") == 0 || strcasecmp(region, "en") == 0) {
audio_set_language(AUDIO_LANG_EN);
my_zlog_info("区域语言: 英语 (EN)");
return;
}
my_zlog_warn("未知区域语言: %s,默认中文", region);
audio_set_language(AUDIO_LANG_ZH);
}
static void parse_moreinfo_language(cJSON *data) {
const char *mock = DEVICE_LANGUAGE_MOCK;
if (mock[0] != '\0') {
my_zlog_info("使用联调假字段 DEVICE_LANGUAGE_MOCK=%s", mock);
apply_region_language_code(mock);
return;
}
if (!data) {
apply_region_language_code("CN");
return;
}
cJSON *moreInfo = cJSON_GetObjectItemCaseSensitive(data, "moreInfo");
if (!moreInfo) {
my_zlog_debug("moreInfo 缺失,默认中文");
apply_region_language_code("CN");
return;
}
cJSON *language = cJSON_GetObjectItemCaseSensitive(moreInfo, "language");
if (!cJSON_IsString(language) || language->valuestring == NULL || language->valuestring[0] == '\0') {
my_zlog_debug("moreInfo.language 缺失,默认中文");
apply_region_language_code("CN");
return;
}
apply_region_language_code(language->valuestring);
}
static int fetch_device_config_json(struct MemoryStruct *chunk) {
CURL *curl;
CURLcode res;
chunk->memory = malloc(1);
chunk->size = 0;
if (!chunk->memory) {
return -1;
}
curl = curl_easy_init();
if (!curl) {
free(chunk->memory);
chunk->memory = NULL;
return -1;
}
char url[512];
snprintf(url, sizeof(url), "https://fcrs-api.yd-ss.com/device/getConfig?deviceNo=%s",
mqtt_topic_pure_number());
my_zlog_debug("getConfig 拉取区域语言: %s", url);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writememorycallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 8L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
my_zlog_warn("getConfig 请求失败: %s", curl_easy_strerror(res));
free(chunk->memory);
chunk->memory = NULL;
chunk->size = 0;
return -1;
}
return 0;
}
int device_fetch_region_language(void) {
struct MemoryStruct chunk = {NULL, 0};
int rc = -1;
curl_global_init(CURL_GLOBAL_DEFAULT);
if (fetch_device_config_json(&chunk) != 0) {
curl_global_cleanup();
return -1;
}
cJSON *root = cJSON_Parse(chunk.memory);
if (!root) {
my_zlog_warn("getConfig JSON 解析失败");
goto cleanup;
}
cJSON *code = cJSON_GetObjectItemCaseSensitive(root, "code");
if (!cJSON_IsNumber(code) || code->valueint != 200) {
my_zlog_warn("getConfig 返回码异常");
cJSON_Delete(root);
goto cleanup;
}
cJSON *data = cJSON_GetObjectItemCaseSensitive(root, "data");
parse_moreinfo_language(data);
cJSON_Delete(root);
rc = 0;
cleanup:
free(chunk.memory);
curl_global_cleanup();
return rc;
}
int parse_device_config(const char *json_str) { int parse_device_config(const char *json_str) {
// 解析 JSON // 解析 JSON
cJSON *root = cJSON_Parse(json_str); cJSON *root = cJSON_Parse(json_str);
...@@ -46,14 +180,14 @@ int parse_device_config(const char *json_str) { ...@@ -46,14 +180,14 @@ int parse_device_config(const char *json_str) {
// 3. 提取 mqtt 服务器列表 // 3. 提取 mqtt 服务器列表
cJSON *mqtt = cJSON_GetObjectItemCaseSensitive(data, "mqtt"); cJSON *mqtt = cJSON_GetObjectItemCaseSensitive(data, "mqtt");
if (cJSON_IsArray(mqtt)) { if (cJSON_IsArray(mqtt)) {
my_zlog_info("MQTT 服务器:"); my_zlog_debug("MQTT 服务器:");
cJSON *item; cJSON *item;
int i = 0; int i = 0;
cJSON_ArrayForEach(item, mqtt) { cJSON_ArrayForEach(item, mqtt) {
if (cJSON_IsString(item)) { if (cJSON_IsString(item)) {
strncpy(g_mqtt_cam_config_t->mqtt_servers[i], item->valuestring, sizeof(g_mqtt_cam_config_t->mqtt_servers[i]) - 1); strncpy(g_mqtt_cam_config_t->mqtt_servers[i], item->valuestring, sizeof(g_mqtt_cam_config_t->mqtt_servers[i]) - 1);
g_mqtt_cam_config_t->mqtt_servers[i][sizeof(g_mqtt_cam_config_t->mqtt_servers[i]) - 1] = '\0'; g_mqtt_cam_config_t->mqtt_servers[i][sizeof(g_mqtt_cam_config_t->mqtt_servers[i]) - 1] = '\0';
my_zlog_info(" [%d] %s", i+1, g_mqtt_cam_config_t->mqtt_servers[i]); my_zlog_debug(" [%d] %s", i+1, g_mqtt_cam_config_t->mqtt_servers[i]);
i = i + 1; i = i + 1;
} }
} }
...@@ -68,10 +202,13 @@ int parse_device_config(const char *json_str) { ...@@ -68,10 +202,13 @@ int parse_device_config(const char *json_str) {
strncpy(g_mqtt_cam_config_t->videourl, videoUrl->valuestring, sizeof(g_mqtt_cam_config_t->videourl) - 1); strncpy(g_mqtt_cam_config_t->videourl, videoUrl->valuestring, sizeof(g_mqtt_cam_config_t->videourl) - 1);
g_mqtt_cam_config_t->videourl[sizeof(g_mqtt_cam_config_t->videourl) - 1] = '\0'; g_mqtt_cam_config_t->videourl[sizeof(g_mqtt_cam_config_t->videourl) - 1] = '\0';
} }
parse_moreinfo_language(data);
} }
// 释放内存 // 释放内存
cJSON_Delete(root); cJSON_Delete(root);
return 0;
} }
// 拉取并解析 JSON 数据的函数 // 拉取并解析 JSON 数据的函数
...@@ -94,7 +231,7 @@ int deviceconfig_mqtt_video_init() { ...@@ -94,7 +231,7 @@ int deviceconfig_mqtt_video_init() {
// 构造请求 URL // 构造请求 URL
char url[512]; char url[512];
snprintf(url, sizeof(url), "https://fcrs-api.yd-ss.com/device/getConfig?deviceNo=%s", mqtt_topic_pure_number()); snprintf(url, sizeof(url), "https://fcrs-api.yd-ss.com/device/getConfig?deviceNo=%s", mqtt_topic_pure_number());
my_zlog_info("url:%s",url); my_zlog_debug("url:%s",url);
// 设置 CURL 选项 // 设置 CURL 选项
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
...@@ -137,7 +274,7 @@ int http_mqtt_video_init(){ ...@@ -137,7 +274,7 @@ int http_mqtt_video_init(){
my_zlog_info("http_mqtt_video_init success"); my_zlog_info("http_mqtt_video_init success");
return 0; return 0;
}else { }else {
my_zlog_info("http_mqtt_video_init reconnect"); my_zlog_debug("http_mqtt_video_init reconnect");
} }
} }
my_zlog_error("http_mqtt_video_init failure"); my_zlog_error("http_mqtt_video_init failure");
......
...@@ -16,4 +16,7 @@ extern DEVICE_MQTTCONFIG *g_mqtt_cam_config_t; ...@@ -16,4 +16,7 @@ extern DEVICE_MQTTCONFIG *g_mqtt_cam_config_t;
/*mqtt服务器和视频流地址初始化*/ /*mqtt服务器和视频流地址初始化*/
int http_mqtt_video_init(); int http_mqtt_video_init();
// 有网时拉取 getConfig.moreInfo.language(CN/EN),在下载离线音频前调用
int device_fetch_region_language(void);
#endif #endif
\ No newline at end of file
...@@ -344,7 +344,7 @@ int device_message_receive(cJSON *json) ...@@ -344,7 +344,7 @@ int device_message_receive(cJSON *json)
if (s_message_type == 2013) { if (s_message_type == 2013) {
if (message2013_recverigy_open(body) == 0) { if (message2013_recverigy_open(body) == 0) {
my_zlog_info("进入是否需要验证"); my_zlog_debug("进入是否需要验证");
return 0; return 0;
} }
return 1; return 1;
...@@ -374,7 +374,7 @@ int device_message_receive(cJSON *json) ...@@ -374,7 +374,7 @@ int device_message_receive(cJSON *json)
case 5: case 5:
audio_wheat_init(); audio_wheat_init();
audio_speaker_init(); audio_speaker_init();
my_zlog_info("执行麦和喇叭命令"); my_zlog_debug("执行麦和喇叭命令");
break; break;
case 6: case 6:
message_6_steering_judyverify(body); message_6_steering_judyverify(body);
...@@ -386,35 +386,35 @@ int device_message_receive(cJSON *json) ...@@ -386,35 +386,35 @@ int device_message_receive(cJSON *json)
break; break;
case 2001: case 2001:
audioplay_mqtt_receive(body); audioplay_mqtt_receive(body);
my_zlog_info("进入音频播放"); my_zlog_debug("进入音频播放");
break; break;
case 2002: case 2002:
device_mqttchange_name(body); device_mqttchange_name(body);
my_zlog_info("进入修改设备号"); my_zlog_debug("进入修改设备号");
break; break;
case 2003: case 2003:
scan_wifi_json(); scan_wifi_json();
my_zlog_info("进入查询WiFi"); my_zlog_debug("进入查询WiFi");
break; break;
case 2004: case 2004:
// wifi_change_recmqtt(body); // wifi_change_recmqtt(body);
my_zlog_info("进入修改WiFi"); my_zlog_debug("进入修改WiFi");
break; break;
case 2006: case 2006:
message2006_verify(body); message2006_verify(body);
my_zlog_info("进入消息为2006验证"); my_zlog_debug("进入消息为2006验证");
break; break;
case 2007: case 2007:
device_send_saved_wifi(); device_send_saved_wifi();
my_zlog_info("查询已保存wifi和现在已连接WiFi"); my_zlog_debug("查询已保存wifi和现在已连接WiFi");
break; break;
case 2008: case 2008:
device_wifi_rec_sava(body); device_wifi_rec_sava(body);
my_zlog_info("保存wifi"); my_zlog_debug("保存wifi");
break; break;
case 2009: case 2009:
device_wifi_rec_delete(body); device_wifi_rec_delete(body);
my_zlog_info("删除已保存wifi"); my_zlog_debug("删除已保存wifi");
break; break;
case 2011: case 2011:
int res = system("sudo reboot"); // 重启香橙派 int res = system("sudo reboot"); // 重启香橙派
...@@ -423,27 +423,31 @@ int device_message_receive(cJSON *json) ...@@ -423,27 +423,31 @@ int device_message_receive(cJSON *json)
break; break;
case 2012: case 2012:
refresh_cam(); refresh_cam();
my_zlog_info("刷新成功"); my_zlog_debug("刷新成功");
break; break;
case 2016: case 2016:
mqtt_verify_data_clear(body); mqtt_verify_data_clear(body);
my_zlog_info("清除验证数据"); my_zlog_debug("清除验证数据");
break;
case 2017:
audioplay_local_mqtt_receive(body);
my_zlog_debug("有人驾驶本地音频");
break; break;
case 2025: case 2025:
receive_self_contorl_mqtt(body); receive_self_contorl_mqtt(body);
my_zlog_info("device self comtrol"); my_zlog_debug("device self comtrol");
break; break;
case 2026: case 2026:
receive_self_contorl_date_mqtt(body); receive_self_contorl_date_mqtt(body);
my_zlog_info("device self comtrol date save"); my_zlog_debug("device self comtrol date save");
break; break;
case 2027: case 2027:
mqtt_audio_tts(body); mqtt_audio_tts(body);
my_zlog_info("device audio_tts"); my_zlog_debug("device audio_tts");
break; break;
case 2028: case 2028:
tailscale_control(body); tailscale_control(body);
my_zlog_info("tailscale control"); my_zlog_debug("tailscale control");
break; break;
default: default:
break; break;
......
...@@ -136,8 +136,7 @@ void on_connect(struct mosquitto *mosq, void *obj, int rc) { ...@@ -136,8 +136,7 @@ void on_connect(struct mosquitto *mosq, void *obj, int rc) {
} }
if (rc == 0) { if (rc == 0) {
my_zlog_info("Connected to broker"); my_zlog_info("MQTT已连接 %s:%d (%s)",
my_zlog_info("[Connected] %s:%d (%s)",
client_t->host, client_t->port, client_t->client_id); client_t->host, client_t->port, client_t->client_id);
client_t->reconnect_attempts = 0; client_t->reconnect_attempts = 0;
client_t->permanently_failed = false; client_t->permanently_failed = false;
...@@ -182,7 +181,7 @@ void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_messag ...@@ -182,7 +181,7 @@ void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_messag
return; return;
} }
my_zlog_info("[Message from %s:%d] topic=%s payload=%s", my_zlog_debug("[Message from %s:%d] topic=%s payload=%s",
client_t->host, client_t->port, client_t->host, client_t->port,
message->topic, (char*)message->payload); message->topic, (char*)message->payload);
...@@ -297,7 +296,7 @@ int add_mqtt_create(const char *host, int port, int clients_idx) { ...@@ -297,7 +296,7 @@ int add_mqtt_create(const char *host, int port, int clients_idx) {
return -1; return -1;
} }
my_zlog_info("成功为主机 %s 添加 MQTT 客户端", host); my_zlog_debug("成功为主机 %s 添加 MQTT 客户端", host);
return 0; // 成功 return 0; // 成功
} }
...@@ -318,12 +317,12 @@ void mqtt_clean(){ ...@@ -318,12 +317,12 @@ void mqtt_clean(){
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
s_mosquitto_lib_inited = false; s_mosquitto_lib_inited = false;
} }
my_zlog_info("清理成功"); my_zlog_debug("MQTT 清理完成");
} }
int mqtt_cycle() {//非阻塞型 int mqtt_cycle() {//非阻塞型
my_zlog_info("MQTT 异步监控线程启动"); my_zlog_debug("MQTT 异步监控线程启动");
int check_interval = 30; // 30秒检查一次,减少日志频率 int check_interval = 30; // 30秒检查一次,减少日志频率
......
...@@ -100,8 +100,7 @@ int receive_jwt(cJSON *body) { ...@@ -100,8 +100,7 @@ int receive_jwt(cJSON *body) {
cJSON *json_token = cJSON_GetObjectItem(body, "token"); cJSON *json_token = cJSON_GetObjectItem(body, "token");
cJSON *json_token_time = cJSON_GetObjectItem(body, "token_time"); cJSON *json_token_time = cJSON_GetObjectItem(body, "token_time");
if(json_token == NULL || json_token_time==NULL) { if(json_token == NULL || json_token_time==NULL) {
my_zlog_warn("JWT验证失败: token或token_time字段缺失, token=%s", my_zlog_warn("JWT验证失败: token或token_time字段缺失");
(json_token && cJSON_IsString(json_token) && json_token->valuestring) ? json_token->valuestring : "<null>");
g_verify_index=1; g_verify_index=1;
return 1; return 1;
} }
...@@ -111,8 +110,7 @@ int receive_jwt(cJSON *body) { ...@@ -111,8 +110,7 @@ int receive_jwt(cJSON *body) {
/* 空字符串视为无效,不发给后端 */ /* 空字符串视为无效,不发给后端 */
if (token == NULL || token[0] == '\0' || token_time == NULL || token_time[0] == '\0') { if (token == NULL || token[0] == '\0' || token_time == NULL || token_time[0] == '\0') {
my_zlog_error("JWT验证失败: token或token_time为空, token=%s", my_zlog_error("JWT验证失败: token或token_time为空");
(token && token[0] != '\0') ? token : "<empty>");
g_verify_index = 1; g_verify_index = 1;
return 1; return 1;
} }
...@@ -429,7 +427,7 @@ void mqtt_verify_data_clear(cJSON *body){ ...@@ -429,7 +427,7 @@ void mqtt_verify_data_clear(cJSON *body){
const char *status = verify_clear_item->valuestring; const char *status = verify_clear_item->valuestring;
if (strcmp(status, "clear") == 0) { if (strcmp(status, "clear") == 0) {
my_zlog_info("状态为 clear,执行清理操作"); my_zlog_debug("状态为 clear,执行清理操作");
pthread_mutex_lock(&g_verify_mutex); pthread_mutex_lock(&g_verify_mutex);
g_verify_count = 12001; g_verify_count = 12001;
pthread_mutex_unlock(&g_verify_mutex); pthread_mutex_unlock(&g_verify_mutex);
...@@ -437,7 +435,7 @@ void mqtt_verify_data_clear(cJSON *body){ ...@@ -437,7 +435,7 @@ void mqtt_verify_data_clear(cJSON *body){
mqtt_verify_clear_send("1"); mqtt_verify_clear_send("1");
} else { } else {
my_zlog_info("状态为: %s", status); my_zlog_debug("状态为: %s", status);
mqtt_verify_clear_send("0"); mqtt_verify_clear_send("0");
} }
} else { } else {
......
...@@ -9,4 +9,4 @@ file perms = 600 ...@@ -9,4 +9,4 @@ file perms = 600
millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n" millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n"
[rules] [rules]
my_log.* "/home/orangepi/car/master/log/log_2026-06-10.log"; millisecond my_log.* "/home/orangepi/car/master/log/log_2026-06-24.log"; millisecond
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment