Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
car-controlserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wenzhongjian
car-controlserver
Commits
29e01fc4
Commit
29e01fc4
authored
Jun 24, 2026
by
957dd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
加入了音频播放的英文播放
parent
6eca326e
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
635 additions
and
141 deletions
+635
-141
device_wifi_change.c
app/device_change/device_wifi_change.c
+2
-2
device_fileopen.c
app/device_identity/device_fileopen.c
+4
-1
wifi_autoconfig.c
app/main/wifi_autoconfig.c
+261
-70
wifi_autoconfig.h
app/main/wifi_autoconfig.h
+28
-1
main
build/main
+0
-0
pg0403_serial.c
drivers/devicecontrol/pg0403_serial.c
+2
-2
self_devicecontrol.c
drivers/selfcontrol/self_devicecontrol.c
+9
-9
audioplay.c
drivers/sensors/audioplay.c
+132
-2
audioplay.h
drivers/sensors/audioplay.h
+1
-0
audiotts_play.c
drivers/sensors/audiotts_play.c
+10
-10
go_deploy.c
modules/go_deploy/go_deploy.c
+10
-10
http_config_mqtt.c
modules/http/http_config_mqtt.c
+141
-4
http_config_mqtt.h
modules/http/http_config_mqtt.h
+4
-0
mqtt_infor_handle.c
modules/mqtt/mqtt_infor_handle.c
+21
-17
mqtt_init.c
modules/mqtt/mqtt_init.c
+5
-6
mqtt_verify.c
modules/mqtt/mqtt_verify.c
+4
-6
zlog.conf
zlog.conf
+1
-1
No files found.
app/device_change/device_wifi_change.c
View file @
29e01fc4
...
...
@@ -130,7 +130,7 @@ int connect_wifi(const char* ssid, const char* password) {
char
output
[
512
]
=
{
0
};
size_t
bytes_read
=
fread
(
output
,
1
,
sizeof
(
output
)
-
1
,
fp
);
if
(
bytes_read
==
0
){
my_zlog_
info
(
"success"
);
my_zlog_
debug
(
"success"
);
}
pclose
(
fp
);
...
...
@@ -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
);
if
(
bytes_read
==
0
){
my_zlog_
info
(
"fread success"
);
my_zlog_
debug
(
"fread success"
);
}
pclose
(
fp
);
...
...
app/device_identity/device_fileopen.c
View file @
29e01fc4
...
...
@@ -25,7 +25,10 @@ char *device_inspect() {
else
{
// 尝试读取文件内容
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
);
my_zlog_info
(
"读取到文件内容: %s"
,
s_buffer_device
);
return
s_buffer_device
;
...
...
app/main/wifi_autoconfig.c
View file @
29e01fc4
#include "wifi_autoconfig.h"
#include "main.h"
#include "http_config_mqtt.h"
#include "cJSON.h"
#include <stdio.h>
#include <stdlib.h>
...
...
@@ -7,62 +8,207 @@
#include <unistd.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
[]
=
{
"noCameraDetected.mp3"
,
"connectionFailed.mp3"
,
"connectionSuccessful.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
ensure_audio_dir
(
const
char
*
dir
);
// 播放 ~/audio/ 下的音频文件
// 播放 ~/audio/ 下的音频文件,如果不存在则回退系统音
void
play_audio_file
(
const
char
*
filename
)
{
char
cmd
[
512
];
const
char
*
audio_dir
=
"/home/orangepi/audio"
;
// 固定路径
static
char
s_current_lang
[
8
]
=
AUDIO_LANG_ZH
;
char
filepath
[
256
];
snprintf
(
filepath
,
sizeof
(
filepath
),
"%s/%s"
,
audio_dir
,
filename
);
static
int
is_cn_lang
(
const
char
*
lang
)
{
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. 检查自定义文件是否存在
if
(
access
(
filepath
,
F_OK
)
==
0
)
{
// 文件存在,优先使用 ffplay
if
(
is_command_available
(
"ffplay"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"ffplay -nodisp -autoexit -loglevel quiet
\"
%s
\"
"
,
filepath
);
if
(
system
(
cmd
)
==
0
)
{
my_zlog_debug
(
"ffplay 播放成功"
);
void
audio_init_offline_language
(
void
)
{
FILE
*
fp
=
fopen
(
AUDIO_OFFLINE_LANG_FILE
,
"r"
);
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
;
}
}
// 其次 paplay
if
(
is_command_available
(
"paplay"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"paplay
\"
%s
\"
"
,
filepath
);
if
(
system
(
cmd
)
==
0
)
{
my_zlog_debug
(
"paplay 播放成功"
);
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
(
"自定义音频播放失败,尝试回退系统音..."
);
}
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
{
my_zlog_warn
(
"音频文件 %s 不存在,准备播放系统回退音。"
,
filepath
);
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"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"ffplay -nodisp -autoexit -loglevel quiet
\"
%s
\"
"
,
filepath
);
if
(
system
(
cmd
)
==
0
)
{
my_zlog_debug
(
"ffplay 播放成功: %s"
,
filepath
);
return
1
;
}
}
if
(
is_command_available
(
"paplay"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"paplay
\"
%s
\"
"
,
filepath
);
if
(
system
(
cmd
)
==
0
)
{
my_zlog_debug
(
"paplay 播放成功: %s"
,
filepath
);
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
);
// 2. 文件不存在,或者播放工具缺失 -> 回退到系统默认声音
// 根据文件名映射一下大概的系统音
const
char
*
sys_sound
=
"dialog-information"
;
// 默认
if
(
is_cn_lang
(
s_current_lang
))
{
build_cn_filepath
(
filepath
,
sizeof
(
filepath
),
filename
);
if
(
try_play_filepath
(
filepath
))
{
return
;
}
my_zlog_warn
(
"中文音频不存在: %s,准备播放系统回退音。"
,
filepath
);
}
else
{
build_lang_filepath
(
filepath
,
sizeof
(
filepath
),
s_current_lang
,
filename
);
if
(
try_play_filepath
(
filepath
))
{
return
;
}
build_cn_filepath
(
filepath
,
sizeof
(
filepath
),
filename
);
if
(
try_play_filepath
(
filepath
))
{
my_zlog_debug
(
"外语音频缺失,已回退中文: %s"
,
filepath
);
return
;
}
my_zlog_warn
(
"音频文件不存在 (%s 及中文回退路径),准备播放系统回退音。"
,
s_current_lang
);
}
const
char
*
sys_sound
=
"dialog-information"
;
if
(
strstr
(
filename
,
"noCamera"
))
sys_sound
=
"software-error"
;
else
if
(
strstr
(
filename
,
"Failed"
))
sys_sound
=
"dialog-error"
;
else
if
(
strstr
(
filename
,
"Success"
))
sys_sound
=
"service-login"
;
else
if
(
strstr
(
filename
,
"toScan"
))
sys_sound
=
"dialog-question"
;
// 尝试播放系统音
if
(
is_command_available
(
"paplay"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"paplay /usr/share/sounds/ubuntu/stereo/%s.ogg"
,
sys_sound
);
if
(
system
(
cmd
)
==
0
)
{
...
...
@@ -74,50 +220,95 @@ void play_audio_file(const char *filename) {
my_zlog_debug
(
"系统音 (paplay-freedesktop) 播放成功: %s"
,
sys_sound
);
return
;
}
}
}
if
(
is_command_available
(
"ffplay"
))
{
snprintf
(
cmd
,
sizeof
(
cmd
),
"ffplay -nodisp -autoexit -loglevel quiet /usr/share/sounds/ubuntu/stereo/%s.ogg"
,
sys_sound
);
if
(
system
(
cmd
)
==
0
)
{
my_zlog_debug
(
"系统音 (ffplay) 播放成功: %s"
,
sys_sound
);
return
;
return
;
}
}
my_zlog_error
(
"所有播放尝试均失败!"
);
}
// 下载音频文件
static
void
download_audio_files
()
{
const
char
*
audio_dir
=
"/home/orangepi/audio"
;
// 固定路径
static
void
download_cn_audio
(
const
char
*
filename
,
int
optional
)
{
char
filepath
[
512
];
build_cn_filepath
(
filepath
,
sizeof
(
filepath
),
filename
);
if
(
access
(
filepath
,
F_OK
)
==
0
)
{
return
;
}
// 1. 检查并创建目录
struct
stat
st
=
{
0
};
if
(
stat
(
audio_dir
,
&
st
)
==
-
1
)
{
my_zlog_info
(
"正在创建音频目录: %s"
,
audio_dir
);
mkdir
(
audio_dir
,
0755
);
}
// 2. 检查并下载每个文件
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
char
filepath
[
512
];
snprintf
(
filepath
,
sizeof
(
filepath
),
"%s/%s"
,
audio_dir
,
s_audio_files
[
i
]);
if
(
access
(
filepath
,
F_OK
)
!=
0
)
{
my_zlog_info
(
"正在下载音频文件: %s"
,
s_audio_files
[
i
]);
char
cmd
[
1024
];
// 使用 wget -q (安静模式) -P (指定目录)
snprintf
(
cmd
,
sizeof
(
cmd
),
"wget -q -P
\"
%s
\"
\"
%s%s
\"
"
,
audio_dir
,
AUDIO_BASE_URL
,
s_audio_files
[
i
]);
if
(
system
(
cmd
)
!=
0
)
{
my_zlog_warn
(
"下载失败: %s"
,
s_audio_files
[
i
]);
}
my_zlog_debug
(
"正在下载中文音频: %s"
,
filename
);
char
cmd
[
1024
];
snprintf
(
cmd
,
sizeof
(
cmd
),
"wget -q -P
\"
%s
\"
\"
%s%s
\"
"
,
AUDIO_LOCAL_BASE
,
AUDIO_COS_BASE
,
filename
);
if
(
system
(
cmd
)
!=
0
)
{
if
(
optional
)
{
my_zlog_debug
(
"中文音频暂未上传,跳过: %s"
,
filename
);
}
else
{
// my_zlog_debug("文件已存在: %s", s_audio_files[i]);
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
);
char
filepath
[
512
];
build_lang_filepath
(
filepath
,
sizeof
(
filepath
),
lang
,
filename
);
if
(
access
(
filepath
,
F_OK
)
==
0
)
{
return
;
}
char
cmd
[
1024
];
snprintf
(
cmd
,
sizeof
(
cmd
),
"wget -q -P
\"
%s
\"
\"
%s%s/%s
\"
"
,
lang_dir
,
AUDIO_COS_BASE
,
lang
,
filename
);
if
(
system
(
cmd
)
!=
0
)
{
my_zlog_debug
(
"预留语言音频暂未上传 [%s]: %s"
,
lang
,
filename
);
}
else
{
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
)
{
char
check_cmd
[
256
];
...
...
@@ -170,7 +361,7 @@ static void check_and_install_dependencies() {
my_zlog_error
(
"依赖安装失败,自动配网功能可能无法正常使用。"
);
}
}
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) {
// 自动配网主逻辑
void
check_and_autoconfig_wifi
()
{
my_zlog_info
(
"开始检查网络连接状态..."
);
audio_init_offline_language
();
my_zlog_debug
(
"开始检查网络连接状态..."
);
// 1. 检查并处理依赖
check_and_install_dependencies
();
// 2. 检查网络
if
(
has_internet_connection
())
{
my_zlog_info
(
"网络连接正常,正在检查音频资源..."
);
download_audio_files
();
my_zlog_info
(
"网络连接正常,正在
确定区域语言并
检查音频资源..."
);
prepare_offline_audio_after_network
();
return
;
}
...
...
@@ -313,9 +505,8 @@ void check_and_autoconfig_wifi() {
// 0. 优先检查网络是否已恢复 (比如插上了网线)
if
(
has_internet_connection
())
{
my_zlog_info
(
"检测到网络已恢复,退出扫码模式。"
);
// 补一声连接成功的提示,让用户知道好了
prepare_offline_audio_after_network
();
play_audio_file
(
"connectionSuccessful.mp3"
);
download_audio_files
();
break
;
}
...
...
@@ -376,12 +567,12 @@ void check_and_autoconfig_wifi() {
if
(
cJSON_IsString
(
ssid_item
)
&&
ssid_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"
);
if
(
try_connect_wifi
(
ssid_item
->
valuestring
,
pwd_item
->
valuestring
))
{
my_zlog_info
(
"WiFi 连接成功!"
);
download_audio_files
();
prepare_offline_audio_after_network
();
play_audio_file
(
"connectionSuccessful.mp3"
);
cJSON_Delete
(
json
);
scan_success
=
1
;
...
...
@@ -404,5 +595,5 @@ void check_and_autoconfig_wifi() {
// 清理临时文件
unlink
(
img_path
);
my_zlog_
info
(
"配网流程结束。"
);
my_zlog_
debug
(
"配网流程结束。"
);
}
app/main/wifi_autoconfig.h
View file @
29e01fc4
#ifndef 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
();
// 播放指定名称的音频文件 (位于 ~/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
);
#endif
build/main
View file @
29e01fc4
No preview for this file type
drivers/devicecontrol/pg0403_serial.c
View file @
29e01fc4
...
...
@@ -199,7 +199,7 @@ int pg0403_serial_init_send(){
return
-
1
;
}
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
;
}
...
...
@@ -301,7 +301,7 @@ void pg0403_serial_gpssend_mqtt_json(int id, uint16_t x, uint16_t y) {
return
;
}
my_zlog_
info
(
"[MQTT Payload]: %s"
,
json_str
);
my_zlog_
debug
(
"[MQTT Payload]: %s"
,
json_str
);
char
mqtt_topic_pg
[
256
];
...
...
drivers/selfcontrol/self_devicecontrol.c
View file @
29e01fc4
...
...
@@ -27,7 +27,7 @@ void free_device_tasks_memory() {
pthread_mutex_lock
(
&
s_self_device_control_data_mutex
);
free
(
s_self_device_control_data
);
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
);
}
else
return
;
...
...
@@ -41,7 +41,7 @@ void malloc_device_tasks_memory() {
if
(
s_self_device_control_data
==
NULL
){
s_self_device_control_data
=
(
devicecontroltask_t
*
)
malloc
(
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
);
}
...
...
@@ -115,7 +115,7 @@ static bool s_selfcontrol_task_index=true;
* @brief 自控线程
*/
void
self_device_control_task_function
(){
my_zlog_
info
(
"自控线程池循环开始"
);
my_zlog_
debug
(
"自控线程池循环开始"
);
static
int
s_status
=
0
;
while
(
s_selfcontrol_task_index
){
if
(
s_self_control_switch
==
true
){
...
...
@@ -130,7 +130,7 @@ void self_device_control_task_function(){
}
}
free_device_tasks_memory
();
my_zlog_
info
(
"自控线程池循环终止"
);
my_zlog_
debug
(
"自控线程池循环终止"
);
return
;
}
...
...
@@ -141,7 +141,7 @@ void self_device_pthrpoll_task_init(){
s_self_devicecontrol_task
=
thread_pool_init
(
1
,
1
);
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(){
*/
void
self_control_thread_close
(){
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
;
thread_pool_destroy
(
s_self_devicecontrol_task
);
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(){
// 将cJSON对象转换为字符串
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
);
...
...
@@ -222,7 +222,7 @@ void send_self_contorl_date_mqtt(){
// 将cJSON对象转换为字符串
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
);
...
...
drivers/sensors/audioplay.c
View file @
29e01fc4
...
...
@@ -4,12 +4,129 @@
#include "mqtt_init.h"
#include "http_config_mqtt.h"
#include "audiotts_play.h"
#include "wifi_autoconfig.h"
#include <strings.h>
#include <unistd.h>
static
int
s_audio_status
=
7
;
static
char
s_urlbuf
[
512
];
static
char
s_keybuf
[
256
];
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
)
{
if
(
v
<
0
.
0
)
{
return
0
.
0
;
...
...
@@ -103,7 +220,7 @@ void audioplay_cycle(){
s_audio_volume
,
urlmoddle
);
my_zlog_debug
(
"播放地址: %s"
,
s_urlbuf
);
my_zlog_
info
(
"执行播放命令: %s"
,
command
);
my_zlog_
debug
(
"执行播放命令: %s"
,
command
);
ret
=
system
(
command
);
if
(
ret
!=
0
)
{
my_zlog_error
(
"播放失败"
);
...
...
@@ -120,6 +237,19 @@ void audioplay_cycle(){
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
();
delay_ms
(
100
);
...
...
@@ -218,7 +348,7 @@ int audio_config_init() {
// 检查是否包含完整配置块
if
(
strstr
(
buffer
,
s_yundea_block
)
!=
NULL
)
{
my_zlog_
info
(
"配置文件中已包含指定配置,跳过添加。"
);
my_zlog_
debug
(
"配置文件中已包含指定配置,跳过添加。"
);
free
(
buffer
);
return
0
;
}
...
...
drivers/sensors/audioplay.h
View file @
29e01fc4
...
...
@@ -3,6 +3,7 @@
#include <cjson/cJSON.h>
void
audioplay_mqtt_receive
(
cJSON
*
body
);
//接收音频mqtt播放函数
void
audioplay_local_mqtt_receive
(
cJSON
*
body
);
// 2017 有人驾驶本地音频
void
audioplay_cycle
();
//音频播放线程中函数
int
audio_wheat_init
();
...
...
drivers/sensors/audiotts_play.c
View file @
29e01fc4
...
...
@@ -108,7 +108,7 @@ static int save_audio_file(const void *data, size_t len, const char *filepath) {
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
;
}
...
...
@@ -170,7 +170,7 @@ int audio_tts(const char *text) {
// 2. 生成唯一 reqid(每次调用必须不同)
char
reqid
[
33
]
=
{
0
};
generate_uuid
(
reqid
,
sizeof
(
reqid
));
my_zlog_
info
(
"Generated ReqID: %s"
,
reqid
);
my_zlog_
debug
(
"Generated ReqID: %s"
,
reqid
);
// 3. 构建请求 JSON(严格遵循接口参数格式)
cJSON
*
root
=
cJSON_CreateObject
();
...
...
@@ -220,7 +220,7 @@ int audio_tts(const char *text) {
free
(
uid
);
return
1
;
}
my_zlog_
info
(
"Request Payload: %s"
,
payload
);
my_zlog_
debug
(
"Request Payload: %s"
,
payload
);
// 4. 初始化 curl 并配置 HTTP 请求
curl_global_init
(
CURL_GLOBAL_DEFAULT
);
...
...
@@ -259,7 +259,7 @@ int audio_tts(const char *text) {
curl_easy_setopt
(
curl
,
CURLOPT_CONNECTTIMEOUT
,
10L
);
// 连接超时 10 秒
// 5. 执行 HTTP 请求
my_zlog_
info
(
"Sending request to %s..."
,
endpoint
);
my_zlog_
debug
(
"Sending request to %s..."
,
endpoint
);
CURLcode
res
=
curl_easy_perform
(
curl
);
if
(
res
!=
CURLE_OK
)
{
my_zlog_error
(
"curl_easy_perform failed: %s"
,
curl_easy_strerror
(
res
));
...
...
@@ -272,7 +272,7 @@ int audio_tts(const char *text) {
}
// 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
)
{
my_zlog_error
(
"Empty response from server"
);
free
(
uid
);
...
...
@@ -317,7 +317,7 @@ int audio_tts(const char *text) {
curl_global_cleanup
();
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 音频字符串(接口实际返回格式)
cJSON
*
audio_base64
=
cJSON_GetObjectItem
(
response_json
,
"data"
);
...
...
@@ -332,7 +332,7 @@ int audio_tts(const char *text) {
curl_global_cleanup
();
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 解码音频数据
size_t
audio_len
=
0
;
...
...
@@ -348,7 +348,7 @@ int audio_tts(const char *text) {
curl_global_cleanup
();
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
)
{
//保存文件
my_zlog_error
(
"save_audio_file fail"
);
...
...
@@ -440,7 +440,7 @@ int mqtt_audio_tts(cJSON *body){
cJSON
*
date
=
cJSON_GetObjectItem
(
body
,
"date"
);
if
(
date
!=
NULL
){
get_audio_text_tts
(
date
->
valuestring
,
0
);
my_zlog_
info
(
"text:%s"
,
date
->
valuestring
);
my_zlog_
debug
(
"text:%s"
,
date
->
valuestring
);
}
else
{
return
1
;
}
...
...
@@ -503,7 +503,7 @@ void video_tts_play() {
int
status
;
waitpid
(
pid
,
&
status
,
WNOHANG
);
// 不阻塞的等待
my_zlog_
info
(
"启动独立播放进程 PID: %d"
,
pid
);
my_zlog_
debug
(
"启动独立播放进程 PID: %d"
,
pid
);
s_audio_tts_index
=
0
;
}
else
{
...
...
modules/go_deploy/go_deploy.c
View file @
29e01fc4
...
...
@@ -145,7 +145,7 @@ int go_deploy_check_and_update(void) {
char
target_dir
[
256
];
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
};
...
...
@@ -153,7 +153,7 @@ int go_deploy_check_and_update(void) {
if
(
mkdir
(
target_dir
,
0777
)
!=
0
)
{
my_zlog_error
(
"Failed to create directory: %s"
,
target_dir
);
}
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) {
char
target_file_path
[
512
];
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
curl_global_init
(
CURL_GLOBAL_ALL
);
...
...
@@ -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), "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_WRITEFUNCTION
,
WriteMemoryCallback
);
...
...
@@ -190,7 +190,7 @@ int go_deploy_check_and_update(void) {
curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYHOST
,
0L
);
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
)
{
my_zlog_error
(
"curl_easy_perform() failed: %s"
,
curl_easy_strerror
(
res
));
...
...
@@ -207,7 +207,7 @@ int go_deploy_check_and_update(void) {
cJSON
*
data
=
cJSON_GetObjectItem
(
root
,
"data"
);
char
*
data_str
=
cJSON_Print
(
data
);
if
(
data_str
)
{
my_zlog_
info
(
"Got config data: %s"
,
data_str
);
my_zlog_
debug
(
"Got config data: %s"
,
data_str
);
free
(
data_str
);
}
if
(
!
data
)
{
...
...
@@ -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
);
need_download
=
1
;
}
else
{
my_zlog_
info
(
"File hash verified. No update needed."
);
my_zlog_
debug
(
"File hash verified. No update needed."
);
}
}
else
{
my_zlog_error
(
"Failed to calculate local hash"
);
...
...
@@ -301,7 +301,7 @@ int go_deploy_check_and_update(void) {
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
)
{
my_zlog_info
(
"video_proxy.7z not found, need download."
);
need_download_7z
=
1
;
...
...
@@ -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
);
need_download_7z
=
1
;
}
else
{
my_zlog_
info
(
"7z Hash verified."
);
my_zlog_
debug
(
"7z Hash verified."
);
}
}
else
{
my_zlog_error
(
"Failed to calculate 7z local hash"
);
...
...
@@ -349,7 +349,7 @@ int go_deploy_check_and_update(void) {
char
cmd
[
1024
];
// 使用密码 fcrs2025606 解压, -y 自动覆盖, -o 指定输出目录
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
);
if
(
extract_ret
==
0
)
{
...
...
modules/http/http_config_mqtt.c
View file @
29e01fc4
...
...
@@ -2,6 +2,8 @@
#include "http_config_mqtt.h"
#include "common.h"
#include "http_request.h"
#include "wifi_autoconfig.h"
#include <strings.h>
static
DEVICE_MQTTCONFIG
s_mqtt_cam_config
;
DEVICE_MQTTCONFIG
*
g_mqtt_cam_config_t
=
&
s_mqtt_cam_config
;
...
...
@@ -16,6 +18,138 @@ void default_device_mqtt_cam(){
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
)
{
// 解析 JSON
cJSON
*
root
=
cJSON_Parse
(
json_str
);
...
...
@@ -46,14 +180,14 @@ int parse_device_config(const char *json_str) {
// 3. 提取 mqtt 服务器列表
cJSON
*
mqtt
=
cJSON_GetObjectItemCaseSensitive
(
data
,
"mqtt"
);
if
(
cJSON_IsArray
(
mqtt
))
{
my_zlog_
info
(
"MQTT 服务器:"
);
my_zlog_
debug
(
"MQTT 服务器:"
);
cJSON
*
item
;
int
i
=
0
;
cJSON_ArrayForEach
(
item
,
mqtt
)
{
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
);
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
;
}
}
...
...
@@ -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
);
g_mqtt_cam_config_t
->
videourl
[
sizeof
(
g_mqtt_cam_config_t
->
videourl
)
-
1
]
=
'\0'
;
}
parse_moreinfo_language
(
data
);
}
// 释放内存
cJSON_Delete
(
root
);
return
0
;
}
// 拉取并解析 JSON 数据的函数
...
...
@@ -94,7 +231,7 @@ int deviceconfig_mqtt_video_init() {
// 构造请求 URL
char
url
[
512
];
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_easy_setopt
(
curl
,
CURLOPT_URL
,
url
);
...
...
@@ -137,7 +274,7 @@ int http_mqtt_video_init(){
my_zlog_info
(
"http_mqtt_video_init success"
);
return
0
;
}
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"
);
...
...
modules/http/http_config_mqtt.h
View file @
29e01fc4
...
...
@@ -16,4 +16,7 @@ extern DEVICE_MQTTCONFIG *g_mqtt_cam_config_t;
/*mqtt服务器和视频流地址初始化*/
int
http_mqtt_video_init
();
// 有网时拉取 getConfig.moreInfo.language(CN/EN),在下载离线音频前调用
int
device_fetch_region_language
(
void
);
#endif
\ No newline at end of file
modules/mqtt/mqtt_infor_handle.c
View file @
29e01fc4
...
...
@@ -344,7 +344,7 @@ int device_message_receive(cJSON *json)
if
(
s_message_type
==
2013
)
{
if
(
message2013_recverigy_open
(
body
)
==
0
)
{
my_zlog_
info
(
"进入是否需要验证"
);
my_zlog_
debug
(
"进入是否需要验证"
);
return
0
;
}
return
1
;
...
...
@@ -374,7 +374,7 @@ int device_message_receive(cJSON *json)
case
5
:
audio_wheat_init
();
audio_speaker_init
();
my_zlog_
info
(
"执行麦和喇叭命令"
);
my_zlog_
debug
(
"执行麦和喇叭命令"
);
break
;
case
6
:
message_6_steering_judyverify
(
body
);
...
...
@@ -386,35 +386,35 @@ int device_message_receive(cJSON *json)
break
;
case
2001
:
audioplay_mqtt_receive
(
body
);
my_zlog_
info
(
"进入音频播放"
);
my_zlog_
debug
(
"进入音频播放"
);
break
;
case
2002
:
device_mqttchange_name
(
body
);
my_zlog_
info
(
"进入修改设备号"
);
my_zlog_
debug
(
"进入修改设备号"
);
break
;
case
2003
:
scan_wifi_json
();
my_zlog_
info
(
"进入查询WiFi"
);
my_zlog_
debug
(
"进入查询WiFi"
);
break
;
case
2004
:
// wifi_change_recmqtt(body);
my_zlog_
info
(
"进入修改WiFi"
);
my_zlog_
debug
(
"进入修改WiFi"
);
break
;
case
2006
:
message2006_verify
(
body
);
my_zlog_
info
(
"进入消息为2006验证"
);
my_zlog_
debug
(
"进入消息为2006验证"
);
break
;
case
2007
:
device_send_saved_wifi
();
my_zlog_
info
(
"查询已保存wifi和现在已连接WiFi"
);
my_zlog_
debug
(
"查询已保存wifi和现在已连接WiFi"
);
break
;
case
2008
:
device_wifi_rec_sava
(
body
);
my_zlog_
info
(
"保存wifi"
);
my_zlog_
debug
(
"保存wifi"
);
break
;
case
2009
:
device_wifi_rec_delete
(
body
);
my_zlog_
info
(
"删除已保存wifi"
);
my_zlog_
debug
(
"删除已保存wifi"
);
break
;
case
2011
:
int
res
=
system
(
"sudo reboot"
);
// 重启香橙派
...
...
@@ -423,27 +423,31 @@ int device_message_receive(cJSON *json)
break
;
case
2012
:
refresh_cam
();
my_zlog_
info
(
"刷新成功"
);
my_zlog_
debug
(
"刷新成功"
);
break
;
case
2016
:
mqtt_verify_data_clear
(
body
);
my_zlog_info
(
"清除验证数据"
);
break
;
my_zlog_debug
(
"清除验证数据"
);
break
;
case
2017
:
audioplay_local_mqtt_receive
(
body
);
my_zlog_debug
(
"有人驾驶本地音频"
);
break
;
case
2025
:
receive_self_contorl_mqtt
(
body
);
my_zlog_
info
(
"device self comtrol"
);
my_zlog_
debug
(
"device self comtrol"
);
break
;
case
2026
:
receive_self_contorl_date_mqtt
(
body
);
my_zlog_
info
(
"device self comtrol date save"
);
my_zlog_
debug
(
"device self comtrol date save"
);
break
;
case
2027
:
mqtt_audio_tts
(
body
);
my_zlog_
info
(
"device audio_tts"
);
my_zlog_
debug
(
"device audio_tts"
);
break
;
case
2028
:
tailscale_control
(
body
);
my_zlog_
info
(
"tailscale control"
);
my_zlog_
debug
(
"tailscale control"
);
break
;
default:
break
;
...
...
modules/mqtt/mqtt_init.c
View file @
29e01fc4
...
...
@@ -136,8 +136,7 @@ void on_connect(struct mosquitto *mosq, void *obj, int rc) {
}
if
(
rc
==
0
)
{
my_zlog_info
(
"Connected to broker"
);
my_zlog_info
(
"[Connected] %s:%d (%s)"
,
my_zlog_info
(
"MQTT已连接 %s:%d (%s)"
,
client_t
->
host
,
client_t
->
port
,
client_t
->
client_id
);
client_t
->
reconnect_attempts
=
0
;
client_t
->
permanently_failed
=
false
;
...
...
@@ -182,7 +181,7 @@ void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_messag
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
,
message
->
topic
,
(
char
*
)
message
->
payload
);
...
...
@@ -297,7 +296,7 @@ int add_mqtt_create(const char *host, int port, int clients_idx) {
return
-
1
;
}
my_zlog_
info
(
"成功为主机 %s 添加 MQTT 客户端"
,
host
);
my_zlog_
debug
(
"成功为主机 %s 添加 MQTT 客户端"
,
host
);
return
0
;
// 成功
}
...
...
@@ -318,12 +317,12 @@ void mqtt_clean(){
mosquitto_lib_cleanup
();
s_mosquitto_lib_inited
=
false
;
}
my_zlog_
info
(
"清理成功
"
);
my_zlog_
debug
(
"MQTT 清理完成
"
);
}
int
mqtt_cycle
()
{
//非阻塞型
my_zlog_
info
(
"MQTT 异步监控线程启动"
);
my_zlog_
debug
(
"MQTT 异步监控线程启动"
);
int
check_interval
=
30
;
// 30秒检查一次,减少日志频率
...
...
modules/mqtt/mqtt_verify.c
View file @
29e01fc4
...
...
@@ -100,8 +100,7 @@ int receive_jwt(cJSON *body) {
cJSON
*
json_token
=
cJSON_GetObjectItem
(
body
,
"token"
);
cJSON
*
json_token_time
=
cJSON_GetObjectItem
(
body
,
"token_time"
);
if
(
json_token
==
NULL
||
json_token_time
==
NULL
)
{
my_zlog_warn
(
"JWT验证失败: token或token_time字段缺失, token=%s"
,
(
json_token
&&
cJSON_IsString
(
json_token
)
&&
json_token
->
valuestring
)
?
json_token
->
valuestring
:
"<null>"
);
my_zlog_warn
(
"JWT验证失败: token或token_time字段缺失"
);
g_verify_index
=
1
;
return
1
;
}
...
...
@@ -111,8 +110,7 @@ int receive_jwt(cJSON *body) {
/* 空字符串视为无效,不发给后端 */
if
(
token
==
NULL
||
token
[
0
]
==
'\0'
||
token_time
==
NULL
||
token_time
[
0
]
==
'\0'
)
{
my_zlog_error
(
"JWT验证失败: token或token_time为空, token=%s"
,
(
token
&&
token
[
0
]
!=
'\0'
)
?
token
:
"<empty>"
);
my_zlog_error
(
"JWT验证失败: token或token_time为空"
);
g_verify_index
=
1
;
return
1
;
}
...
...
@@ -429,7 +427,7 @@ void mqtt_verify_data_clear(cJSON *body){
const
char
*
status
=
verify_clear_item
->
valuestring
;
if
(
strcmp
(
status
,
"clear"
)
==
0
)
{
my_zlog_
info
(
"状态为 clear,执行清理操作"
);
my_zlog_
debug
(
"状态为 clear,执行清理操作"
);
pthread_mutex_lock
(
&
g_verify_mutex
);
g_verify_count
=
12001
;
pthread_mutex_unlock
(
&
g_verify_mutex
);
...
...
@@ -437,7 +435,7 @@ void mqtt_verify_data_clear(cJSON *body){
mqtt_verify_clear_send
(
"1"
);
}
else
{
my_zlog_
info
(
"状态为: %s"
,
status
);
my_zlog_
debug
(
"状态为: %s"
,
status
);
mqtt_verify_clear_send
(
"0"
);
}
}
else
{
...
...
zlog.conf
View file @
29e01fc4
...
...
@@ -9,4 +9,4 @@ file perms = 600
millisecond
=
"%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n"
[
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment