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
6a503b14
Commit
6a503b14
authored
Dec 20, 2025
by
DESKTOP-MC5UL36\dell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
可以发送mqtt开启关闭tailscale vpn, unix_server,go程序更新和根据后台配置开启go视频或浏览器
parent
b77cdb0a
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1153 additions
and
361 deletions
+1153
-361
CMakeLists.txt
CMakeLists.txt
+6
-0
main.c
app/main/main.c
+55
-32
pthread_open.c
app/main/pthread_open.c
+189
-91
modules_common.h
include/modules_common.h
+4
-0
go_deploy.c
modules/go_deploy/go_deploy.c
+377
-0
go_deploy.h
modules/go_deploy/go_deploy.h
+20
-0
unix_socket_server.c
modules/ipc/unix_socket_server.c
+110
-0
unix_socket_server.h
modules/ipc/unix_socket_server.h
+8
-0
mqtt_infor_handle.c
modules/mqtt/mqtt_infor_handle.c
+283
-238
tailscale_deploy.c
modules/tailscale_deploy/tailscale_deploy.c
+93
-0
tailscale_deploy.h
modules/tailscale_deploy/tailscale_deploy.h
+8
-0
No files found.
CMakeLists.txt
View file @
6a503b14
...
...
@@ -51,6 +51,9 @@ include_directories(
modules/mqtt
modules/http
modules/browser
modules/ipc
modules/go_deploy
modules/tailscale_deploy
third_party/zlog/src
third_party/mosquitto/include
third_party/mosquitto/lib
...
...
@@ -70,6 +73,9 @@ file(GLOB_RECURSE SOURCES
modules/mqtt/*.c
modules/http/*.c
modules/browser/*.c
modules/ipc/*.c
modules/go_deploy/*.c
modules/tailscale_deploy/*.c
app/device_identity/*.c
app/device_change/*.c
app/main/*.c
...
...
app/main/main.c
View file @
6a503b14
#include "main.h"
int
main
(){
if
(
mylog_init
()
!=
0
){
my_zlog_error
(
"日志初始化失败,错误代码:%d"
,
mylog_init
());
return
-
1
;
int
main
()
{
if
(
mylog_init
()
!=
0
)
{
my_zlog_error
(
"日志初始化失败,错误代码:%d"
,
mylog_init
());
return
-
1
;
}
if
(
wiringPiSetup
()
==
-
1
)
{
my_zlog_fatal
(
"WiringPi setup failed!"
);
return
-
2
;
if
(
wiringPiSetup
()
==
-
1
)
{
my_zlog_fatal
(
"WiringPi setup failed!"
);
return
-
2
;
}
if
(
device_id_file_init
()
!=
0
){
my_zlog_error
(
"设备id读取失败"
);
return
-
3
;
}
if
(
device_mqtt_topic_init
()
!=
0
){
if
(
device_id_file_init
()
!=
0
)
{
my_zlog_error
(
"设备id读取失败"
);
return
-
3
;
}
if
(
device_mqtt_topic_init
()
!=
0
)
{
my_zlog_error
(
"设备id判断失败"
);
return
-
4
;
}
return
-
4
;
}
if
(
request_date
()
!=
0
){
my_zlog_error
(
"请求数据失败"
);
return
-
5
;
}
if
(
request_date
()
!=
0
)
{
my_zlog_error
(
"请求数据失败"
);
return
-
5
;
}
if
(
http_mqtt_video_init
()
!=
0
){
if
(
http_mqtt_video_init
()
!=
0
)
{
my_zlog_error
(
"请求mqtt服务器和video数据失败"
);
return
-
6
;
}
if
(
audio_config_init
()
!=
0
){
// 检查并更新 Go 程序
if
(
go_deploy_check_and_update
()
!=
0
)
{
my_zlog_warn
(
"Go 程序检查/部署失败"
);
}
// 启动 Unix Socket 服务,用于 C 和 Go 程序通信
if
(
ipc_start_unix_server
(
NULL
)
!=
0
)
{
my_zlog_warn
(
"IPC Unix Socket Server 启动失败"
);
return
-
8
;
}
if
(
audio_config_init
()
!=
0
)
{
my_zlog_warn
(
"音频配置初始化失败"
);
}
if
(
hardware_iic_init
()
!=
0
){
if
(
hardware_iic_init
()
!=
0
)
{
my_zlog_error
(
"硬件iic初始化失败"
);
return
-
7
;
}
if
(
device_shot_cooling_init
()
!=
0
){
if
(
device_shot_cooling_init
()
!=
0
)
{
my_zlog_warn
(
"该设备没有冷却"
);
}
if
(
audio_init
()
==
0
){
if
(
audio_init
()
==
0
)
{
my_zlog_info
(
"音频命令执行初始化成功"
);
}
int
thread_rc
=
thread_start_init
(
thread_exit_time
,
thread_mqtt_beat
,
thread_open_browser
,
thread_mqtt_reconnect
,
thread_time_calculation
,
thread_play_mp3
);
if
(
thread_rc
!=
0
){
int
thread_rc
=
thread_start_init
(
thread_exit_time
,
thread_mqtt_beat
,
thread_open_browser
,
thread_mqtt_reconnect
,
thread_time_calculation
,
thread_play_mp3
);
if
(
thread_rc
!=
0
)
{
my_zlog_warn
(
"多线程初始化失败"
);
return
-
7
;
}
}
thread_end_close
();
device_end_close
(
g_device_type
);
self_control_thread_close
();
//
销毁自控的线程
my_log_close
();
//
关闭日志
self_control_thread_close
();
//
销毁自控的线程
my_log_close
();
//
关闭日志
hardware_iic_close
();
my_zlog_info
(
"程序关闭成功"
);
return
0
;
}
\ No newline at end of file
app/main/pthread_open.c
View file @
6a503b14
...
...
@@ -3,32 +3,35 @@
#include "drivers_common.h"
#include "modules_common.h"
#include "pthread_open.h"
#include "go_deploy.h"
#define PTHREAD_MAX 6
pthread_t
g_thread
[
PTHREAD_MAX
];
// 全局线程句柄数组(或传参)
pthread_t
g_thread
[
PTHREAD_MAX
];
// 全局线程句柄数组(或传参)
int
g_webrtc_index
=
0
;
//
判断游览器是否打开
int
g_webrtc_index
=
0
;
//
判断游览器是否打开
int
g_mqtt_grc
=
0
;
//
mqtt连接状态机
int
g_mqtt_grc
=
0
;
//
mqtt连接状态机
void
*
g_args
[
PTHREAD_MAX
]
=
{
NULL
};
void
*
g_args
[
PTHREAD_MAX
]
=
{
NULL
};
int
thread_start_init
(
ThreadFunc
thread_exit_time
,
ThreadFunc
thread_mqtt_beat
,
ThreadFunc
thread_open_browser
,
ThreadFunc
thread_mqtt_reconnect
,
ThreadFunc
thread_time_calculation
,
ThreadFunc
thread_play_mp3
)
{
ThreadFunc
thread_open_browser
,
ThreadFunc
thread_mqtt_reconnect
,
ThreadFunc
thread_time_calculation
,
ThreadFunc
thread_play_mp3
)
{
ThreadFunc
thread_funcs
[]
=
{
thread_exit_time
,
thread_mqtt_beat
,
thread_open_browser
,
thread_mqtt_reconnect
,
thread_time_calculation
,
thread_play_mp3
};
thread_play_mp3
};
for
(
int
i
=
0
;
i
<
PTHREAD_MAX
;
i
++
)
{
if
(
pthread_create
(
&
g_thread
[
i
],
NULL
,
thread_funcs
[
i
],
g_args
[
i
])
!=
0
)
{
for
(
int
i
=
0
;
i
<
PTHREAD_MAX
;
i
++
)
{
if
(
pthread_create
(
&
g_thread
[
i
],
NULL
,
thread_funcs
[
i
],
g_args
[
i
])
!=
0
)
{
my_zlog_error
(
"创建线程 %d 失败"
,
i
);
return
i
+
1
;
}
...
...
@@ -36,113 +39,201 @@ int thread_start_init(ThreadFunc thread_exit_time, ThreadFunc thread_mqtt_beat,
return
0
;
}
//出现意外自动停止
void
*
thread_exit_time
(
void
*
arg
)
{
pg0403_serial_run
();
while
(
1
){
if
(
get_self_control_index
()
==
false
){
delay_ms
(
100
);
pthread_mutex_lock
(
&
g_exit_count_mutex
);
g_devcontrol_exit_count
++
;
if
(
g_devcontrol_exit_count
>=
5
)
{
device_stop
(
g_device_type
);
g_devcontrol_exit_count
=
6
;
}
pthread_mutex_unlock
(
&
g_exit_count_mutex
);
}
else
if
(
get_self_control_index
()
==
true
){
delay_ms
(
20
);
set_self_control_time_countfuntion
();
}
// 出现意外自动停止
void
*
thread_exit_time
(
void
*
arg
)
{
pg0403_serial_run
();
while
(
1
)
{
if
(
get_self_control_index
()
==
false
)
{
delay_ms
(
100
);
pthread_mutex_lock
(
&
g_exit_count_mutex
);
g_devcontrol_exit_count
++
;
if
(
g_devcontrol_exit_count
>=
5
)
{
device_stop
(
g_device_type
);
g_devcontrol_exit_count
=
6
;
}
pthread_mutex_unlock
(
&
g_exit_count_mutex
);
}
else
if
(
get_self_control_index
()
==
true
)
{
delay_ms
(
20
);
set_self_control_time_countfuntion
();
}
}
return
NULL
;
return
NULL
;
}
/*心跳线程处理函数,心跳发送前会像上层请求是否需要验证*/
void
*
thread_mqtt_beat
(
void
*
arg
)
{
void
*
thread_mqtt_beat
(
void
*
arg
)
{
my_zlog_info
(
"thread_mqtt_beat start"
);
g_webrtc_index
=
1
;
g_webrtc_index
=
1
;
delay_s
(
3
);
/*在这步进行检测,等mqtt连接成功后检查*/
// if(wifi_change_sendmqtt_init()!=0){
// my_zlog_error("WIFI是否更改检查相关,不会到这一步,有问题会直接重启,可能会导致重启,不会因此造成程序停止");
// }
if
(
verify_open_index_init
()
!=
0
){
if
(
verify_open_index_init
()
!=
0
)
{
my_zlog_info
(
"mqtt send verify is NULL"
);
}
//如果为相关的不需要心跳或者游览器设备,提早结束线程
if
(
g_device_type
==
DEVICE_ROBOT_DOG0501
){
my_zlog_info
(
"device am robot and no c/c++"
);
// 如果为相关的不需要心跳或者游览器设备,提早结束线程
if
(
g_device_type
==
DEVICE_ROBOT_DOG0501
)
{
my_zlog_info
(
"device am robot and no c/c++"
);
return
NULL
;
}
while
(
1
)
{
while
(
1
)
{
delay_ms
(
100
);
g_heartbeat_count
++
;
set_tank_angle_count
();
//角度发布计时,1开始计时,0清0
if
(
g_mqtt_grc
==
0
){
mqtt_beat_wirte
();
//心跳等发布函数,更具不同时间发布
set_tank_angle_count
();
// 角度发布计时,1开始计时,0清0
if
(
g_mqtt_grc
==
0
)
{
mqtt_beat_wirte
();
// 心跳等发布函数,更具不同时间发布
if
(
get_device_self_control_configuration_initialization
()
==
0
){
if
(
get_device_self_control_configuration_initialization
()
==
0
)
{
my_zlog_warn
(
"自控配置初始化成功"
);
}
}
}
}
}
return
NULL
;
}
//打开游览器线程,让游览器一直在一个线程中打开并运行
void
*
thread_open_browser
(
void
*
arg
)
{
// 打开go_video或者浏览器
void
*
thread_open_browser
(
void
*
arg
)
{
if
(
g_device_type
==
DEVICE_PG_GPS0403
){
return
NULL
;
if
(
g_device_type
==
DEVICE_PG_GPS0403
)
{
return
NULL
;
}
delay_s
(
5
);
// 检查 go_video 可执行文件是否存在
my_zlog_info
(
"开始检测go_video可执行文件是否存在"
);
if
(
strcmp
(
g_webrtc_mode
,
"go"
)
==
0
&&
access
(
"/home/orangepi/go_video/go_video"
,
F_OK
)
==
0
)
{
my_zlog_info
(
"检测到 go_video 可执行文件"
);
// 检查 go_video 进程是否已经在运行
FILE
*
fp
=
popen
(
"pidof go_video"
,
"r"
);
if
(
fp
!=
NULL
)
{
char
buf
[
64
]
=
{
0
};
if
(
fgets
(
buf
,
sizeof
(
buf
),
fp
)
!=
NULL
)
{
// 检查是否真的有数字 PID
int
pid
=
atoi
(
buf
);
if
(
pid
>
0
)
{
// 进程已经在运行,先终止
char
kill_cmd
[
64
];
snprintf
(
kill_cmd
,
sizeof
(
kill_cmd
),
"kill %d"
,
pid
);
my_zlog_info
(
"检测到 go_video 进程 %d 已在运行,尝试终止"
,
pid
);
if
(
system
(
kill_cmd
)
!=
0
)
{
my_zlog_warn
(
"无法终止 go_video 进程 %d"
,
pid
);
pclose
(
fp
);
return
NULL
;
}
my_zlog_info
(
"已终止 go_video 进程 %d"
,
pid
);
}
}
pclose
(
fp
);
}
// 进程未运行,启动它
my_zlog_info
(
"启动 go_video 程序并跳过浏览器"
);
system
(
"sudo -u orangepi nohup /home/orangepi/go_video/go_video > /dev/null 2>&1 &"
);
return
NULL
;
}
int
result
=
system
(
"pkill chromium"
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
my_zlog_error
(
"system error"
);
}
delay_s
(
5
);
while
(
1
){
while
(
1
)
{
if
(
g_webrtc_index
==
1
)
{
if
(
is_browser_running
()
==
true
)
{
if
(
g_webrtc_index
==
1
)
{
if
(
is_browser_running
()
==
true
)
{
continue
;
}
else
{
}
else
{
my_zlog_info
(
"open cam"
);
opencamsh
();
//10s后打开游览器并且进入网址
opencamsh
();
// 10s后打开游览器并且进入网址
}
}
delay_ms
(
200
);
}
return
NULL
;
return
NULL
;
}
//mqtt异常处理,断开自动重连,简单粗暴
void
*
thread_mqtt_reconnect
(
void
*
arg
)
{
while
(
1
){
static
int
reconnect_count
=
0
;
// 打开游览器线程,让游览器一直在一个线程中打开并运行
// void *thread_open_browser(void *arg) {
// if(g_device_type==DEVICE_PG_GPS0403){
// return NULL;
// }
// int result = system("pkill chromium");
// if (result != 0) {
// my_zlog_error("system error");
// }
// delay_s(5);
// while(1){
// if(g_webrtc_index==1) {
// if(is_browser_running() == true ) {
// continue;
// }else{
// my_zlog_info("open cam");
// opencamsh();//10s后打开游览器并且进入网址
// }
// }
// delay_ms(200);
// }
// return NULL;
// }
// mqtt异常处理,断开自动重连,简单粗暴
void
*
thread_mqtt_reconnect
(
void
*
arg
)
{
while
(
1
)
{
static
int
reconnect_count
=
0
;
static
int
remqtt_index
;
remqtt_index
=
mqtt_init
();
if
(
remqtt_index
==
0
){
my_zlog_warn
(
"mqtt success"
,
remqtt_index
);
remqtt_index
=
mqtt_init
();
if
(
remqtt_index
==
0
)
{
my_zlog_warn
(
"mqtt success"
,
remqtt_index
);
break
;
}
else
{
my_zlog_warn
(
"wait... mqtt reconect,error:%d"
,
remqtt_index
);
}
else
{
my_zlog_warn
(
"wait... mqtt reconect,error:%d"
,
remqtt_index
);
delay_ms
(
300
);
reconnect_count
++
;
if
(
reconnect_count
>
MAX_RECONNECT_ATTEMPTS
){
if
(
reconnect_count
>
MAX_RECONNECT_ATTEMPTS
)
{
send_fail_mqtt_conect
();
break
;
}
...
...
@@ -151,45 +242,52 @@ void *thread_mqtt_reconnect(void *arg) {
}
mqtt_cycle
();
mqtt_clean
();
return
NULL
;
}
//专门用于计时的线程
void
*
thread_time_calculation
(
void
*
arg
)
{
while
(
1
)
{
// 专门用于计时的线程
void
*
thread_time_calculation
(
void
*
arg
)
{
while
(
1
)
{
device_fast_read
();
// 用于快速判断设备的及时检查和停止
device_fast_read
();
//用于快速判断设备的及时检查和停止
delay_ms
(
5
);
g_device_delay_back_count
++
;
//
设备计时,坦克打击倒退逻辑
g_device_delay_back_count
++
;
//
设备计时,坦克打击倒退逻辑
pthread_mutex_lock
(
&
g_verify_mutex
);
g_verify_count
++
;
//
jwt验证计时,每15s一次
g_verify_count
++
;
//
jwt验证计时,每15s一次
pthread_mutex_unlock
(
&
g_verify_mutex
);
if
(
g_verify_count
>=
20000
)
{
//防止溢出
if
(
g_verify_count
>=
20000
)
{
// 防止溢出
pthread_mutex_lock
(
&
g_verify_mutex
);
g_verify_count
=
20000
;
pthread_mutex_unlock
(
&
g_verify_mutex
);
pthread_mutex_unlock
(
&
g_verify_mutex
);
}
if
(
g_device_delay_back_count
>=
5000
)
g_device_delay_back_count
=
5000
;
//防止溢出
}
if
(
g_device_delay_back_count
>=
5000
)
g_device_delay_back_count
=
5000
;
// 防止溢出
}
return
NULL
;
}
//专门处理MP3播放
void
*
thread_play_mp3
(
void
*
arg
)
{
// 专门处理MP3播放
void
*
thread_play_mp3
(
void
*
arg
)
{
audioplay_cycle
();
return
NULL
;
}
// 等待线程结束
void
thread_end_close
()
{
for
(
int
i
=
0
;
i
<
PTHREAD_MAX
;
i
++
)
{
if
(
g_thread
[
i
])
pthread_join
(
g_thread
[
i
],
NULL
);
void
thread_end_close
()
{
for
(
int
i
=
0
;
i
<
PTHREAD_MAX
;
i
++
)
{
if
(
g_thread
[
i
])
pthread_join
(
g_thread
[
i
],
NULL
);
}
}
include/modules_common.h
View file @
6a503b14
...
...
@@ -7,5 +7,8 @@
#include "mylog.h"
#include "mqtt_common.h"
#include "pthrpoll.h"
#include "unix_socket_server.h"
#include "go_deploy.h"
#include "tailscale_deploy.h"
#endif
\ No newline at end of file
modules/go_deploy/go_deploy.c
0 → 100644
View file @
6a503b14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <curl/curl.h>
#include <cJSON.h>
#include <openssl/evp.h>
#include "go_deploy.h"
#include "common.h" // 包含日志 my_zlog 等
#include "device_fileopen.h" // 包含设备文件读取函数
#define GO_VIDEO_FILENAME "go_video"
#define HASH_TYPE_SHA256 1
char
g_webrtc_mode
[
32
]
=
"web"
;
// 内存结构体,用于 curl 回调
struct
MemoryStruct
{
char
*
memory
;
size_t
size
;
};
// CURL 写回调(内存)
static
size_t
WriteMemoryCallback
(
void
*
contents
,
size_t
size
,
size_t
nmemb
,
void
*
userp
)
{
size_t
realsize
=
size
*
nmemb
;
struct
MemoryStruct
*
mem
=
(
struct
MemoryStruct
*
)
userp
;
char
*
ptr
=
realloc
(
mem
->
memory
,
mem
->
size
+
realsize
+
1
);
if
(
!
ptr
)
{
my_zlog_error
(
"not enough memory (realloc returned NULL)"
);
return
0
;
}
mem
->
memory
=
ptr
;
memcpy
(
&
(
mem
->
memory
[
mem
->
size
]),
contents
,
realsize
);
mem
->
size
+=
realsize
;
mem
->
memory
[
mem
->
size
]
=
0
;
return
realsize
;
}
// CURL 写回调(文件)
static
size_t
WriteFileCallback
(
void
*
ptr
,
size_t
size
,
size_t
nmemb
,
FILE
*
stream
)
{
size_t
written
=
fwrite
(
ptr
,
size
,
nmemb
,
stream
);
return
written
;
}
// 计算文件的 MD5 (128位)
static
int
calculate_file_hash
(
const
char
*
path
,
char
*
output_hash
)
{
FILE
*
file
=
fopen
(
path
,
"rb"
);
if
(
!
file
)
return
-
1
;
EVP_MD_CTX
*
mdctx
=
EVP_MD_CTX_new
();
const
EVP_MD
*
md
=
EVP_md5
();
// 使用 MD5 (128位)
unsigned
char
hash
[
EVP_MAX_MD_SIZE
];
unsigned
int
md_len
;
char
buffer
[
4096
];
size_t
bytes
;
if
(
!
mdctx
)
{
fclose
(
file
);
return
-
1
;
}
EVP_DigestInit_ex
(
mdctx
,
md
,
NULL
);
while
((
bytes
=
fread
(
buffer
,
1
,
sizeof
(
buffer
),
file
))
!=
0
)
{
EVP_DigestUpdate
(
mdctx
,
buffer
,
bytes
);
}
EVP_DigestFinal_ex
(
mdctx
,
hash
,
&
md_len
);
EVP_MD_CTX_free
(
mdctx
);
fclose
(
file
);
// 转为 hex 字符串
for
(
unsigned
int
i
=
0
;
i
<
md_len
;
i
++
)
{
sprintf
(
&
output_hash
[
i
*
2
],
"%02x"
,
hash
[
i
]);
}
output_hash
[
md_len
*
2
]
=
'\0'
;
return
0
;
}
// 下载文件
static
int
download_file
(
const
char
*
url
,
const
char
*
filepath
)
{
CURL
*
curl
;
FILE
*
fp
;
CURLcode
res
;
curl
=
curl_easy_init
();
if
(
!
curl
)
return
-
1
;
fp
=
fopen
(
filepath
,
"wb"
);
if
(
!
fp
)
{
my_zlog_error
(
"Failed to open file for writing: %s"
,
filepath
);
curl_easy_cleanup
(
curl
);
return
-
1
;
}
curl_easy_setopt
(
curl
,
CURLOPT_URL
,
url
);
curl_easy_setopt
(
curl
,
CURLOPT_WRITEFUNCTION
,
WriteFileCallback
);
curl_easy_setopt
(
curl
,
CURLOPT_WRITEDATA
,
fp
);
curl_easy_setopt
(
curl
,
CURLOPT_FOLLOWLOCATION
,
1L
);
curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYPEER
,
0L
);
// 忽略 SSL 验证(视情况而定)
curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYHOST
,
0L
);
res
=
curl_easy_perform
(
curl
);
fclose
(
fp
);
curl_easy_cleanup
(
curl
);
if
(
res
!=
CURLE_OK
)
{
my_zlog_error
(
"Download failed: %s"
,
curl_easy_strerror
(
res
));
remove
(
filepath
);
// 下载失败删除残缺文件
return
-
1
;
}
return
0
;
}
// 检查是否有 pip3,没有则安装
static
int
check_and_install_pip3
(
void
)
{
if
(
system
(
"which pip3 > /dev/null 2>&1"
)
!=
0
)
{
my_zlog_info
(
"pip3 not found. Installing python3-pip..."
);
int
install_ret
=
system
(
"sudo apt-get update && sudo apt-get install -y python3-pip"
);
if
(
install_ret
!=
0
)
{
my_zlog_error
(
"Failed to install python3-pip, return code: %d"
,
install_ret
);
return
-
1
;
}
else
{
my_zlog_info
(
"python3-pip installation completed successfully."
);
}
}
return
0
;
}
int
go_deploy_check_and_update
(
void
)
{
CURL
*
curl
;
CURLcode
res
;
struct
MemoryStruct
chunk
;
chunk
.
memory
=
malloc
(
1
);
chunk
.
size
=
0
;
int
ret
=
-
1
;
char
*
home_dir
=
"/home/orangepi"
;
char
target_dir
[
256
];
snprintf
(
target_dir
,
sizeof
(
target_dir
),
"%s/go_video"
,
home_dir
);
my_zlog_info
(
"target_dir: %s"
,
target_dir
);
// 确保目录存在
struct
stat
st
=
{
0
};
if
(
stat
(
target_dir
,
&
st
)
==
-
1
)
{
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
);
}
}
// 确保目录权限正确
chmod
(
target_dir
,
0777
);
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
);
// 1. 请求 Config
curl_global_init
(
CURL_GLOBAL_ALL
);
curl
=
curl_easy_init
();
if
(
!
curl
)
{
my_zlog_error
(
"Failed to init curl"
);
free
(
chunk
.
memory
);
return
-
1
;
}
char
url
[
512
];
const
char
*
device_no
=
device_id_function
();
if
(
device_no
==
NULL
||
strlen
(
device_no
)
==
0
)
{
my_zlog_error
(
"deviceNo is empty"
);
goto
cleanup
;
}
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
);
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_SSL_VERIFYPEER
,
0L
);
curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYHOST
,
0L
);
res
=
curl_easy_perform
(
curl
);
my_zlog_info
(
"curl_easy_perform result: %d"
,
res
);
if
(
res
!=
CURLE_OK
)
{
my_zlog_error
(
"curl_easy_perform() failed: %s"
,
curl_easy_strerror
(
res
));
goto
cleanup
;
}
// 2. 解析 JSON
cJSON
*
root
=
cJSON_Parse
(
chunk
.
memory
);
if
(
!
root
)
{
my_zlog_error
(
"JSON Parse Error"
);
goto
cleanup
;
}
cJSON
*
data
=
cJSON_GetObjectItem
(
root
,
"data"
);
char
*
data_str
=
cJSON_Print
(
data
);
if
(
data_str
)
{
my_zlog_info
(
"Got config data: %s"
,
data_str
);
free
(
data_str
);
}
if
(
!
data
)
{
cJSON_Delete
(
root
);
goto
cleanup
;
}
cJSON
*
moreInfo
=
cJSON_GetObjectItem
(
data
,
"moreInfo"
);
if
(
!
moreInfo
)
{
my_zlog_warn
(
"moreInfo is null"
);
cJSON_Delete
(
root
);
goto
cleanup
;
}
cJSON
*
webrtcMode
=
cJSON_GetObjectItem
(
moreInfo
,
"webrtcMode"
);
if
(
!
webrtcMode
||
!
cJSON_IsString
(
webrtcMode
))
{
cJSON_Delete
(
root
);
goto
cleanup
;
}
// 更新全局模式变量
strncpy
(
g_webrtc_mode
,
webrtcMode
->
valuestring
,
sizeof
(
g_webrtc_mode
)
-
1
);
g_webrtc_mode
[
sizeof
(
g_webrtc_mode
)
-
1
]
=
'\0'
;
// 3. 检查 webrtcMode
if
(
strcmp
(
webrtcMode
->
valuestring
,
"go"
)
==
0
)
{
// 检查 pip3 是否安装
check_and_install_pip3
();
cJSON
*
goUrl
=
cJSON_GetObjectItem
(
moreInfo
,
"goUrl"
);
cJSON
*
goHash
=
cJSON_GetObjectItem
(
moreInfo
,
"goHash"
);
if
(
!
goUrl
||
!
cJSON_IsString
(
goUrl
))
{
my_zlog_error
(
"goUrl is missing"
);
cJSON_Delete
(
root
);
goto
cleanup
;
}
int
need_download
=
0
;
// 4. 检查文件是否存在
if
(
access
(
target_file_path
,
F_OK
)
!=
0
)
{
my_zlog_info
(
"go_video file not found, downloading..."
);
need_download
=
1
;
}
else
{
// 5. 检查 Hash
if
(
goHash
&&
cJSON_IsString
(
goHash
))
{
char
local_hash
[
65
]
=
{
0
};
if
(
calculate_file_hash
(
target_file_path
,
local_hash
)
==
0
)
{
// 若服务器 hash 也是小写, 直接对比; 否则建议 strcasecmp
if
(
strcasecmp
(
local_hash
,
goHash
->
valuestring
)
!=
0
)
{
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."
);
}
}
else
{
my_zlog_error
(
"Failed to calculate local hash"
);
need_download
=
1
;
}
}
else
{
my_zlog_warn
(
"goHash is missing, skipping hash check"
);
// 可选择: 强制下载 或 不下载
// 这里通常如果不给 hash,如果文件存在假设是好的,或者强制覆盖?
// 但需求是 "不一样就下载",没说没 hash 怎么办。假设存在就不下?
// 还是安全起见没 hash 就不校验了
}
}
if
(
need_download
)
{
my_zlog_info
(
"Downloading from: %s"
,
goUrl
->
valuestring
);
if
(
download_file
(
goUrl
->
valuestring
,
target_file_path
)
==
0
)
{
my_zlog_info
(
"Download success."
);
// 下载后重新给权限
chmod
(
target_file_path
,
0777
);
}
else
{
my_zlog_error
(
"Download failed."
);
}
}
else
{
// 即使没下载,确认文件存在后也确保权限正确
if
(
access
(
target_file_path
,
F_OK
)
==
0
)
{
chmod
(
target_file_path
,
0777
);
}
// ---------------------------------------------------------
// 处理 video_proxy.7z
// ---------------------------------------------------------
cJSON
*
pythonUrl
=
cJSON_GetObjectItem
(
moreInfo
,
"pythonUrl"
);
if
(
pythonUrl
&&
cJSON_IsString
(
pythonUrl
)
&&
strlen
(
pythonUrl
->
valuestring
)
>
0
)
{
char
target_7z_path
[
512
];
snprintf
(
target_7z_path
,
sizeof
(
target_7z_path
),
"%s/video_proxy.7z"
,
target_dir
);
int
need_download_7z
=
0
;
// 检查文件是否存在
if
(
access
(
target_7z_path
,
F_OK
)
!=
0
)
{
my_zlog_info
(
"video_proxy.7z not found, need download."
);
need_download_7z
=
1
;
}
else
{
// 检查 Hash (使用 pythonHash)
cJSON
*
pythonHash
=
cJSON_GetObjectItem
(
moreInfo
,
"pythonHash"
);
if
(
pythonHash
&&
cJSON_IsString
(
pythonHash
))
{
char
local_hash
[
65
]
=
{
0
};
if
(
calculate_file_hash
(
target_7z_path
,
local_hash
)
==
0
)
{
if
(
strcasecmp
(
local_hash
,
pythonHash
->
valuestring
)
!=
0
)
{
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."
);
}
}
else
{
my_zlog_error
(
"Failed to calculate 7z local hash"
);
need_download_7z
=
1
;
}
}
else
{
my_zlog_warn
(
"goHash missing for 7z check"
);
}
}
if
(
need_download_7z
)
{
my_zlog_info
(
"Downloading 7z from: %s"
,
pythonUrl
->
valuestring
);
if
(
download_file
(
pythonUrl
->
valuestring
,
target_7z_path
)
==
0
)
{
my_zlog_info
(
"Download 7z success. Preparing to extract..."
);
// 检查 7z 是否安装
if
(
system
(
"which 7z > /dev/null 2>&1"
)
!=
0
)
{
my_zlog_info
(
"7z not found. Installing p7zip-full..."
);
// 尝试安装 p7zip-full (Ubuntu)
int
install_ret
=
system
(
"sudo apt-get update && sudo apt-get install -y p7zip-full"
);
if
(
install_ret
!=
0
)
{
my_zlog_error
(
"Failed to install p7zip-full, return code: %d"
,
install_ret
);
}
else
{
my_zlog_info
(
"p7zip-full installation completed successfully."
);
}
}
// 解压
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
);
int
extract_ret
=
system
(
cmd
);
if
(
extract_ret
==
0
)
{
my_zlog_info
(
"Extraction success."
);
}
else
{
my_zlog_error
(
"Extraction failed with code: %d"
,
extract_ret
);
}
}
else
{
my_zlog_error
(
"Download 7z failed."
);
}
}
}
}
}
cJSON_Delete
(
root
);
ret
=
0
;
cleanup:
curl_easy_cleanup
(
curl
);
free
(
chunk
.
memory
);
curl_global_cleanup
();
return
ret
;
}
modules/go_deploy/go_deploy.h
0 → 100644
View file @
6a503b14
#ifndef GO_DEPLOY_H
#define GO_DEPLOY_H
#ifdef __cplusplus
extern
"C"
{
#endif
/*
* 检查并更新/部署 Go 程序
* 返回值: 0 成功, -1 失败
*/
int
go_deploy_check_and_update
(
void
);
extern
char
g_webrtc_mode
[
32
];
#ifdef __cplusplus
}
#endif
#endif // GO_DEPLOY_H
modules/ipc/unix_socket_server.c
0 → 100644
View file @
6a503b14
#include "unix_socket_server.h"
#include "mqtt_infor_handle.h"
#include "mylog.h"
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#define IPC_SOCKET_PATH "/tmp/device_msg.sock"
#define IPC_BUFFER_SIZE 4096
static
int
g_ipc_server_fd
=
-
1
;
static
pthread_t
g_ipc_thread
;
static
int
g_ipc_running
=
0
;
static
void
*
ipc_server_thread
(
void
*
arg
);
int
ipc_start_unix_server
(
const
char
*
socket_path
)
{
if
(
g_ipc_running
)
{
return
0
;
}
const
char
*
path
=
socket_path
?
socket_path
:
IPC_SOCKET_PATH
;
g_ipc_server_fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
);
if
(
g_ipc_server_fd
<
0
)
{
my_zlog_error
(
"unix socket 创建失败"
);
return
-
1
;
}
struct
sockaddr_un
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
sun_family
=
AF_UNIX
;
strncpy
(
addr
.
sun_path
,
path
,
sizeof
(
addr
.
sun_path
)
-
1
);
unlink
(
path
);
if
(
bind
(
g_ipc_server_fd
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
))
<
0
)
{
my_zlog_error
(
"unix socket 绑定失败"
);
close
(
g_ipc_server_fd
);
g_ipc_server_fd
=
-
1
;
return
-
1
;
}
// 设置 socket 文件权限为 0777,允许所有用户读写
if
(
chmod
(
path
,
0777
)
<
0
)
{
my_zlog_warn
(
"设置 socket 文件权限失败"
);
}
if
(
listen
(
g_ipc_server_fd
,
5
)
<
0
)
{
my_zlog_error
(
"unix socket 监听失败"
);
close
(
g_ipc_server_fd
);
g_ipc_server_fd
=
-
1
;
return
-
1
;
}
g_ipc_running
=
1
;
if
(
pthread_create
(
&
g_ipc_thread
,
NULL
,
ipc_server_thread
,
(
void
*
)
path
)
!=
0
)
{
my_zlog_error
(
"unix socket 线程创建失败"
);
close
(
g_ipc_server_fd
);
g_ipc_server_fd
=
-
1
;
g_ipc_running
=
0
;
return
-
1
;
}
my_zlog_info
(
"IPC Unix socket 服务已启动: %s"
,
path
);
return
0
;
}
void
ipc_stop_unix_server
(
void
)
{
if
(
!
g_ipc_running
)
return
;
g_ipc_running
=
0
;
shutdown
(
g_ipc_server_fd
,
SHUT_RDWR
);
close
(
g_ipc_server_fd
);
g_ipc_server_fd
=
-
1
;
pthread_join
(
g_ipc_thread
,
NULL
);
}
static
void
*
ipc_server_thread
(
void
*
arg
)
{
char
buffer
[
IPC_BUFFER_SIZE
];
while
(
g_ipc_running
)
{
int
client_fd
=
accept
(
g_ipc_server_fd
,
NULL
,
NULL
);
if
(
client_fd
<
0
)
{
if
(
g_ipc_running
)
{
my_zlog_warn
(
"IPC accept 失败"
);
}
continue
;
}
ssize_t
len
=
read
(
client_fd
,
buffer
,
sizeof
(
buffer
)
-
1
);
if
(
len
>
0
)
{
buffer
[
len
]
=
'\0'
;
cJSON
*
root
=
cJSON_Parse
(
buffer
);
if
(
root
)
{
device_message_receive
(
root
);
cJSON_Delete
(
root
);
}
else
{
my_zlog_warn
(
"IPC 收到无效 JSON"
);
}
}
close
(
client_fd
);
}
return
NULL
;
}
\ No newline at end of file
modules/ipc/unix_socket_server.h
0 → 100644
View file @
6a503b14
#ifndef IPC_UNIX_SOCKET_SERVER_H
#define IPC_UNIX_SOCKET_SERVER_H
int
ipc_start_unix_server
(
const
char
*
socket_path
);
void
ipc_stop_unix_server
(
void
);
#endif
\ No newline at end of file
modules/mqtt/mqtt_infor_handle.c
View file @
6a503b14
...
...
@@ -5,240 +5,274 @@
#include "drivers_common.h"
#include "modules_common.h"
int
g_heartbeat_count
=
0
;
//
心跳计数
int
g_heartbeat_count
=
0
;
//
心跳计数
/*
*
*/
pthread_mutex_t
g_exit_count_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
//互斥锁
int
g_devcontrol_exit_count
=
0
;
*
*/
pthread_mutex_t
g_exit_count_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
// 互斥锁
int
g_devcontrol_exit_count
=
0
;
int
g_message_type
=
0
;
//
接收的mqtt的g_message_type
int
g_message_type
=
0
;
//
接收的mqtt的g_message_type
static
unsigned
char
g_valt
[
4
];
//
存放mqtt接收的tpye,mode等
static
unsigned
char
g_valt
[
4
];
//
存放mqtt接收的tpye,mode等
//心跳发送格式*5/2
void
heartbeat_send
()
{
// 心跳发送格式*5/2
void
heartbeat_send
()
{
static
double
voltage
;
static
double
current
;
voltage
=
ads1115_read_channel
(
0
)
*
5
/
2
;
current
=
ads1115_read_channel
(
1
)
*
5
/
2
;
current
=
(
current
-
voltage
)
*
10
;
voltage
=
ads1115_read_channel
(
0
)
*
5
/
2
;
current
=
ads1115_read_channel
(
1
)
*
5
/
2
;
current
=
(
current
-
voltage
)
*
10
;
my_zlog_debug
(
"v:%.2f"
,
voltage
);
my_zlog_debug
(
"i:%.2f"
,
current
);
char
voltage_str
[
20
];
// 足够存储转换后的字符串的缓冲区
sprintf
(
voltage_str
,
"%.2f"
,
voltage
);
char
current_str
[
20
];
// 足够存储转换后的字符串的缓冲区
sprintf
(
current_str
,
"%.2f"
,
current
);
if
(
g_devcontrol_exit_count
>
5
)
alarm_control
(
voltage
);
//判断电压警报,在不动时候才判断
char
voltage_str
[
20
];
// 足够存储转换后的字符串的缓冲区
sprintf
(
voltage_str
,
"%.2f"
,
voltage
);
char
current_str
[
20
];
// 足够存储转换后的字符串的缓冲区
sprintf
(
current_str
,
"%.2f"
,
current
);
if
(
g_devcontrol_exit_count
>
5
)
alarm_control
(
voltage
);
// 判断电压警报,在不动时候才判断
/*读取程序版本号*/
char
*
version_num
=
program_version
();
if
(
heat_tem
()
!=
0
)
{
//获取CPU温度
if
(
heat_tem
()
!=
0
)
{
// 获取CPU温度
my_zlog_debug
(
"获取cpu温度失败"
);
}
ipaddr_obtain
();
//
获取ip
int
message
=
1
;
ipaddr_obtain
();
//
获取ip
int
message
=
1
;
cJSON
*
root
=
cJSON_CreateObject
();
cJSON
*
body
=
cJSON_CreateObject
();
cJSON
*
head
=
cJSON_CreateObject
();
cJSON_AddStringToObject
(
body
,
"ip"
,
g_ip_address
);
//
发送设备ip
cJSON_AddStringToObject
(
body
,
"ID"
,
mqtt_topic_app2dev_number
());
//
发送设备号
cJSON_AddStringToObject
(
body
,
"V"
,
voltage_str
);
//
心跳发送电压
cJSON_AddStringToObject
(
body
,
"I"
,
current_str
);
//
心跳发送电流
cJSON_AddStringToObject
(
body
,
"Tem"
,
g_temperature
);
//
发送温度
cJSON_AddStringToObject
(
body
,
"version"
,
version_num
);
//
版本号
cJSON_AddStringToObject
(
body
,
"ip"
,
g_ip_address
);
//
发送设备ip
cJSON_AddStringToObject
(
body
,
"ID"
,
mqtt_topic_app2dev_number
());
//
发送设备号
cJSON_AddStringToObject
(
body
,
"V"
,
voltage_str
);
//
心跳发送电压
cJSON_AddStringToObject
(
body
,
"I"
,
current_str
);
//
心跳发送电流
cJSON_AddStringToObject
(
body
,
"Tem"
,
g_temperature
);
//
发送温度
cJSON_AddStringToObject
(
body
,
"version"
,
version_num
);
//
版本号
cJSON_AddNumberToObject
(
head
,
"message_type"
,
message
);
cJSON_AddNumberToObject
(
head
,
"message_type"
,
message
);
cJSON_AddItemToObject
(
root
,
"body"
,
body
);
cJSON_AddItemToObject
(
root
,
"head"
,
head
);
cJSON_AddItemToObject
(
root
,
"head"
,
head
);
char
*
payload
=
cJSON_PrintUnformatted
(
root
);
my_zlog_debug
(
"%s"
,
payload
);
for
(
int
i
=
0
;
i
<
g_mqtt_cam_config_t
->
mqtt_count
;
i
++
){
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
mqtt_topic_dev2app_number
(),
strlen
(
payload
),
payload
,
0
,
false
);
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
mqtt_topic_pure_number
(),
strlen
(
payload
),
payload
,
0
,
false
);
my_zlog_debug
(
"%s"
,
payload
);
for
(
int
i
=
0
;
i
<
g_mqtt_cam_config_t
->
mqtt_count
;
i
++
)
{
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
mqtt_topic_dev2app_number
(),
strlen
(
payload
),
payload
,
0
,
false
);
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
mqtt_topic_pure_number
(),
strlen
(
payload
),
payload
,
0
,
false
);
}
cJSON_Delete
(
root
);
// 释放 cJSON 对象
cJSON_Delete
(
root
);
// 释放 cJSON 对象
}
//角度发送
void
angle_mqtt_send
()
{
static
int
angle_i
=
0
;
// 角度发送
void
angle_mqtt_send
()
{
static
int
angle_i
=
0
;
cJSON
*
root
=
cJSON_CreateObject
();
char
TOPIC_send_angle
[
26
];
static
double
prev_angle
=
0
;
static
double
prev_angle
=
0
;
static
double
rounded_angle
;
rounded_angle
=
low_pass_filter_360
(
prev_angle
,
tank_angle
(),
0
.
7
);
sprintf
(
TOPIC_send_angle
,
"dev_rtinfo/%s"
,
mqtt_topic_pure_number
());
cJSON_AddStringToObject
(
root
,
"type"
,
"tank_angle"
);
if
(
rounded_angle
>
160
&&
rounded_angle
<
180
){
rounded_angle
=
160
;
}
else
if
(
rounded_angle
<
200
&&
rounded_angle
>
180
){
rounded_angle
=
200
;
rounded_angle
=
low_pass_filter_360
(
prev_angle
,
tank_angle
(),
0
.
7
);
sprintf
(
TOPIC_send_angle
,
"dev_rtinfo/%s"
,
mqtt_topic_pure_number
());
cJSON_AddStringToObject
(
root
,
"type"
,
"tank_angle"
);
if
(
rounded_angle
>
160
&&
rounded_angle
<
180
)
{
rounded_angle
=
160
;
}
cJSON_AddNumberToObject
(
root
,
"angle"
,
rounded_angle
);
else
if
(
rounded_angle
<
200
&&
rounded_angle
>
180
)
{
rounded_angle
=
200
;
}
cJSON_AddNumberToObject
(
root
,
"angle"
,
rounded_angle
);
char
*
payload
=
cJSON_PrintUnformatted
(
root
);
angle_i
++
;
if
(
angle_i
>=
10
){
my_zlog_debug
(
"%s"
,
payload
);
prev_angle
=
tank_angle
();
angle_i
=
0
;
if
(
angle_i
>=
10
)
{
my_zlog_debug
(
"%s"
,
payload
);
prev_angle
=
tank_angle
();
angle_i
=
0
;
}
if
(
fabs
(
rounded_angle
)
<
1e-8
){
if
(
fabs
(
rounded_angle
)
<
1e-8
)
{
cJSON_Delete
(
root
);
return
;
}
for
(
int
i
=
0
;
i
<
g_mqtt_cam_config_t
->
mqtt_count
;
i
++
){
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
TOPIC_send_angle
,
strlen
(
payload
),
payload
,
0
,
false
);
for
(
int
i
=
0
;
i
<
g_mqtt_cam_config_t
->
mqtt_count
;
i
++
)
{
mosquitto_publish
(
g_clients_t
[
i
].
mosq
,
NULL
,
TOPIC_send_angle
,
strlen
(
payload
),
payload
,
0
,
false
);
}
cJSON_Delete
(
root
);
// 释放 cJSON 对象
cJSON_Delete
(
root
);
// 释放 cJSON 对象
}
//心跳格式,每5s一次心跳
void
mqtt_beat_wirte
(){
// 心跳格式,每5s一次心跳
void
mqtt_beat_wirte
()
{
if
(
g_heartbeat_count
>=
30
)
{
if
(
g_heartbeat_count
>=
30
)
{
heartbeat_send
();
g_heartbeat_count
=
0
;
g_heartbeat_count
=
0
;
}
if
(
get_tank_angle_count
()
>
2
){
switch
(
g_device_type
)
{
case
DEVICE_TANK0202
:
case
DEVICE_TANK0203
:
case
DEVICE_TANK0204
:
angle_mqtt_send
();
break
;
default
:
break
;
if
(
get_tank_angle_count
()
>
2
)
{
switch
(
g_device_type
)
{
case
DEVICE_TANK0202
:
case
DEVICE_TANK0203
:
case
DEVICE_TANK0204
:
angle_mqtt_send
();
break
;
default:
break
;
}
set_tank_angle_count_clear
();
}
}
}
//message_type为3,控制pwm
void
message_3
(
cJSON
*
body
){
// message_type为3,控制pwm
void
message_3
(
cJSON
*
body
)
{
cJSON
*
pwm_ctrl
=
cJSON_GetObjectItem
(
body
,
"pwm_ctrl"
);
cJSON
*
pin_setctrl
=
cJSON_GetObjectItem
(
body
,
"pin_setctrl"
);
if
(
pwm_ctrl
==
NULL
||
pin_setctrl
==
NULL
){
return
;
if
(
pwm_ctrl
==
NULL
||
pin_setctrl
==
NULL
)
{
return
;
}
cJSON
*
mode
=
cJSON_GetObjectItem
(
pwm_ctrl
,
"mode"
);
//
mode=1 速度,mode=2 转向(unsigned char)
cJSON
*
mode
=
cJSON_GetObjectItem
(
pwm_ctrl
,
"mode"
);
//
mode=1 速度,mode=2 转向(unsigned char)
cJSON
*
type
=
cJSON_GetObjectItem
(
pwm_ctrl
,
"type"
);
cJSON
*
val
=
cJSON_GetObjectItem
(
pwm_ctrl
,
"val"
);
//
val为pwm的值 0~100(unsigned char)(unsigned char)
cJSON
*
val
=
cJSON_GetObjectItem
(
pwm_ctrl
,
"val"
);
//
val为pwm的值 0~100(unsigned char)(unsigned char)
unsigned
char
modeTemp
=
mode
->
valueint
;
unsigned
char
typeTemp
=
type
->
valueint
;
unsigned
char
valTemp
=
val
->
valueint
;
unsigned
char
modeTemp
=
mode
->
valueint
;
unsigned
char
typeTemp
=
type
->
valueint
;
unsigned
char
valTemp
=
val
->
valueint
;
g_valt
[
0
]
=
typeTemp
;
g_valt
[
1
]
=
modeTemp
;
g_valt
[
2
]
=
valTemp
;
g_valt
[
0
]
=
typeTemp
;
g_valt
[
1
]
=
modeTemp
;
g_valt
[
2
]
=
valTemp
;
my_zlog_debug
(
"typeTemp:%d"
,
g_valt
[
0
]);
my_zlog_debug
(
"modeTemp:%d"
,
g_valt
[
1
]);
my_zlog_debug
(
"valTemp:%d"
,
g_valt
[
2
]);
my_zlog_debug
(
"typeTemp:%d"
,
g_valt
[
0
]);
my_zlog_debug
(
"modeTemp:%d"
,
g_valt
[
1
]);
my_zlog_debug
(
"valTemp:%d"
,
g_valt
[
2
]);
device_walk_control
(
g_device_type
,
g_valt
);
device_walk_control
(
g_device_type
,
g_valt
);
}
void
message_4
(
cJSON
*
body
){
//message 为4时候
void
message_4
(
cJSON
*
body
)
{
// message 为4时候
cJSON
*
pwm_ctrl
=
cJSON_GetObjectItem
(
body
,
"pwm_ctrl"
);
cJSON
*
pin_setctrl
=
cJSON_GetObjectItem
(
body
,
"pin_setctrl"
);
if
(
pwm_ctrl
==
NULL
||
pin_setctrl
==
NULL
){
return
;
if
(
pwm_ctrl
==
NULL
||
pin_setctrl
==
NULL
)
{
return
;
}
cJSON
*
pin
=
cJSON_GetObjectItem
(
pin_setctrl
,
"pin"
);
cJSON
*
val
=
cJSON_GetObjectItem
(
pin_setctrl
,
"val"
);
//
val为pwm的值 0~100(unsigned char)(unsigned char)
unsigned
char
pinTemp
=
pin
->
valueint
;
cJSON
*
val
=
cJSON_GetObjectItem
(
pin_setctrl
,
"val"
);
//
val为pwm的值 0~100(unsigned char)(unsigned char)
unsigned
char
pinTemp
=
pin
->
valueint
;
unsigned
char
valTemp
=
val
->
valueint
;
if
(
valTemp
>=
1
){
valTemp
=
1
;
if
(
valTemp
>=
1
)
{
valTemp
=
1
;
}
g_valt
[
0
]
=
0
;
g_valt
[
1
]
=
pinTemp
;
g_valt
[
2
]
=
valTemp
;
g_valt
[
0
]
=
0
;
g_valt
[
1
]
=
pinTemp
;
g_valt
[
2
]
=
valTemp
;
my_zlog_debug
(
"pinTemp:%d"
,
g_valt
[
1
]);
my_zlog_debug
(
"valTemp:%d"
,
g_valt
[
2
]);
my_zlog_debug
(
"pinTemp:%d"
,
g_valt
[
1
]);
my_zlog_debug
(
"valTemp:%d"
,
g_valt
[
2
]);
device_gpio_control
(
g_device_type
,
g_valt
[
1
],
g_valt
[
2
]);
device_gpio_control
(
g_device_type
,
g_valt
[
1
],
g_valt
[
2
]);
tank_shot_stop_control
(
g_device_type
,
g_valt
[
1
],
g_valt
[
2
]);
tank_shot_stop_control
(
g_device_type
,
g_valt
[
1
],
g_valt
[
2
]);
}
//当接收到2时候验证
void
message_2_judyverify
(
cJSON
*
body
){
if
(
VERIFIED_MODE
==
FALSE
)
{
// 当接收到2时候验证
void
message_2_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
{
refresh_cam
();
my_zlog_warn
(
"不使用验证"
);
return
;
return
;
}
receive_jwt
(
body
);
if
(
g_verify_index
==
0
)
{
refresh_cam
();
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
if
(
g_verify_index
==
0
)
{
refresh_cam
();
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
}
//当接收到3时候验证
void
message_3_judyverify
(
cJSON
*
body
){
if
(
VERIFIED_MODE
==
FALSE
)
{
// 当接收到3时候验证
void
message_3_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
{
message_3
(
body
);
my_zlog_warn
(
"不使用验证"
);
return
;
return
;
}
receive_jwt
(
body
);
if
(
g_verify_index
==
0
)
{
message_3
(
body
);
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
if
(
g_verify_index
==
0
)
{
message_3
(
body
);
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
}
//当接收到4时候验证
void
message_4_judyverify
(
cJSON
*
body
){
if
(
VERIFIED_MODE
==
FALSE
)
{
// 当接收到4时候验证
void
message_4_judyverify
(
cJSON
*
body
)
{
if
(
VERIFIED_MODE
==
FALSE
)
{
message_4
(
body
);
my_zlog_warn
(
"不使用验证"
);
return
;
return
;
}
receive_jwt
(
body
);
if
(
g_verify_index
==
0
)
{
message_4
(
body
);
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
}
receive_jwt
(
body
);
if
(
g_verify_index
==
0
)
{
message_4
(
body
);
}
else
{
my_zlog_warn
(
"验证不通过"
);
}
}
//接收到设备改名函数
int
device_mqttchange_name
(
cJSON
*
device_id
){
cJSON
*
id
=
cJSON_GetObjectItem
(
device_id
,
"id"
);
// 提取ID
cJSON
*
date
=
cJSON_GetObjectItem
(
device_id
,
"date"
);
// 提取日期
char
*
device_change_id
=
id
->
valuestring
;
char
*
device_change_date
=
date
->
valuestring
;
device_changename_back
(
device_change_date
,
device_change_id
);
// 接收到设备改名函数
int
device_mqttchange_name
(
cJSON
*
device_id
)
{
cJSON
*
id
=
cJSON_GetObjectItem
(
device_id
,
"id"
);
// 提取ID
cJSON
*
date
=
cJSON_GetObjectItem
(
device_id
,
"date"
);
// 提取日期
char
*
device_change_id
=
id
->
valuestring
;
char
*
device_change_date
=
date
->
valuestring
;
device_changename_back
(
device_change_date
,
device_change_id
);
// 输出提取的数据
my_zlog_debug
(
"设备ID: %s"
,
device_change_id
);
my_zlog_debug
(
"日期: %s"
,
device_change_date
);
...
...
@@ -246,15 +280,19 @@ int device_mqttchange_name(cJSON *device_id){
return
0
;
}
int
device_message_receive
(
cJSON
*
json
){
//接收到的控制设备的mqtt消息
int
device_message_receive
(
cJSON
*
json
)
{
// 接收到的控制设备的mqtt消息
cJSON
*
head
=
cJSON_GetObjectItem
(
json
,
"head"
);
cJSON
*
message_type
=
cJSON_GetObjectItem
(
head
,
"message_type"
);
if
(
cJSON_IsObject
(
head
)
&&
cJSON_IsNumber
(
message_type
))
{;
cJSON
*
body
=
cJSON_GetObjectItem
(
json
,
"body"
);
//提取 body数据段
if
(
!
cJSON_IsObject
(
body
))
{
if
(
cJSON_IsObject
(
head
)
&&
cJSON_IsNumber
(
message_type
))
{
;
cJSON
*
body
=
cJSON_GetObjectItem
(
json
,
"body"
);
// 提取 body数据段
if
(
!
cJSON_IsObject
(
body
))
{
return
1
;
}
...
...
@@ -262,94 +300,101 @@ int device_message_receive(cJSON *json){//接收到的控制设备的mqtt消息
g_devcontrol_exit_count
=
0
;
pthread_mutex_unlock
(
&
g_exit_count_mutex
);
g_message_type
=
message_type
->
valueint
;
my_zlog_debug
(
"message_type: %d"
,
message_type
->
valueint
);
switch
(
g_message_type
){
case
2
:
message_2_judyverify
(
body
);
my_zlog_debug
(
"进入刷新"
);
break
;
case
3
:
message_3_judyverify
(
body
);
set_self_control_index
(
false
);
my_zlog_debug
(
"进入pwm控制"
);
break
;
case
4
:
message_4_judyverify
(
body
);
set_self_control_index
(
false
);
my_zlog_debug
(
"进入引脚控制"
);
break
;
case
5
:
audio_wheat_init
();
audio_speaker_init
();
my_zlog_debug
(
"执行麦和喇叭命令"
);
break
;
case
2001
:
audioplay_mqtt_receive
(
body
);
my_zlog_debug
(
"进入音频播放"
);
break
;
case
2002
:
device_mqttchange_name
(
body
);
my_zlog_debug
(
"进入修改设备号"
);
break
;
case
2003
:
scan_wifi_json
();
my_zlog_debug
(
"进入查询WiFi"
);
break
;
case
2004
:
//wifi_change_recmqtt(body);
my_zlog_debug
(
"进入修改WiFi"
);
break
;
case
2006
:
message2006_verify
(
body
);
my_zlog_debug
(
"进入消息为2006验证"
);
break
;
case
2007
:
device_send_saved_wifi
();
my_zlog_debug
(
"查询已保存wifi和现在已连接WiFi"
);
break
;
case
2008
:
device_wifi_rec_sava
(
body
);
my_zlog_debug
(
"保存wifi"
);
break
;
case
2009
:
device_wifi_rec_delete
(
body
);
my_zlog_debug
(
"删除已保存wifi"
);
break
;
case
2011
:
int
res
=
system
(
"sudo reboot"
);
//重启香橙派
if
(
res
==
0
)
my_zlog_debug
(
"重启成功"
);
break
;
case
2012
:
refresh_cam
();
my_zlog_debug
(
"刷新成功"
);
break
;
case
2013
:
message2013_recverigy_open
(
body
);
my_zlog_debug
(
"进入是否需要验证"
);
break
;
case
2014
:
control_pthread_function
(
"open"
);
my_zlog_debug
(
"打开控制台推送"
);
break
;
case
2015
:
control_pthread_function
(
"close"
);
my_zlog_debug
(
"关闭控制台推送"
);
break
;
case
2025
:
receive_self_contorl_mqtt
(
body
);
my_zlog_debug
(
"device self comtrol"
);
break
;
case
2026
:
receive_self_contorl_date_mqtt
(
body
);
my_zlog_info
(
"device self comtrol date save"
);
case
2027
:
mqtt_audio_tts
(
body
);
my_zlog_info
(
"device audio_tts"
);
default
:
break
;
g_message_type
=
message_type
->
valueint
;
my_zlog_debug
(
"message_type: %d"
,
message_type
->
valueint
);
switch
(
g_message_type
)
{
case
2
:
message_2_judyverify
(
body
);
my_zlog_debug
(
"进入刷新"
);
break
;
case
3
:
message_3_judyverify
(
body
);
set_self_control_index
(
false
);
my_zlog_debug
(
"进入pwm控制"
);
break
;
case
4
:
message_4_judyverify
(
body
);
set_self_control_index
(
false
);
my_zlog_debug
(
"进入引脚控制"
);
break
;
case
5
:
audio_wheat_init
();
audio_speaker_init
();
my_zlog_debug
(
"执行麦和喇叭命令"
);
break
;
case
2001
:
audioplay_mqtt_receive
(
body
);
my_zlog_debug
(
"进入音频播放"
);
break
;
case
2002
:
device_mqttchange_name
(
body
);
my_zlog_debug
(
"进入修改设备号"
);
break
;
case
2003
:
scan_wifi_json
();
my_zlog_debug
(
"进入查询WiFi"
);
break
;
case
2004
:
// wifi_change_recmqtt(body);
my_zlog_debug
(
"进入修改WiFi"
);
break
;
case
2006
:
message2006_verify
(
body
);
my_zlog_debug
(
"进入消息为2006验证"
);
break
;
case
2007
:
device_send_saved_wifi
();
my_zlog_debug
(
"查询已保存wifi和现在已连接WiFi"
);
break
;
case
2008
:
device_wifi_rec_sava
(
body
);
my_zlog_debug
(
"保存wifi"
);
break
;
case
2009
:
device_wifi_rec_delete
(
body
);
my_zlog_debug
(
"删除已保存wifi"
);
break
;
case
2011
:
int
res
=
system
(
"sudo reboot"
);
// 重启香橙派
if
(
res
==
0
)
my_zlog_debug
(
"重启成功"
);
break
;
case
2012
:
refresh_cam
();
my_zlog_debug
(
"刷新成功"
);
break
;
case
2013
:
message2013_recverigy_open
(
body
);
my_zlog_debug
(
"进入是否需要验证"
);
break
;
case
2014
:
control_pthread_function
(
"open"
);
my_zlog_debug
(
"打开控制台推送"
);
break
;
case
2015
:
control_pthread_function
(
"close"
);
my_zlog_debug
(
"关闭控制台推送"
);
break
;
case
2025
:
receive_self_contorl_mqtt
(
body
);
my_zlog_debug
(
"device self comtrol"
);
break
;
case
2026
:
receive_self_contorl_date_mqtt
(
body
);
my_zlog_info
(
"device self comtrol date save"
);
case
2027
:
mqtt_audio_tts
(
body
);
my_zlog_info
(
"device audio_tts"
);
case
2028
:
tailscale_control
(
body
);
my_zlog_info
(
"tailscale control"
);
default:
break
;
}
}
else
return
3
;
}
else
return
3
;
return
0
;
}
modules/tailscale_deploy/tailscale_deploy.c
0 → 100644
View file @
6a503b14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cJSON.h>
#include "tailscale_deploy.h"
#include "common.h"
int
tailscale_control
(
cJSON
*
body
)
{
if
(
body
==
NULL
)
{
my_zlog_error
(
"tailscale_control: body is NULL"
);
return
-
1
;
}
cJSON
*
authkey_json
=
cJSON_GetObjectItem
(
body
,
"authkey"
);
if
(
!
cJSON_IsString
(
authkey_json
)
||
(
authkey_json
->
valuestring
==
NULL
))
{
my_zlog_error
(
"tailscale_control: authkey is missing or invalid"
);
return
-
2
;
}
char
*
authkey
=
authkey_json
->
valuestring
;
if
(
strcmp
(
authkey
,
"stop"
)
==
0
)
{
my_zlog_info
(
"tailscale_control: Stopping Tailscale..."
);
// 尝试停止 tailscale并捕获输出
FILE
*
fp
=
popen
(
"sudo tailscale down 2>&1"
,
"r"
);
if
(
fp
!=
NULL
)
{
char
buf
[
256
];
while
(
fgets
(
buf
,
sizeof
(
buf
),
fp
)
!=
NULL
)
{
// 去除换行符让日志更整洁
size_t
len
=
strlen
(
buf
);
if
(
len
>
0
&&
buf
[
len
-
1
]
==
'\n'
)
buf
[
len
-
1
]
=
'\0'
;
my_zlog_info
(
"tailscale output: %s"
,
buf
);
}
int
ret
=
pclose
(
fp
);
if
(
WEXITSTATUS
(
ret
)
==
0
)
{
my_zlog_info
(
"tailscale_control: Tailscale stopped successfully"
);
}
else
{
my_zlog_error
(
"tailscale_control: Failed to stop Tailscale, ret=%d"
,
WEXITSTATUS
(
ret
));
return
-
3
;
}
}
else
{
my_zlog_error
(
"tailscale_control: Failed to execute stop command"
);
return
-
3
;
}
}
else
{
// 检查 tailscale 是否安装
if
(
system
(
"which tailscale > /dev/null 2>&1"
)
!=
0
)
{
my_zlog_info
(
"tailscale_control: Tailscale not found. Installing..."
);
// 安装 tailscale
int
install_ret
=
system
(
"curl -fsSL https://tailscale.com/install.sh | sh"
);
if
(
install_ret
!=
0
)
{
my_zlog_error
(
"tailscale_control: Failed to install Tailscale, ret=%d"
,
install_ret
);
return
-
4
;
}
// 用户要求不开机自启,因此先 disable
system
(
"sudo systemctl disable tailscaled > /dev/null 2>&1"
);
my_zlog_info
(
"tailscale_control: Tailscale installed successfully"
);
}
// 确保服务已启动
system
(
"sudo systemctl start tailscaled > /dev/null 2>&1"
);
// 启动 tailscale
char
cmd
[
512
];
snprintf
(
cmd
,
sizeof
(
cmd
),
"sudo tailscale up --authkey %s --hostname orangepi-01 2>&1"
,
authkey
);
my_zlog_info
(
"tailscale_control: Starting Tailscale..."
);
FILE
*
fp_up
=
popen
(
cmd
,
"r"
);
if
(
fp_up
!=
NULL
)
{
char
buf
[
256
];
while
(
fgets
(
buf
,
sizeof
(
buf
),
fp_up
)
!=
NULL
)
{
size_t
len
=
strlen
(
buf
);
if
(
len
>
0
&&
buf
[
len
-
1
]
==
'\n'
)
buf
[
len
-
1
]
=
'\0'
;
my_zlog_info
(
"tailscale up output: %s"
,
buf
);
}
int
start_ret
=
pclose
(
fp_up
);
if
(
WEXITSTATUS
(
start_ret
)
==
0
)
{
my_zlog_info
(
"tailscale_control: Tailscale started successfully"
);
}
else
{
my_zlog_error
(
"tailscale_control: Failed to start Tailscale, ret=%d"
,
WEXITSTATUS
(
start_ret
));
return
-
5
;
}
}
else
{
my_zlog_error
(
"tailscale_control: Failed to execute start command"
);
return
-
5
;
}
}
return
0
;
}
modules/tailscale_deploy/tailscale_deploy.h
0 → 100644
View file @
6a503b14
#ifndef TAILSCALE_DEPLOY_H
#define TAILSCALE_DEPLOY_H
#include <cJSON.h>
int
tailscale_control
(
cJSON
*
body
);
#endif
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