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
dced7c62
Commit
dced7c62
authored
Jul 17, 2026
by
957dd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化了播报与游览器之间的竞争问题
parent
055aa314
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
520 additions
and
90 deletions
+520
-90
main
build/main
+0
-0
device_init.c
drivers/gpio/device_init.c
+5
-5
device_init.c.bak-boolcase-20260716-063617
drivers/gpio/device_init.c.bak-boolcase-20260716-063617
+278
-0
audioplay.c
drivers/sensors/audioplay.c
+84
-21
audioplay.c.bak-audio-preempt-20260717
drivers/sensors/audioplay.c.bak-audio-preempt-20260717
+0
-0
audioplay.h
drivers/sensors/audioplay.h
+7
-0
audioplay.h.bak-audio-preempt-20260717
drivers/sensors/audioplay.h.bak-audio-preempt-20260717
+16
-0
audiotts_play.c
drivers/sensors/audiotts_play.c
+6
-37
audiotts_play.c.bak-audio-preempt-20260717
drivers/sensors/audiotts_play.c.bak-audio-preempt-20260717
+0
-0
http_config_mqtt.h
modules/http/http_config_mqtt.h
+1
-1
mqtt_infor_handle.c
modules/mqtt/mqtt_infor_handle.c
+5
-5
mqtt_verify.c
modules/mqtt/mqtt_verify.c
+11
-11
rtc_client.c
modules/webrtcpush/rtc_client.c
+53
-4
webrtcpush_config.h
modules/webrtcpush/webrtcpush_config.h
+5
-3
ws_signaling.c
modules/webrtcpush/ws_signaling.c
+48
-2
zlog.conf
zlog.conf
+1
-1
No files found.
build/main
View file @
dced7c62
No preview for this file type
drivers/gpio/device_init.c
View file @
dced7c62
...
...
@@ -236,9 +236,9 @@ static const deviceconfig_t s_device_configs[] = {
bool
get_array_length
(
const
int
*
arr
)
{
if
(
arr
[
0
]
!=
-
1
)
{
// 遇到-1停止计数
return
TRUE
;
return
true
;
}
return
FALSE
;
return
false
;
}
void
device_init
(
int
device_id
)
{
...
...
@@ -258,9 +258,9 @@ void device_init(int device_id) {
}
// 执行初始化流程
if
(
get_array_length
(
config
->
gpio_pins
)
==
TRUE
)
init_gpiowpi
(
config
->
gpio_pins
);
// GPIO初始化
if
(
get_array_length
(
config
->
gpio_pwms
)
==
TRUE
)
init_gpiopwm
(
config
->
gpio_pwms
);
// GPIOsoft_pwm初始化
if
(
get_array_length
(
config
->
gpio_inputs
)
==
TRUE
)
init_gpio_input
(
config
->
gpio_inputs
);
if
(
get_array_length
(
config
->
gpio_pins
))
init_gpiowpi
(
config
->
gpio_pins
);
// GPIO初始化
if
(
get_array_length
(
config
->
gpio_pwms
))
init_gpiopwm
(
config
->
gpio_pwms
);
// GPIOsoft_pwm初始化
if
(
get_array_length
(
config
->
gpio_inputs
))
init_gpio_input
(
config
->
gpio_inputs
);
g_device_type
=
config
->
emergency_code
;
config
->
device_pwm_init
();
// PWM初始化
config
->
device_control_stop
();
// 速度控制初始化
...
...
drivers/gpio/device_init.c.bak-boolcase-20260716-063617
0 → 100644
View file @
dced7c62
#include "device_init.h"
#include "devcontrol_common.h"
#include "common.h"
#include "gpio_init.h"
#include "car0107_idle.h"
int g_device_delay_back_count =0;//设备计时,比如坦克打击倒退逻辑
int g_device_type =0; //设备详细类型,让其他地方判断,比如tank0202、car0101
static const deviceconfig_t s_device_configs[] = {
// car0101配置
{
.device_id = DEVICE_CAR0101,
.device_name = "car0101",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26, 27, -1},
.gpio_pwms = {-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0101_middle_pwm,
.emergency_code = 101
},
// car0102配置
{
.device_id = DEVICE_CAR0102,
.device_name = "car0102",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26, 27, -1},
.gpio_pwms = {5, 7, -1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0102_speed_stop,
.emergency_code = 102
},
// car0103配置(根据您的需求补充)
{
.device_id = DEVICE_CAR0103,
.device_name = "car0103",
.gpio_pins = {5, 6, 7, 9 , 10, 16, 20, 22, 23, 24, 25, 26, 27,-1},/* 补充GPIO引脚 */
.gpio_pwms = {-1},
.gpio_inputs={11,12,14,17,18,20,-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0103_middle,/* 补充速度控制函数 */
.emergency_code = 103
},
// car0104配置(根据您的需求补充)
{
.device_id = DEVICE_CAR0104,
.device_name = "car0104",
.gpio_pins = {5, 6, 7, 9,10, 16, 20, 22, 23, 24, 25, 26, 27,-1},/* 补充GPIO引脚 */
.gpio_pwms = {-1},
.gpio_inputs={11,12,14,20,-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0104_stop,/* 补充速度控制函数 */
.emergency_code = 104
},
// car0105配置(根据您的需求补充)
{
.device_id = DEVICE_CAR0105,
.device_name = "car0105",
.gpio_pins = {5, 6, 7, 9,10, 16, 20, 22, 23, 24, 25, 26, -1},/* 补充GPIO引脚 */
.gpio_pwms = {27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0101_middle_pwm,/* 补充速度控制函数 */
.emergency_code = 105
},
// car0106 F1赛车(双电机大板): 软PWM 5/7/24/26 对应前后左右
{
.device_id = DEVICE_CAR0106,
.device_name = "car0106",
.gpio_pins = {-1},
.gpio_pwms = {5, 7, 24, 26, -1},
.gpio_inputs={-1},
.device_pwm_init = car0106_pwm_init_empty,
.device_control_stop = car0106_stop,
.emergency_code = 106
},
// car0107 大众POLO R(与0101相同硬件,前后方向相反)
{
.device_id = DEVICE_CAR0107,
.device_name = "car0107",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26, 27, -1},
.gpio_pwms = {-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0107_middle_pwm,
.emergency_code = 107
},
// tank0202配置(根据您的需求补充)
{
.device_id = DEVICE_TANK0202,
.device_name = "tank0202",
.gpio_pins = {6, 16, 20, 22,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24,26, 27,-1},
.gpio_inputs={12,-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = tank0202_middle,/* 补充速度控制函数 */
.emergency_code = 202
},
{
.device_id = DEVICE_TANK0203,
.device_name = "tank0203",
.gpio_pins = {6, 16, 20, 22,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24, 26, 27,-1},
.gpio_inputs={12,-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = tank0203_middle,/* 补充速度控制函数 */
.emergency_code = 203
},
{
.device_id = DEVICE_TANK0204,
.device_name = "tank0204",
.gpio_pins = {6, 16, 20, 22,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24, 26, 27,-1},
.gpio_inputs={12,-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = tank0204_stop,/* 补充速度控制函数 */
.emergency_code = 204
},
{
.device_id = DEVICE_TANK0206,
.device_name = "tank0206",
.gpio_pins = {6, 16, 20, 22, 23,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24,26, 27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = tank0206_middle,/* 补充速度控制函数 */
.emergency_code = 206
},
{
.device_id = DEVICE_TANK0207,
.device_name = "tank0207",
.gpio_pins = {6, 16, 20, 22, 23,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24,26, 27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = tank0207_middle,/* 补充速度控制函数 */
.emergency_code = 207
},
{
.device_id = DEVICE_SHIP0301,
.device_name = "ship0301",
.gpio_pins = {6, 16, 20, 22, 23,-1},/* 补充GPIO引脚 */
.gpio_pwms = {5 , 7 ,24,26, 27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = ship0301_stop,/* 补充速度控制函数 */
.emergency_code = 301
},
{
.device_id = DEVICE_SHIP0302,
.device_name = "ship0302",
.gpio_pins = {6, 16, 20, 22, 23,-1},
.gpio_pwms = {5 , 7 ,24,26, 27,-1},
.gpio_inputs={-1},
.device_pwm_init = device_ship0302_init,
.device_control_stop = ship0302_stop,
.emergency_code = 302
},
{
.device_id = DEVICE_PAO_PTZ0401,
.device_name = "ptz0401",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26,27,-1},/* 补充GPIO引脚 */
.gpio_pwms = { -1},
.gpio_inputs={-1},
.device_pwm_init = ptz_driver_pwm_hz,
.device_control_stop = ptz_driver_init,
.emergency_code = 401
},
{
.device_id = DEVICE_PAO_PTZ0404,
.device_name = "ptz0404",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26,27,-1},/* 补充GPIO引脚 */
.gpio_pwms = { -1},
.gpio_inputs={-1},
.device_pwm_init = ptz_driver_pwm_hz,
.device_control_stop = ptz_driver_init,
.emergency_code = 404
},
{
.device_id = DEVICE_PAO_PTZ0405,
.device_name = "ptz0405",
.gpio_pins = {5, 7, 10, 16, 20, 22, 23, 24, 25, 26,27,-1},
.gpio_pwms = {-1},
.gpio_inputs={-1},
.device_pwm_init = ptz_driver_pwm_hz,
.device_control_stop = ptz_driver_init,
.emergency_code = 405
},
{
.device_id = DEVICE_PAO_PTZ0406,
.device_name = "ptz0406",
.gpio_pins = {5, 7, 10, 16, 20, 22, 23, 24, 25, 26,27,-1},
.gpio_pwms = {-1},
.gpio_inputs={-1},
.device_pwm_init = ptz_driver_pwm_hz,
.device_control_stop = ptz_driver_init,
.emergency_code = 406
},
{
.device_id = DEVICE_PG_GPS0403,
.device_name = "gps0403",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26,-1},/* 补充GPIO引脚 */
.gpio_pwms = { 27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0101_middle_pwm,/* 补充速度控制函数 */
.emergency_code = 403
},
{
.device_id = DEVICE_ROBOT_DOG0501,
.device_name = "dog0501",
.gpio_pins = {6, 10, 16, 20, 22, 23, 25,-1},/* 补充GPIO引脚 */
.gpio_pwms = { 5, 7,24, 26,27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = car0101_middle_pwm,/* 补充速度控制函数 */
.emergency_code = 501
},
{
.device_id = DEVICE_ROBOT_ARM0502,
.device_name = "arm0502",
.gpio_pins = {5, 6, 7, 10, 16, 20, 22, 23, 24, 25, 26,-1},
.gpio_pwms = { 27,-1},
.gpio_inputs={-1},
.device_pwm_init = physics_pwm_init,
.device_control_stop = arm0502_control_stop_init,
.emergency_code = 502
},
// 结束标记
{ .device_id = -1 }
};
bool get_array_length(const int* arr) {
if(arr[0] != -1) { // 遇到-1停止计数
return TRUE;
}
return FALSE;
}
void device_init(int device_id) {
const deviceconfig_t *config = NULL;
// 查找设备配置
for(int i = 0; s_device_configs[i].device_id != -1; i++) {
if(s_device_configs[i].device_id == device_id) {
config = &s_device_configs[i];
break;
}
}
if(!config) {
my_zlog_error("Error: Device ID %d not found!", device_id);
return;
}
// 执行初始化流程
if(get_array_length(config->gpio_pins)==TRUE)init_gpiowpi(config->gpio_pins); // GPIO初始化
if(get_array_length(config->gpio_pwms)==TRUE)init_gpiopwm(config->gpio_pwms); // GPIOsoft_pwm初始化
if(get_array_length(config->gpio_inputs)==TRUE) init_gpio_input(config->gpio_inputs);
g_device_type =config->emergency_code;
config->device_pwm_init(); // PWM初始化
config->device_control_stop(); // 速度控制初始化
if (device_id == DEVICE_CAR0102) {
car0102_pin27_startup(device_id);
}
if (device_id == DEVICE_CAR0107) {
car0107_idle_startup(device_id);
}
my_zlog_debug("%s initialized successfully!", config->device_name);
}
\ No newline at end of file
drivers/sensors/audioplay.c
View file @
dced7c62
...
...
@@ -14,7 +14,7 @@
#define AUDIO_USB_ALSA_DEVICE "hw:2,0"
#define AUDIO_LOCAL_ALSA_DEVICE "plughw:2,0"
#define AUDIO_
LOCAL_PLAY_TIMEOUT_SEC 8
#define AUDIO_
ANNOUNCEMENT_TIMEOUT_SEC 20
static
int
s_audio_status
=
7
;
static
char
s_urlbuf
[
512
];
...
...
@@ -189,36 +189,104 @@ static void shell_single_quote(char *out, size_t size, const char *in) {
out
[
pos
]
=
'\0'
;
}
static
int
play_local_audio_file
(
const
char
*
filepath
)
{
static
int
pulse_suspend_default_output
(
int
suspend
)
{
const
char
*
command
=
suspend
?
"pactl suspend-sink @DEFAULT_SINK@ 1 >/dev/null 2>&1"
:
"pactl suspend-sink @DEFAULT_SINK@ 0 >/dev/null 2>&1"
;
int
exit_code
=
audio_system_exit_code
(
system
(
command
));
if
(
exit_code
!=
0
)
{
my_zlog_warn
(
"%s浏览器音频输出失败 exit=%d"
,
suspend
?
"暂停"
:
"恢复"
,
exit_code
);
}
return
exit_code
;
}
int
audioplay_file_with_browser_preempt
(
const
char
*
filepath
,
double
volume
)
{
char
quoted_path
[
1024
];
char
command
[
2048
];
int
ret
;
int
exit_code
;
int
pulse_suspended
;
if
(
filepath
==
NULL
||
filepath
[
0
]
==
'\0'
)
{
return
-
1
;
}
shell_single_quote
(
quoted_path
,
sizeof
(
quoted_path
),
filepath
);
volume
=
audioplay_volume_clamp
(
volume
);
/*
排队等待USB声卡: 如果audio_sink正在播放手机音频, 等它释放
*/
/*
先和项目内 DataChannel/本地音频排队,再让浏览器临时释放 USB 声卡。
*/
audio_sink_lock_alsa
();
pulse_suspended
=
(
pulse_suspend_default_output
(
1
)
==
0
);
if
(
pulse_suspended
)
{
snprintf
(
command
,
sizeof
(
command
),
/* timeout 使用 KILL,保证卡死的播放进程到 20 秒时立即释放 ALSA。 */
"timeout -s KILL %ds gst-launch-1.0 -q filesrc location=%s ! mpegaudioparse ! mpg123audiodec ! audioconvert ! volume volume=%.3f ! audioresample ! audio/x-raw,channels=2 ! alsasink device=%s sync=true >/dev/null 2>&1"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
quoted_path
,
volume
,
AUDIO_LOCAL_ALSA_DEVICE
);
}
else
{
/* PulseAudio 无法暂停时走其默认输出,避免直接打开同一声卡导致 device busy。 */
snprintf
(
command
,
sizeof
(
command
),
/* sync=true 防止 EOS 提前关 ALSA 丢尾部(只播前半段); channels=2 上混规避 USB 声卡单声道 ring_buffer CRITICAL */
"timeout %ds gst-launch-1.0 -q filesrc location=%s ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! audio/x-raw,channels=2 ! alsasink device=%s sync=true >/dev/null 2>&1"
,
AUDIO_LOCAL_PLAY_TIMEOUT_SEC
,
quoted_path
,
AUDIO_LOCAL_ALSA_DEVICE
);
"timeout -s KILL %ds ffplay -nodisp -autoexit -loglevel warning -af
\"
volume=%.3f
\"
%s >/dev/null 2>&1"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
volume
,
quoted_path
);
}
ret
=
system
(
command
);
exit_code
=
audio_system_exit_code
(
ret
);
if
(
exit_code
!=
0
)
{
my_zlog_warn
(
"本地音频 GStreamer 播放失败 exit=%d,尝试 ffplay: %s"
,
exit_code
,
filepath
);
/* 无论正常结束、播放失败还是 timeout,退出前都恢复浏览器音频。 */
if
(
pulse_suspended
)
{
pulse_suspend_default_output
(
0
);
}
audio_sink_unlock_alsa
();
if
(
exit_code
==
137
)
{
my_zlog_warn
(
"播报超过 %d 秒,已强制停止并释放声卡: %s"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
filepath
);
}
return
exit_code
;
}
int
audioplay_url_with_browser_preempt
(
const
char
*
url
,
double
volume
)
{
char
quoted_url
[
1024
];
char
command
[
2048
];
int
exit_code
;
int
pulse_suspended
;
if
(
url
==
NULL
||
url
[
0
]
==
'\0'
)
{
return
-
1
;
}
shell_single_quote
(
quoted_url
,
sizeof
(
quoted_url
),
url
);
volume
=
audioplay_volume_clamp
(
volume
);
audio_sink_lock_alsa
();
pulse_suspended
=
(
pulse_suspend_default_output
(
1
)
==
0
);
if
(
pulse_suspended
)
{
snprintf
(
command
,
sizeof
(
command
),
"timeout %ds ffplay -nodisp -autoexit -loglevel warning %s"
,
AUDIO_LOCAL_PLAY_TIMEOUT_SEC
,
quoted_path
);
ret
=
system
(
command
);
exit_code
=
audio_system_exit_code
(
ret
);
"timeout -s KILL %ds ffmpeg -nostdin -hide_banner -loglevel warning -i %s -af
\"
volume=%.3f
\"
-f alsa %s >/dev/null 2>&1"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
quoted_url
,
volume
,
AUDIO_LOCAL_ALSA_DEVICE
);
}
else
{
snprintf
(
command
,
sizeof
(
command
),
"timeout -s KILL %ds ffplay -nodisp -autoexit -loglevel warning -af
\"
volume=%.3f
\"
%s >/dev/null 2>&1"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
volume
,
quoted_url
);
}
exit_code
=
audio_system_exit_code
(
system
(
command
));
if
(
pulse_suspended
)
{
pulse_suspend_default_output
(
0
);
}
audio_sink_unlock_alsa
();
if
(
exit_code
==
137
)
{
my_zlog_warn
(
"网络播报超过 %d 秒,已强制停止并释放声卡: %s"
,
AUDIO_ANNOUNCEMENT_TIMEOUT_SEC
,
url
);
}
return
exit_code
;
}
...
...
@@ -291,26 +359,21 @@ void audioplay_send_mqtt() {
//音频播放
void
audioplay_cycle
(){
char
command
[
2048
];
int
ret
;
while
(
1
){
if
(
s_audio_status
==
0
){
char
*
urlmoddle
=
s_urlbuf
;
s_audio_volume
=
audioplay_volume_clamp
(
s_audio_volume
);
snprintf
(
command
,
sizeof
(
command
),
"sudo ffplay -nodisp -autoexit -loglevel quiet -af
\"
volume=%.3f
\"
\"
%s
\"
"
,
s_audio_volume
,
urlmoddle
);
my_zlog_debug
(
"播放地址: %s"
,
s_urlbuf
);
my_zlog_debug
(
"执行播放命令: %s"
,
command
);
ret
=
system
(
command
);
ret
=
audioplay_url_with_browser_preempt
(
urlmoddle
,
s_audio_volume
);
if
(
ret
!=
0
)
{
my_zlog_error
(
"播放失败"
);
s_audio_status
=
2
;
}
if
(
WIFEXITED
(
ret
)
&&
WEXITSTATUS
(
ret
)
==
0
)
{
if
(
ret
==
0
)
{
my_zlog_debug
(
"播放已成功完成 : %s "
,
s_urlbuf
);
s_audio_status
=
1
;
}
else
{
...
...
@@ -334,7 +397,7 @@ void audioplay_cycle(){
if
(
local_play_pending
)
{
int
exit_code
;
my_zlog_info
(
"播放本地音频: %s"
,
local_filepath
);
exit_code
=
play_local_audio_file
(
local_filepath
);
exit_code
=
audioplay_file_with_browser_preempt
(
local_filepath
,
1
.
0
);
if
(
exit_code
==
0
)
{
my_zlog_debug
(
"本地音频播放完成: %s"
,
local_filepath
);
}
else
{
...
...
drivers/sensors/audioplay.c.bak-audio-preempt-20260717
0 → 100644
View file @
dced7c62
This diff is collapsed.
Click to expand it.
drivers/sensors/audioplay.h
View file @
dced7c62
...
...
@@ -6,6 +6,13 @@ void audioplay_mqtt_receive(cJSON *body); //接收音频mqtt播放函数
void
audioplay_local_mqtt_receive
(
cJSON
*
body
);
// 2017 有人驾驶本地音频
void
audioplay_cycle
();
//音频播放线程中函数
/*
* 播放播报文件:与项目内其它 ALSA 播放串行,并在播放期间暂停浏览器使用的
* PulseAudio 默认输出。播放完成或超过 20 秒后会恢复浏览器音频。
*/
int
audioplay_file_with_browser_preempt
(
const
char
*
filepath
,
double
volume
);
int
audioplay_url_with_browser_preempt
(
const
char
*
url
,
double
volume
);
int
audio_wheat_init
();
int
audio_speaker_init
();
...
...
drivers/sensors/audioplay.h.bak-audio-preempt-20260717
0 → 100644
View file @
dced7c62
#ifndef AUDIOPLAY_H__
#define AUDIOPLAY_H__
#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();
int audio_speaker_init();
int audio_init();
int audio_config_init();//加入配置
#endif
\ No newline at end of file
drivers/sensors/audiotts_play.c
View file @
dced7c62
...
...
@@ -471,46 +471,15 @@ void video_tts_play() {
return
;
}
pid_t
pid
=
fork
();
if
(
pid
==
0
)
{
// 子进程:创建新的会话组,脱离父进程组
setsid
();
// 关键!创建新的会话组
char
command
[
256
];
snprintf
(
command
,
sizeof
(
command
),
"ffmpeg -i "
TTS_ADUINO_PTAH
" -af
\"
volume=%.1f
\"
-f alsa default 2>/dev/null"
,
s_volume
);
// 重定向标准输入输出,避免占用终端
if
(
freopen
(
"/dev/null"
,
"r"
,
stdin
)
==
NULL
)
{
my_zlog_error
(
"重定向stdin失败: %s"
,
strerror
(
errno
));
// 可以选择退出或继续
}
if
(
freopen
(
"/dev/null"
,
"w"
,
stdout
)
==
NULL
)
{
my_zlog_error
(
"重定向stdout失败: %s"
,
strerror
(
errno
));
}
if
(
freopen
(
"/dev/null"
,
"w"
,
stderr
)
==
NULL
)
{
my_zlog_error
(
"重定向stderr失败: %s"
,
strerror
(
errno
));
}
int
res
=
system
(
command
);
_exit
(
res
);
// 使用_exit避免清理父进程资源
}
else
if
(
pid
>
0
)
{
// 父进程:非阻塞等待,避免僵尸进程
int
status
;
waitpid
(
pid
,
&
status
,
WNOHANG
);
// 不阻塞的等待
my_zlog_debug
(
"启动独立播放进程 PID: %d"
,
pid
);
s_audio_tts_index
=
0
;
/* audioplay_cycle 本身运行在音频线程,这里同步等待可确保声卡一定被恢复。 */
int
exit_code
=
audioplay_file_with_browser_preempt
(
TTS_ADUINO_PTAH
,
s_volume
);
if
(
exit_code
==
0
)
{
my_zlog_info
(
"TTS 播报完成, volume: %.1f"
,
s_volume
);
}
else
{
my_zlog_warn
(
"TTS 播报失败或超时 exit=%d, volume: %.1f"
,
exit_code
,
s_volume
);
}
else
{
my_zlog_error
(
"fork()失败"
);
s_audio_tts_index
=
0
;
}
}
}
...
...
drivers/sensors/audiotts_play.c.bak-audio-preempt-20260717
0 → 100644
View file @
dced7c62
This diff is collapsed.
Click to expand it.
modules/http/http_config_mqtt.h
View file @
dced7c62
...
...
@@ -3,7 +3,7 @@
#include "common.h"
#define DEFAULT_MQTT_BROKER_ADDRESS "
119.45.167.177
"
#define DEFAULT_MQTT_BROKER_ADDRESS "
mqtt177.controlmelive.com
"
#define DEVICE_DEFAULT_VIDEO "https://jywy.yd-ss.com?dev="
typedef
struct
{
...
...
modules/mqtt/mqtt_infor_handle.c
View file @
dced7c62
...
...
@@ -213,7 +213,7 @@ static void refresh_cam_browser_only(const char *reason)
void
message_2_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
if
(
VERIFIED_MODE
==
false
)
{
refresh_cam_browser_only
(
"MQTT type2 verify off"
);
my_zlog_warn
(
"不使用验证"
);
...
...
@@ -234,7 +234,7 @@ void message_2_judyverify(cJSON *body)
// 当接收到3时候验证
void
message_3_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
if
(
VERIFIED_MODE
==
false
)
{
message_3
(
body
);
my_zlog_warn
(
"不使用验证"
);
...
...
@@ -255,7 +255,7 @@ void message_3_judyverify(cJSON *body)
// 当接收到4时候验证
void
message_4_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
if
(
VERIFIED_MODE
==
false
)
{
message_4
(
body
);
my_zlog_warn
(
"不使用验证"
);
...
...
@@ -276,7 +276,7 @@ void message_4_judyverify(cJSON *body)
void
message_6_steering_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
if
(
VERIFIED_MODE
==
false
)
{
steering_mqtt_recv
(
body
);
my_zlog_warn
(
"不使用验证"
);
...
...
@@ -303,7 +303,7 @@ void message_7_joystick_judyverify(cJSON *body)
return
;
}
if
(
VERIFIED_MODE
==
FALSE
)
if
(
VERIFIED_MODE
==
false
)
{
ptz_driver_set_joystick_json
(
joystick_ctrl
);
my_zlog_warn
(
"不使用验证"
);
...
...
modules/mqtt/mqtt_verify.c
View file @
dced7c62
...
...
@@ -9,9 +9,9 @@
#include "webrtcpush_run.h"
/*TRUE为打开验证,FALSE为关闭验证*/
bool
VERIFIED_MODE
=
FALSE
;
bool
VERIFIED_MODE
=
false
;
static
bool
s_service_verify
=
TRUE
;
//验证判断
static
bool
s_service_verify
=
true
;
//验证判断
int
g_verify_count
=
6000
;
//判断是否有一分钟
...
...
@@ -19,7 +19,7 @@ static char s_only_id_middle[11];
static
char
s_secret_key
[
1024
];
//存储上一次的topic
static
bool
s_secret_key_index
=
TRUE
;
//用于判断是否对比topic
static
bool
s_secret_key_index
=
true
;
//用于判断是否对比topic
/* topic 不同时发后端验证,失败可重试,超过 3 次不通过则判定该 topic 不通过 */
static
char
s_pending_verify_token
[
1024
];
...
...
@@ -172,7 +172,7 @@ int receive_jwt(cJSON *body) {
my_zlog_debug
(
"token时间戳:%1d"
,(
long
)
token_time_sec
);
if
(
token_time_sec
>
current_verify_time
){
if
(
s_service_verify
==
TRUE
)
g_verify_index
=
0
;
//验证默认为正确
if
(
s_service_verify
==
true
)
g_verify_index
=
0
;
//验证默认为正确
my_zlog_debug
(
"g_verify_index= %d "
,
g_verify_index
);
if
(
g_verify_count
>
12000
){
send_jwtser
(
token
);
...
...
@@ -205,7 +205,7 @@ int message2006_verify(cJSON *body){
if
(
json_status
==
NULL
||
json_onlyid
==
NULL
)
{
my_zlog_warn
(
"验证为空"
);
s_service_verify
=
FALSE
;
s_service_verify
=
false
;
g_verify_index
=
1
;
my_zlog_debug
(
"g_verify_index= %d "
,
g_verify_index
);
return
1
;
...
...
@@ -219,10 +219,10 @@ int message2006_verify(cJSON *body){
gboolean
driver_changed
=
(
s_secret_key
[
0
]
!=
'\0'
&&
strcmp
(
s_secret_key
,
s_pending_verify_token
)
!=
0
);
my_zlog_info
(
"获得验证正确, onlyid=%s"
,
onlyid
);
s_service_verify
=
TRUE
;
s_service_verify
=
true
;
g_verify_index
=
0
;
/* 后端通过后必须清除失败标志,否则正确 token 仍会提示验证不通过 */
strcpy
(
s_secret_key
,
s_pending_verify_token
);
s_secret_key_index
=
FALSE
;
s_secret_key_index
=
false
;
s_verify_retry_count
=
0
;
s_verify_retry_after_time
=
0
;
if
(
driver_changed
)
...
...
@@ -238,13 +238,13 @@ int message2006_verify(cJSON *body){
}
else
{
my_zlog_warn
(
"topic验证超过%d次不通过,禁止使用, token=%s"
,
VERIFY_RETRY_MAX
,
s_pending_verify_token
);
g_verify_index
=
1
;
s_service_verify
=
FALSE
;
s_service_verify
=
false
;
return
2
;
}
}
else
{
my_zlog_warn
(
"获得验证错误,禁止使用, onlyid=%s status=%s"
,
onlyid
,
status
);
g_verify_index
=
1
;
s_service_verify
=
FALSE
;
s_service_verify
=
false
;
return
2
;
}
}
...
...
@@ -297,14 +297,14 @@ int message2013_recverigy_open(cJSON *body_raw)
s_verify_open_query_gave_up
=
false
;
if
(
verify_status
->
valueint
==
1
)
{
VERIFIED_MODE
=
TRUE
;
VERIFIED_MODE
=
true
;
my_zlog_info
(
"开启验证成功(加密校验通过), verify_status=1"
);
cJSON_Delete
(
body
);
return
0
;
}
if
(
verify_status
->
valueint
==
0
)
{
VERIFIED_MODE
=
FALSE
;
VERIFIED_MODE
=
false
;
my_zlog_info
(
"关闭验证成功(加密校验通过), verify_status=0"
);
cJSON_Delete
(
body
);
return
0
;
...
...
modules/webrtcpush/rtc_client.c
View file @
dced7c62
...
...
@@ -21,6 +21,7 @@
typedef
struct
{
gchar
*
candidate
;
gchar
*
mid
;
gchar
*
ufrag
;
}
PendingRemoteIce
;
typedef
struct
{
...
...
@@ -277,6 +278,7 @@ static void free_pending_remote_ice(gpointer data)
return
;
g_free
(
ice
->
candidate
);
g_free
(
ice
->
mid
);
g_free
(
ice
->
ufrag
);
g_free
(
ice
);
}
...
...
@@ -1990,14 +1992,24 @@ static void flush_remote_ice(RtcClient *client)
for
(;;)
{
PendingRemoteIce
*
ice
;
int
pc
;
gboolean
ufrag_match
;
g_mutex_lock
(
&
client
->
lock
);
ice
=
g_queue_pop_head
(
client
->
pending_remote_ice
);
pc
=
client
->
pc
;
ufrag_match
=
!
ice
||
!
ice
->
ufrag
||
!
client
->
remote_ice_ufrag
||
g_strcmp0
(
ice
->
ufrag
,
client
->
remote_ice_ufrag
)
==
0
;
g_mutex_unlock
(
&
client
->
lock
);
if
(
!
ice
)
break
;
if
(
pc
>=
0
)
rtcAddRemoteCandidate
(
pc
,
ice
->
candidate
,
ice
->
mid
);
if
(
pc
>=
0
&&
ufrag_match
)
{
if
(
rtcAddRemoteCandidate
(
pc
,
ice
->
candidate
,
ice
->
mid
)
<
0
)
my_zlog_warn
(
"libdatachannel: rejected queued remote ICE candidate ufrag=%s"
,
ice
->
ufrag
?
ice
->
ufrag
:
"?"
);
}
else
if
(
!
ufrag_match
)
{
my_zlog_info
(
"libdatachannel: discard stale remote ICE candidate ufrag=%s current=%s"
,
ice
->
ufrag
?
ice
->
ufrag
:
"?"
,
client
->
remote_ice_ufrag
?
client
->
remote_ice_ufrag
:
"?"
);
}
free_pending_remote_ice
(
ice
);
}
}
...
...
@@ -2095,8 +2107,12 @@ int rtc_client_start(AppState *app)
void
rtc_client_reset
(
AppState
*
app
)
{
RtcClient
*
client
=
client_from_app
(
app
);
if
(
client
)
if
(
client
)
{
destroy_peer
(
client
);
g_mutex_lock
(
&
client
->
lock
);
g_queue_clear_full
(
client
->
pending_remote_ice
,
free_pending_remote_ice
);
g_mutex_unlock
(
&
client
->
lock
);
}
}
void
rtc_client_stop
(
AppState
*
app
)
...
...
@@ -2285,6 +2301,9 @@ void rtc_client_handle_remote_ice(AppState *app, JsonObject *candidate_obj)
RtcClient
*
client
=
client_from_app
(
app
);
const
gchar
*
candidate
;
const
gchar
*
mid
=
NULL
;
const
gchar
*
ufrag
=
NULL
;
gchar
*
candidate_ufrag
=
NULL
;
gboolean
queued
=
FALSE
;
int
pc
;
if
(
!
client
||
!
candidate_obj
||
...
...
@@ -2299,18 +2318,48 @@ void rtc_client_handle_remote_ice(AppState *app, JsonObject *candidate_obj)
json_node_get_value_type
(
node
)
==
G_TYPE_STRING
)
mid
=
json_object_get_string_member
(
candidate_obj
,
"sdpMid"
);
}
if
(
json_object_has_member
(
candidate_obj
,
"usernameFragment"
))
{
JsonNode
*
node
=
json_object_get_member
(
candidate_obj
,
"usernameFragment"
);
if
(
JSON_NODE_HOLDS_VALUE
(
node
)
&&
json_node_get_value_type
(
node
)
==
G_TYPE_STRING
)
ufrag
=
json_object_get_string_member
(
candidate_obj
,
"usernameFragment"
);
}
else
if
(
json_object_has_member
(
candidate_obj
,
"ufrag"
))
{
JsonNode
*
node
=
json_object_get_member
(
candidate_obj
,
"ufrag"
);
if
(
JSON_NODE_HOLDS_VALUE
(
node
)
&&
json_node_get_value_type
(
node
)
==
G_TYPE_STRING
)
ufrag
=
json_object_get_string_member
(
candidate_obj
,
"ufrag"
);
}
if
(
!
ufrag
)
{
const
gchar
*
tag
=
strstr
(
candidate
,
" ufrag "
);
if
(
tag
)
{
const
gchar
*
end
;
tag
+=
strlen
(
" ufrag "
);
end
=
strchr
(
tag
,
' '
);
candidate_ufrag
=
end
?
g_strndup
(
tag
,
(
gsize
)(
end
-
tag
))
:
g_strdup
(
tag
);
ufrag
=
candidate_ufrag
;
}
}
g_mutex_lock
(
&
client
->
lock
);
pc
=
client
->
pc
;
if
(
pc
<
0
)
{
if
(
pc
<
0
||
(
ufrag
&&
client
->
remote_ice_ufrag
&&
g_strcmp0
(
ufrag
,
client
->
remote_ice_ufrag
)
!=
0
))
{
PendingRemoteIce
*
pending
=
g_new0
(
PendingRemoteIce
,
1
);
pending
->
candidate
=
g_strdup
(
candidate
);
pending
->
mid
=
g_strdup
(
mid
);
pending
->
ufrag
=
g_strdup
(
ufrag
);
g_queue_push_tail
(
client
->
pending_remote_ice
,
pending
);
pc
=
-
1
;
queued
=
TRUE
;
}
g_mutex_unlock
(
&
client
->
lock
);
if
(
pc
>=
0
&&
rtcAddRemoteCandidate
(
pc
,
candidate
,
mid
)
<
0
)
my_zlog_warn
(
"libdatachannel: rejected remote ICE candidate"
);
else
if
(
queued
)
my_zlog_info
(
"libdatachannel: queued remote ICE candidate for ufrag=%s"
,
ufrag
?
ufrag
:
"?"
);
g_free
(
candidate_ufrag
);
}
gboolean
rtc_client_is_active
(
AppState
*
app
)
...
...
modules/webrtcpush/webrtcpush_config.h
View file @
dced7c62
...
...
@@ -8,7 +8,7 @@
*
* 原生分支:v4l2 采集 → mpph264enc(或 x264enc 回退)→ libdatachannel 发送。
*/
#define WEBRTCPUSH_USE_MPP
1
#define WEBRTCPUSH_USE_MPP
0
/* 正常固定 24fps;弱网以降码率为主,后续若启用动态帧率也不得低于 22fps。 */
#define WEBRTCPUSH_H264_FPS 24
...
...
@@ -17,10 +17,10 @@
/*
* 与 gst_webrtc_pipeline / jywy 浏览器推流对齐的码率策略。
* 首屏先用
900kbps,不像 1.4Mbps
那样猛冲,也不要低到一进来就糊。
* 首屏先用
1.06Mbps,不像高码率
那样猛冲,也不要低到一进来就糊。
* RTCP REMB 只作为码率趋势:小步慢降、慢升、带滞回,尽量接近浏览器的无感自适应。
*/
#define WEBRTCPUSH_INITIAL_BITRATE
90
0000U
#define WEBRTCPUSH_INITIAL_BITRATE
106
0000U
#define WEBRTCPUSH_MIN_BITRATE 800000U
#define WEBRTCPUSH_MAX_BITRATE 3000000U
#define WEBRTCPUSH_REMB_UTIL_PERCENT 80U
...
...
@@ -44,6 +44,8 @@
#define WEBRTCPUSH_REMB_SANE_PACING_MAX_MS 100U
/* IDR 会产生短时大包,不能在这个窗口内把瞬时 pacing 峰值误判成网络拥塞。 */
#define WEBRTCPUSH_REMB_IDR_GRACE_MS 1000U
/* 手机切 Wi-Fi/蜂窝或换手机时,旧成员的 leave 可能晚于新 offer 到达。 */
#define WEBRTCPUSH_PEER_LEAVE_GRACE_MS 8000U
/* 达到 2.3Mbps 后继续发送一段时间,让浏览器有真实流量可重新估计带宽。 */
#define WEBRTCPUSH_INITIAL_PROBE_HOLD_MS 6000U
#define WEBRTCPUSH_PACING_HEADROOM_PERCENT 135U
...
...
modules/webrtcpush/ws_signaling.c
View file @
dced7c62
...
...
@@ -23,11 +23,15 @@ static gchar *s_ws_url;
static
GMainContext
*
s_main_ctx
;
static
gchar
*
s_debounced_offer_sdp
=
NULL
;
static
guint
s_debounce_offer_id
=
0
;
static
guint
s_peer_leave_reset_id
=
0
;
static
guint
s_offer_generation
=
0
;
static
guint
s_leave_generation
=
0
;
static
gboolean
reconnect_cb
(
gpointer
data
);
static
void
ws_connect
(
void
);
static
void
reset_signaling_session
(
AppState
*
app
,
gboolean
teardown_pipeline
);
static
gboolean
idle_pipeline_teardown
(
gpointer
p
);
static
gboolean
delayed_peer_leave_reset
(
gpointer
p
);
static
void
schedule_tx_flush
(
void
);
static
void
dispatch_json
(
const
gchar
*
payload
);
...
...
@@ -228,6 +232,12 @@ static gboolean debounced_offer_fire(gpointer user_data) {
}
static
void
schedule_offer
(
AppState
*
app
,
const
gchar
*
sdp
)
{
s_offer_generation
++
;
if
(
s_peer_leave_reset_id
)
{
g_source_remove
(
s_peer_leave_reset_id
);
s_peer_leave_reset_id
=
0
;
my_zlog_info
(
"webrtcpush: new offer cancels pending stale peer-leave reset"
);
}
if
(
!
app
->
member_id
)
{
g_free
(
s_pending_offer_sdp
);
s_pending_offer_sdp
=
g_strdup
(
sdp
);
...
...
@@ -388,8 +398,14 @@ static void dispatch_json(const gchar *payload) {
if
(
!
g_strcmp0
(
t
,
"leave"
))
{
if
(
rtc_client_is_active
(
s_app
))
{
my_zlog_info
(
"webrtcpush: peer left, reset libdatachannel peer"
);
g_idle_add
(
idle_pipeline_teardown
,
s_app
);
if
(
s_peer_leave_reset_id
)
g_source_remove
(
s_peer_leave_reset_id
);
s_leave_generation
=
s_offer_generation
;
s_peer_leave_reset_id
=
g_timeout_add
(
WEBRTCPUSH_PEER_LEAVE_GRACE_MS
,
delayed_peer_leave_reset
,
s_app
);
my_zlog_info
(
"webrtcpush: peer left, defer reset %ums for network/device switch"
,
WEBRTCPUSH_PEER_LEAVE_GRACE_MS
);
}
g_object_unref
(
parser
);
return
;
...
...
@@ -436,6 +452,12 @@ static void dispatch_json(const gchar *payload) {
if
(
json_node_get_value_type
(
midn
)
==
G_TYPE_STRING
)
json_object_set_string_member
(
co
,
"sdpMid"
,
json_object_get_string_member
(
root
,
"sdpMid"
));
}
if
(
json_object_has_member
(
root
,
"usernameFragment"
))
{
JsonNode
*
ufn
=
json_object_get_member
(
root
,
"usernameFragment"
);
if
(
json_node_get_value_type
(
ufn
)
==
G_TYPE_STRING
)
json_object_set_string_member
(
co
,
"usernameFragment"
,
json_object_get_string_member
(
root
,
"usernameFragment"
));
}
g_idle_add
(
idle_ice
,
co
);
}
}
...
...
@@ -506,6 +528,26 @@ static gboolean idle_pipeline_teardown(gpointer p) {
return
G_SOURCE_REMOVE
;
}
static
gboolean
delayed_peer_leave_reset
(
gpointer
p
)
{
AppState
*
app
=
p
;
guint
generation
=
s_leave_generation
;
s_peer_leave_reset_id
=
0
;
if
(
!
app
||
generation
!=
s_offer_generation
)
{
my_zlog_info
(
"webrtcpush: stale peer-leave reset ignored (new offer generation)"
);
return
G_SOURCE_REMOVE
;
}
if
(
rtc_client_media_open
(
app
))
{
my_zlog_info
(
"webrtcpush: stale peer-leave reset ignored (new media already open)"
);
return
G_SOURCE_REMOVE
;
}
if
(
rtc_client_is_active
(
app
))
{
my_zlog_info
(
"webrtcpush: peer leave confirmed, release inactive libdatachannel peer"
);
rtc_client_reset
(
app
);
}
return
G_SOURCE_REMOVE
;
}
static
void
ws_connect
(
void
)
{
if
(
s_ws_exiting
||
!
s_app
||
!
s_ws_url
)
return
;
...
...
@@ -610,6 +652,10 @@ void ws_signaling_stop(AppState *app) {
g_source_remove
(
s_reconnect_id
);
s_reconnect_id
=
0
;
}
if
(
s_peer_leave_reset_id
)
{
g_source_remove
(
s_peer_leave_reset_id
);
s_peer_leave_reset_id
=
0
;
}
if
(
s_ping_id
)
{
g_source_remove
(
s_ping_id
);
s_ping_id
=
0
;
...
...
zlog.conf
View file @
dced7c62
...
...
@@ -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-07-1
1
.log"
;
millisecond
my_log
.*
"/home/orangepi/car/master/log/log_2026-07-1
4
.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