Commit 6a503b14 authored by DESKTOP-MC5UL36\dell's avatar DESKTOP-MC5UL36\dell

可以发送mqtt开启关闭tailscale vpn, unix_server,go程序更新和根据后台配置开启go视频或浏览器

parent b77cdb0a
......@@ -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
......
#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
......@@ -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);
}
}
......@@ -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
#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;
}
#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
#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
#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
......@@ -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;
}
#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;
}
#ifndef TAILSCALE_DEPLOY_H
#define TAILSCALE_DEPLOY_H
#include <cJSON.h>
int tailscale_control(cJSON *body);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment