Commit 6d5a6a99 authored by 学习的菜鸟's avatar 学习的菜鸟

mqtt重写,音频测试完成,WiFi扫描未测试,换连WiFi已完成大半

parent 37fcaa35
cmake_minimum_required(VERSION 3.10)
project(DeviceControlSystem
VERSION 1.1.6
VERSION 1.1.7
LANGUAGES C
)
......
......@@ -640,6 +640,30 @@ src/thread_main.c.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/thread_main.c.s
.PHONY : src/thread_main.c.s
src/wifichange.o: src/wifichange.c.o
.PHONY : src/wifichange.o
# target to build an object file
src/wifichange.c.o:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/wifichange.c.o
.PHONY : src/wifichange.c.o
src/wifichange.i: src/wifichange.c.i
.PHONY : src/wifichange.i
# target to preprocess a source file
src/wifichange.c.i:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/wifichange.c.i
.PHONY : src/wifichange.c.i
src/wifichange.s: src/wifichange.c.s
.PHONY : src/wifichange.s
# target to generate assembly for a file
src/wifichange.c.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/wifichange.c.s
.PHONY : src/wifichange.c.s
system/gpio/gpio_common.o: system/gpio/gpio_common.c.o
.PHONY : system/gpio/gpio_common.o
......@@ -1503,6 +1527,9 @@ help:
@echo "... src/thread_main.o"
@echo "... src/thread_main.i"
@echo "... src/thread_main.s"
@echo "... src/wifichange.o"
@echo "... src/wifichange.i"
@echo "... src/wifichange.s"
@echo "... system/gpio/gpio_common.o"
@echo "... system/gpio/gpio_common.i"
@echo "... system/gpio/gpio_common.s"
......
#define PROJECT_VERSION_MAJOR 1
#define PROJECT_VERSION_MINOR 1
#define PROJECT_VERSION_PATCH 6
#define PROJECT_VERSION_PATCH 7
#define GIT_HASH ""
#define BUILD_TIMESTAMP "2025-06-03T10:33:26"
#define BUILD_TIMESTAMP "2025-06-05T10:05:06"
#define BUILD_USER "orangepi"
No preview for this file type
......@@ -13,6 +13,7 @@
char TOPIC_middle[23];
char TOPIC2_middle[23];
char TOPIC3_middle[15];
char TOPIC4_middle[23];
bool device_name_exists=0;
......@@ -24,6 +25,7 @@ void topic_middle_value() {//指针中转函数,在使用指针前调用
TOPIC=TOPIC_middle;
TOPIC2=TOPIC2_middle;
TOPIC3=TOPIC3_middle;
TOPIC4=TOPIC4_middle;
}
// void topic_back_middle_value() {//指针中转函数,在使用指针前调用
......@@ -145,10 +147,12 @@ int Device_File_Init() {//设备文件读取函数
sprintf(TOPIC2_middle,"dev2app/%s",readbuf);
sprintf(TOPIC_middle,"app2dev/%s",readbuf);
sprintf(TOPIC3_middle,"%s",readbuf);
sprintf(TOPIC4_middle,"ser2dev/%s",readbuf);
} else {
sprintf(TOPIC2_middle,"dev2app/%s","00000000000000");
sprintf(TOPIC_middle,"app2dev/%s","00000000000000");
sprintf(TOPIC3_middle,"%s","00000000000000");
sprintf(TOPIC4_middle,"ser2dev/%s","00000000000000");
}
......
......@@ -2,8 +2,8 @@
#define AUDIOPLAY_H
#include <cjson/cJSON.h>
extern int audio_status;
// extern int audio_status;
void audioplay_mqtt_receive(cJSON *json) ;
void audioplay_cycle();
void audioplay_mqtt_receive(cJSON *body); //接收音频mqtt播放函数
void audioplay_cycle();//音频播放线程中函数
#endif
\ No newline at end of file
......@@ -7,6 +7,7 @@
extern char* TOPIC;
extern char* TOPIC2;
extern char* TOPIC3;
extern char* TOPIC4;
extern char* TOPIC_BACK;
extern char* TOPIC2_BACK;
......@@ -27,11 +28,11 @@ extern int gPwmCount; // 计数
extern int gmessage_type;//message消息值
int mqtt_init();//mqtt初始化
void mqtt_create(struct mosquitto *mosq);//创建mqtt客服端
int mqtt_create(struct mosquitto *mosq);//创建mqtt客服端
void on_connect(struct mosquitto *mosq, void *obj, int rc);//回调函数
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message);//消息回调函数
void mqtt_wirte();//发送mqtt,现为心跳
void mqtt_cycle(struct mosquitto *mosq);//循环
int mqtt_cycle(struct mosquitto *mosq);//循环
void mqtt_clean(struct mosquitto *mosq);//清理
#endif
\ No newline at end of file
......@@ -11,7 +11,7 @@ void *Mqttbeat(void *arg) ;//心跳线程
void *opensh(void *arg) ;//启动游览器线程
void *Mqtt_onnect(void *arg) ;//mqtt自带重连线程
void *delay_count(void *arg) ;//延时计算延迟
void *play_mp3_thread(void* arg);
void *play_mp3_thread(void* arg);//等待播放音频线程
void thread_end() ;
#endif
\ No newline at end of file
#ifndef WIFICHANGE_H__
#define WIFICHANGE_H__
#define SSID_MAX_LEN 128
#define PASS_MAX_LEN 128
#define CMD_BUFFER_SIZE 256
#define MAX_WIFI_LIST 100
#define default_SSID jking
#define default_password 12345678
#define WIFI_CONF_PATH "/home/orangepi/car/master/device_wifi.conf"
typedef struct {
char ssid[SSID_MAX_LEN];
int signal;
} wifi_info_t;
void scan_wifi_json();//显示以连接WiFi名称和周围已有的WiFi和过滤信号强度低于50的WiFi
int delete_wifi_by_ssid(const char* ssid);//忘记指定的WiFi的密码
#endif
\ No newline at end of file
......@@ -3,7 +3,7 @@
#include "mqtt.h"
#include "judg.h"
int audio_status=3;
int audio_status=7;
char urlbuf[512];
char keybuf[256];
double audio_volume=0.8;
......@@ -26,7 +26,8 @@ void audioplay_mqtt_receive(cJSON *json) {
char *key=key_char->valuestring;
snprintf(keybuf, sizeof(keybuf), "%s", key);
} else {
my_zlog_warn("错误:无法解析密钥字段\n");
my_zlog_warn("错误:无法解析音频链接");
audio_status=5;
}
// 解析"status"字段
......@@ -48,16 +49,21 @@ void audioplay_mqtt_receive(cJSON *json) {
}
}
void audioplay_send_mqtt() {
cJSON* root = cJSON_CreateObject();
void audioplay_send_mqtt() {//发送音频播放是否完毕
cJSON *root = cJSON_CreateObject();
cJSON *body = cJSON_CreateObject();
cJSON *head = cJSON_CreateObject();
// 添加各个字段到 JSON 对象
cJSON_AddStringToObject(root, "type", "audio");
cJSON_AddStringToObject(root, "audioLink", urlbuf);
cJSON_AddStringToObject(root, "key", keybuf);
cJSON_AddNumberToObject(root, "status", audio_status);
cJSON_AddNumberToObject(root, "volume", audio_volume);
cJSON_AddStringToObject(body, "type", "audio");
cJSON_AddStringToObject(body, "audioLink", urlbuf);
cJSON_AddStringToObject(body, "key", keybuf);
cJSON_AddNumberToObject(body, "status", audio_status);
cJSON_AddNumberToObject(body, "volume", audio_volume);
cJSON_AddNumberToObject(head, "message_type",3001);
cJSON_AddItemToObject(root, "body", body);
cJSON_AddItemToObject(root, "head",head);
// 将 JSON 对象转换为字符串
char* json_string = cJSON_PrintUnformatted(root);
my_zlog_debug("%s",json_string);
......@@ -85,15 +91,14 @@ void audioplay_cycle(){
}
if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) {
my_zlog_debug("播放已成功完成 : %s \n", urlbuf);
my_zlog_debug("播放已成功完成 : %s ", urlbuf);
audio_status=1;
audioplay_send_mqtt();
} else {
my_zlog_warn("播放失败或中断: %s \n", urlbuf);
my_zlog_warn("播放失败或中断: %s ", urlbuf);
audio_status=2;
}
audioplay_send_mqtt();
}
}
}
\ No newline at end of file
......@@ -15,7 +15,7 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, voi
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(!ptr) {
my_zlog_warn("not enough memory (realloc returned NULL)\n");
my_zlog_warn("not enough memory (realloc returned NULL)");
return 0;
}
......
This diff is collapsed.
......@@ -13,6 +13,8 @@
pthread_t thread[6]; // 全局线程句柄数组(或传参)
int grc=0;
void* args[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
int thread_start(ThreadFunc AppExit, ThreadFunc Mqttbeat,
......@@ -60,13 +62,14 @@ void *Mqttbeat(void *arg) {
my_zlog_info("Mqttbeat start");
Delay_Ms(15,0);
while(1) {
ipaddr();//获取ip
if( AppExit_pin_pwm == 202) Delay_Ms(0,45);
if( AppExit_pin_pwm != 202) Delay_Ms(0,100);
heartbeat_count++;
if(grc == 0){
ipaddr();//获取ip
mqtt_wirte();//心跳,3s一个
}
if(heartbeat_count>=30) heartbeat_count=0;
}
return NULL;
}
......@@ -81,11 +84,35 @@ void *opensh(void *arg) {
void *Mqtt_onnect(void *arg) {//mqtt异常处理,断开自动重连,简单粗暴
Delay_Ms(5,0);
mqtt_init();//mqtt初始化
mqtt_create(mosq);//创建mqtt客户端
while(1){
mqtt_create(mosq);//创建mqtt客户端
mqtt_cycle(mosq); //进入mqtt死循环,异常退出继续执行while
if (mqtt_init() != 0) {
my_zlog_fatal("mqtt_init failed");
return NULL;
}
while (1) {
if (mosq == NULL) {
mqtt_init();
if (!mosq) {
mqtt_clean(mosq);
my_zlog_error("Failed to create mosquitto client");
continue;
}
}
grc = mqtt_create(mosq);
if (grc != 0) {
mqtt_clean(mosq);
mosq = NULL;
continue;
}
grc = mqtt_cycle(mosq); // 阻塞直到断开
if(grc !=0 ){
mqtt_clean(mosq);
mosq = NULL;
}
my_zlog_warn("mqtt disconnected ...");
}
mqtt_clean(mosq);
return NULL;
......
#include <cjson/cJSON.h>
#include "wifichange.h"
#include "mqtt.h"
#include "common.h"
#include "judg.h"
char current_ssid[SSID_MAX_LEN] = {0};//用于存现在已连接WiFi
int find_ssid(wifi_info_t list[], int count, const char *ssid) {//找重复的WiFi名称
for (int i = 0; i < count; i++) {
if (strcmp(list[i].ssid, ssid) == 0) {
return i;
}
}
return -1;
}
int cmp_signal_desc(const void *a, const void *b) {//进行qsort前,此未降序操作
wifi_info_t *wa = (wifi_info_t *)a;
wifi_info_t *wb = (wifi_info_t *)b;
return wb->signal - wa->signal;
}
void get_current_wifi() {
//显示已连接代码
FILE *fp = popen("nmcli -t -f ACTIVE,SSID dev wifi", "r");
if (!fp) {
my_zlog_error("{\"error\": \"无法执行扫描命令\"}");
return;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
char *active = strtok(line, ":");
char *ssid = strtok(NULL, "\n");
if (active && ssid && strcmp(active, "yes") == 0 && strlen(ssid) > 0) {
strncpy(current_ssid, ssid, SSID_MAX_LEN - 1);
current_ssid[SSID_MAX_LEN - 1] = '\0';
break;
}
}
pclose(fp);
}
void scan_wifi_json() { //显示以连接WiFi名称和周围已有的WiFi和过滤信号强度低于50的WiFi
get_current_wifi();
char line[100];
//显示WiFi名称与信号强度
FILE *fp = popen("nmcli -t -f SSID,SIGNAL dev wifi list", "r");
if (!fp) {
my_zlog_error("{\"error\": \"无法执行扫描命令\"}");
return;
}
wifi_info_t wifi_list[MAX_WIFI_LIST];
int wifi_count = 0;
while (fgets(line, sizeof(line), fp)) {
char *ssid = strtok(line, ":");
char *signal_str = strtok(NULL, "\n");
if (!ssid || !signal_str) continue;
if (strlen(ssid) == 0) continue;
int signal = atoi(signal_str);
int idx = find_ssid(wifi_list, wifi_count, ssid);//去重 + 只保留信号最强的
if (idx == -1) {
if (wifi_count < MAX_WIFI_LIST) {
strncpy(wifi_list[wifi_count].ssid, ssid, SSID_MAX_LEN - 1);
wifi_list[wifi_count].ssid[SSID_MAX_LEN - 1] = '\0';
wifi_list[wifi_count].signal = signal;
wifi_count++;
}
} else {
if (signal > wifi_list[idx].signal) {
wifi_list[idx].signal = signal;
}
}
}
pclose(fp);
qsort(wifi_list, wifi_count, sizeof(wifi_info_t), cmp_signal_desc);//通过信号强度进行排序
//将WiFi信息转化为json格式
cJSON *root = cJSON_CreateObject();
cJSON *body = cJSON_CreateObject();
cJSON *head = cJSON_CreateObject();
cJSON_AddStringToObject(body, "current_connected", current_ssid[0] ? current_ssid : "");
cJSON *array = cJSON_CreateArray();
for (int i = 0; i < wifi_count; i++) {
if (wifi_list[i].signal < 50) continue; // 过滤信号小于50的
cJSON *item = cJSON_CreateObject();
cJSON_AddStringToObject(item, "ssid", wifi_list[i].ssid);
cJSON_AddNumberToObject(item, "strength", wifi_list[i].signal);
cJSON_AddItemToArray(array, item);
}
cJSON_AddItemToObject(body, "available_wifi", array);
cJSON_AddNumberToObject(head, "message_type", 3003);
cJSON_AddItemToObject(root, "body", body);
cJSON_AddItemToObject(root, "head",head);
char *json_str = cJSON_Print(root);
if (json_str) {
my_zlog_debug("%s", json_str);
topic_middle_value();
mosquitto_publish(mosq, NULL, TOPIC3, strlen(json_str), json_str, 0, false);
free(json_str);
}
cJSON_Delete(root);
}
int connect_wifi(const char* ssid, const char* password) {//连接WiFi
char cmd[CMD_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "nmcli dev wifi connect '%s' password '%s' 2>&1", ssid, password);
my_zlog_debug("🔌 正在连接 Wi-Fi:%s...", ssid);
FILE *fp = popen(cmd, "r");
if (!fp) {
my_zlog_warn("❌ 无法执行连接命令。");
return -1;
}
char output[512] = {0};
fread(output, 1, sizeof(output) - 1, fp);
pclose(fp);
if (strstr(output, "successfully activated")) {
my_zlog_debug("✅ 已成功连接到:%s", ssid);
return 0;
} else if (strstr(output, "No network with SSID")) {
my_zlog_warn("❌ 连接失败:Wi-Fi '%s' 不存在。", ssid);
return -2;
} else if (strstr(output, "Secrets were required") || strstr(output, "incorrect password")) {
my_zlog_warn("❌ 连接失败:密码错误。");
return -3;
} else {
my_zlog_error("❌ 连接失败,未知错误:%s", output);
return -4;
}
}
int connect_wifi_with_fallback(const char* ssid, const char* password, const char* fallback_ssid) {//如果连接失败则回退
int ret = connect_wifi(ssid, password);
if (ret != 0 && fallback_ssid && fallback_ssid[0] != 0) {
my_zlog_warn("⚠️ 连接失败,尝试回退连接原Wi-Fi:%s", fallback_ssid);
char cmd[CMD_BUFFER_SIZE];
snprintf(cmd, sizeof(cmd), "nmcli dev wifi connect '%s' 2>&1", fallback_ssid);
FILE *fp = popen(cmd, "r");
if (fp) {
char output[512] = {0};
fread(output, 1, sizeof(output) - 1, fp);
pclose(fp);
if (strstr(output, "successfully activated")) {
my_zlog_debug("✅ 回退连接成功:%s", fallback_ssid);
} else {
my_zlog_warn("❌ 回退连接失败:%s", output);
}
} else {
my_zlog_error("❌ 无法执行回退连接命令。");
}
}
return ret;
}
int change_wifi_connect(const char *wifi_ssid, const char *wifi_password) {//改变WiFi连接
get_current_wifi(current_ssid, sizeof(current_ssid));
int ret = connect_wifi_with_fallback(wifi_ssid, wifi_password, current_ssid);
my_zlog_notice("返回代码:%d", ret);
return ret;
}
int can_access_internet() {//测试网络是否连接成功
int ret = system("ping -c 1 -W 1 baidu.com > /dev/null 2>&1");
return ret == 0; // 返回 0 表示 ping 成功
}
int delete_wifi_by_ssid(const char* ssid) {//删除对应wifi
if (ssid == NULL || strlen(ssid) == 0) {
fprintf(stderr, "SSID is empty.");
return -1;
}
char command[256];
// 构造 nmcli 删除连接命令
snprintf(command, sizeof(command), "nmcli -t -f NAME,TYPE connection show | grep '^%s:wifi$' | cut -d: -f1", ssid);
// 打开管道读取匹配到的连接名
FILE* fp = popen(command, "r");
if (!fp) {
perror("popen failed");
return -1;
}
char conn_name[128];
if (fgets(conn_name, sizeof(conn_name), fp) == NULL) {
my_zlog_debug("No matching WiFi connection found for SSID: %s", ssid);
pclose(fp);
return -1;
}
pclose(fp);
// 去除末尾换行符
conn_name[strcspn(conn_name, "\n")] = 0;
// 构造删除命令
snprintf(command, sizeof(command), "nmcli connection delete \"%s\"", conn_name);
int ret = system(command);
if (ret == 0) {
my_zlog_debug("Successfully deleted WiFi connection: %s", conn_name);
} else {
my_zlog_warn("Failed to delete WiFi connection: %s", conn_name);
}
return ret;
}
// 检查文件是否存在,不存在则创建
int check_or_create_wifi_conf() {
struct stat st;
if (stat(WIFI_CONF_PATH, &st) == 0) {
// 文件已存在
return 0;
}
// 创建空配置文件
FILE *fp = fopen(WIFI_CONF_PATH, "w");
if (!fp) {
perror("Failed to create device_wifi.conf");
return -1;
}
fclose(fp);
return 0;
}
// 写入 SSID 和密码到文件
int write_wifi_conf(const char *ssid, const char *password) {
FILE *fp = fopen(WIFI_CONF_PATH, "w");
if (!fp) {
perror("Failed to open device_wifi.conf for writing");
return -1;
}
fprintf(fp, "SSID=%s\n", ssid);
fprintf(fp, "PASSWORD=%s\n", password);
fclose(fp);
return 0;
}
// 从文件读取 SSID,比较当前连接的 WiFi 名称
int compare_ssid_with_file() {
char file_ssid[128] = {0};
FILE *fp = fopen(WIFI_CONF_PATH, "r");
if (!fp) {
perror("Failed to open device_wifi.conf");
return -1;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (strncmp(line, "SSID=", 5) == 0) {
strncpy(file_ssid, line + 5, sizeof(file_ssid) - 1);
file_ssid[strcspn(file_ssid, "\n")] = 0;
break;
}
}
fclose(fp);
get_current_wifi();
my_zlog_debug("File SSID: %s", file_ssid);
my_zlog_debug("Current SSID: %s", current_ssid);
if (strcmp(file_ssid, current_ssid) == 0) {
my_zlog_debug("WiFi matches the config file.");
return 1;
} else {
my_zlog_debug("WiFi does NOT match the config file.");
return 0;
}
}
\ No newline at end of file
......@@ -11,10 +11,6 @@ extern int device_delay_count;//延时计算函数,使用前必须置0
#define PWM_PIN_SPEED 21
#define PWM_PIN_CHANGE 2
void Device_exit_end();//main最后结束需要调用的函数
void init_gpioWPi(int *values_pin);//gpio引脚初始化
void init_gpioPwm(int *values_pwm);
......@@ -27,4 +23,6 @@ void pin_value(int pin,int value);
void pwm_init_speed();
void pwm_value(int pin,int value); //软件陪我们控制调速
void Device_exit_end();//main最后结束需要调用的函数
#endif
......@@ -212,7 +212,7 @@ long long get_current_time_millis() {
return (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
void tank_shot_back_stop_task_function(void *arg) {
void tank_shot_back_stop_task_function(void *arg) {//多线程处理坦克发射后退线程池
while(1){
long long interval=shot_device_time_start-shot_device_time_end;
if(device_delay_count>10&&device_delay_count<=25) mode_right_back(0);
......@@ -224,6 +224,7 @@ void tank_shot_back_stop_task_function(void *arg) {
}
}
free(arg);
}
ThreadPool *pool_tank;
......@@ -231,6 +232,14 @@ void tank_shot_back_stop_task_end(){
thread_pool_destroy(pool_tank);
}
void tank_shot_pthrpoll_task_init(){
int *arg = malloc(sizeof(int));
*arg = 1;
pool_tank=thread_pool_init(1,1);
thread_pool_add_task(pool_tank, tank_shot_back_stop_task_function, &arg);
my_zlog_debug("线程池打开");
}
int tank_shot_back_stop(int pin,int val){
static int shot_count=0;
shot_device_time_start=get_current_time_millis();
......@@ -246,10 +255,7 @@ int tank_shot_back_stop(int pin,int val){
}
if(val != 0) {
if(shot_count == 0){
int arg =1;
pool_tank=thread_pool_init(1,1);
thread_pool_add_task(pool_tank, tank_shot_back_stop_task_function, &arg);
my_zlog_debug("线程池打开");
tank_shot_pthrpoll_task_init();
shot_count=1;
}
shot_count=1;
......
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