Commit 289587b0 authored by 957dd's avatar 957dd

Merge branch 'feature/wifi_change' into 'master'

Feature/wifi change See merge request !43
parents a9560b46 a80c5b31
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-06T09:12:32"
#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"
#define WIFI_CONF_DIR "/home/orangepi/car/master"
typedef struct {
char ssid[SSID_MAX_LEN];
int signal;
} wifi_info_t;
void scan_wifi_json();//显示以连接WiFi名称和周围已有的WiFi和过滤信号强度低于50的WiFi
int wifi_change_sendmqtt_init();//wifi改变初始化,放在main开头,必须要等mqtt直播就绪才行
void wifi_change_recmqtt(cJSON *body);//接收到修改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);
audio_status=1;
audioplay_send_mqtt();
my_zlog_debug("播放已成功完成 : %s ", urlbuf);
audio_status=1;
} else {
my_zlog_warn("播放失败或中断: %s \n", urlbuf);
my_zlog_warn("播放失败或中断: %s ", urlbuf);
audio_status=2;
}
audioplay_send_mqtt();
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;
}
......
......@@ -13,6 +13,8 @@
#include "device_change.h"
#include "judg.h"
#include "ads1115.h"
#include "audioplay.h"
#include "wifichange.h"
struct mosquitto *mosq;
......@@ -21,6 +23,7 @@ int heartbeat_count=0;
char* TOPIC = NULL;
char* TOPIC2 = NULL;
char* TOPIC3 = NULL;
char* TOPIC4 = NULL;
char* TOPIC_BACK = NULL;
char* TOPIC2_BACK = NULL;
......@@ -48,17 +51,14 @@ char *glon=NULL;//加入gps后删除,心跳预留,不更改
time_t gStart;//时间戳
int mqtt_init() {
// 初始化 mosquitto 库
mosquitto_lib_init();
mosq = mosquitto_new(NULL, true, NULL);//
mosquitto_lib_init();
// 这里创建mosq可以保留,也可以删除这一行,让创建放到 Mqtt_onnect 里
mosq = mosquitto_new(NULL, true, NULL);
if (!mosq) {
my_zlog_fatal("Failed to create Mosquitto client");
return -1;
}
mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5);
return 0;
}
......@@ -67,7 +67,7 @@ void on_connect(struct mosquitto *mosq, void *obj, int rc) {//回调函数
my_zlog_debug("Connected to broker");
topic_middle_value();
mosquitto_subscribe(mosq, NULL, TOPIC, 0);
//mosquitto_subscribe(mosq, NULL, TOPIC_BACK, 0);
mosquitto_subscribe(mosq, NULL, TOPIC4, 0);
} else {
fprintf(stderr, "Connection failed with code %d\n", rc);
my_zlog_fatal("Connection failed");
......@@ -156,7 +156,12 @@ void mqtt_wirte(){//心跳格式,每5s一次心跳
}
void message_3(cJSON *body,cJSON *pwm_ctrl){//message_type为3,控制pwm
void message_3(cJSON *body){//message_type为3,控制pwm
cJSON *pwm_ctrl = cJSON_GetObjectItem(body, "pwm_ctrl");
cJSON *pin_setctrl = cJSON_GetObjectItem(body, "pin_setctrl");
if(pwm_ctrl==NULL||pin_setctrl==NULL){
return ;
}
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)
......@@ -182,7 +187,13 @@ void message_3(cJSON *body,cJSON *pwm_ctrl){//message_type为3,控制pwm
}
void message_4(cJSON *body, cJSON *pin_setctrl){//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 ;
}
cJSON *pin = cJSON_GetObjectItem(pin_setctrl, "pin");
cJSON *val = cJSON_GetObjectItem(pin_setctrl, "val"); //val为pwm的值 0~100(unsigned char)(unsigned char)
......@@ -206,7 +217,46 @@ void message_4(cJSON *body, cJSON *pin_setctrl){//message 为4时候
if(AppExit_pin_pwm == 202 ) tank_shot_back_stop(gvalt[1],gvalt[2]);
}
int device_message(cJSON *json){//接收到的控制设备的mqtt消息
int download_message(cJSON *body){//接收的下载的mqtt消息
if (cJSON_IsObject(body)) {
// 获取 doby 对象
// 获取 site 中的 name 和 url
cJSON *name = cJSON_GetObjectItem(body, "name");
cJSON *url = cJSON_GetObjectItem(body, "url");
if (cJSON_IsString(name) && cJSON_IsString(url)) {
my_zlog_debug("Site Name: %s", name->valuestring);
my_zlog_debug("Site URL: %s", url->valuestring);
}
// 获取 type 中的 suf、dir 和 sername
cJSON *down_suf = cJSON_GetObjectItem(body, "suf");
//cJSON *down_dir = cJSON_GetObjectItem(type, "dir");&& cJSON_IsString(down_dir)
cJSON *down_sername = cJSON_GetObjectItem(body, "sername");
if (cJSON_IsString(down_suf) && cJSON_IsString(down_sername)) {
my_zlog_debug("Type Suf: %s", down_suf->valuestring);
//my_zlog_debug("Type Dir: %s", down_dir->valuestring);
my_zlog_debug("Type Sername: %s", down_sername->valuestring);
}
}else return -1;
return 0;
}
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);
return 0;
}
int device_message_receive(cJSON *json){//接收到的控制设备的mqtt消息
cJSON *head = cJSON_GetObjectItem(json, "head");
cJSON *message_type = cJSON_GetObjectItem(head, "message_type");
......@@ -218,12 +268,6 @@ int device_message(cJSON *json){//接收到的控制设备的mqtt消息
return 1;
}
cJSON *pwm_ctrl = cJSON_GetObjectItem(body, "pwm_ctrl");
cJSON *pin_setctrl = cJSON_GetObjectItem(body, "pin_setctrl");
if(pwm_ctrl==NULL||pin_setctrl==NULL){
return 2;
}
gmessage_type=message_type->valueint;
my_zlog_debug("message_type: %d",message_type->valueint);
switch(gmessage_type){
......@@ -236,13 +280,32 @@ int device_message(cJSON *json){//接收到的控制设备的mqtt消息
my_zlog_debug("刷新成功");
break;
case 3:
message_3(body,pwm_ctrl);
message_3(body);
my_zlog_debug("进入pwm控制");
break;
case 4:
message_4(body,pin_setctrl);
message_4(body);
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 2005:
download_message(body);
break;
default:
break;
}
......@@ -251,53 +314,6 @@ int device_message(cJSON *json){//接收到的控制设备的mqtt消息
return 0;
}
int download_message(cJSON *root){//接收的下载的mqtt消息
cJSON *down = cJSON_GetObjectItem(root, "down");
if (cJSON_IsObject(down)) {
// 获取 site 对象
cJSON *site = cJSON_GetObjectItem(down, "site");
if (cJSON_IsObject(site)) {
// 获取 site 中的 name 和 url
cJSON *name = cJSON_GetObjectItem(site, "name");
cJSON *url = cJSON_GetObjectItem(site, "url");
if (cJSON_IsString(name) && cJSON_IsString(url)) {
my_zlog_debug("Site Name: %s", name->valuestring);
my_zlog_debug("Site URL: %s", url->valuestring);
}
}
// 获取 type 对象
cJSON *type = cJSON_GetObjectItem(down, "type");
if (cJSON_IsObject(type)) {
// 获取 type 中的 suf、dir 和 sername
cJSON *down_suf = cJSON_GetObjectItem(type, "suf");
//cJSON *down_dir = cJSON_GetObjectItem(type, "dir");&& cJSON_IsString(down_dir)
cJSON *down_sername = cJSON_GetObjectItem(type, "sername");
if (cJSON_IsString(down_suf) && cJSON_IsString(down_sername)) {
my_zlog_debug("Type Suf: %s", down_suf->valuestring);
//my_zlog_debug("Type Dir: %s", down_dir->valuestring);
my_zlog_debug("Type Sername: %s", down_sername->valuestring);
}
}
}else return -1;
return 0;
}
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);
return 0;
}
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) {//消息回环函数
time_t end = time(NULL);
......@@ -319,23 +335,10 @@ void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_messag
// 解析 JSON
cJSON *json = cJSON_Parse(payload_str);
if (json == NULL) {
//fprintf(stderr, "Error before: [%s]\n", cJSON_GetErrorPtr());
my_zlog_error("Error before: [%s]", cJSON_GetErrorPtr());
} else if(cJSON_GetObjectItem(json, "device_id") != NULL) {
cJSON *device_id=cJSON_GetObjectItem(json, "device_id");
device_mqttchange_name(device_id);
my_zlog_debug("接收到设备号更改");
} else if(cJSON_GetObjectItem(json, "type") != NULL) {
cJSON *type = cJSON_GetObjectItem(json, "type");
if (type && cJSON_IsString(type) && strcmp(type->valuestring, "audio") == 0) {
audioplay_mqtt_receive(json);
my_zlog_debug("接收到音频播放");
}
}else {// 提取 head 对象
if(download_message(json) == 0) my_zlog_debug("接收到dowwnload下载");
if(device_message(json) != 0) my_zlog_debug("没有接收到控制信息,代码编号:%d",device_message(json));
}
if(json != NULL){
if(device_message_receive(json)==0) my_zlog_debug("进入设备接收mqtt");
}
// 释放 payload 字符串
free(payload_str);
cJSON_Delete(json);
......@@ -343,27 +346,42 @@ void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_messag
}
void mqtt_create(struct mosquitto *mosq) {//创建mqtt客服端
int mqtt_create(struct mosquitto *mosq) { // 返回连接结果,0成功,非0失败
mosquitto_reconnect_delay_set(mosq, 2, 10, true);
// 设置连接和消息回调
mosquitto_connect_callback_set(mosq, on_connect);
mosquitto_message_callback_set(mosq, on_message);
//设置用户名和密码
mosquitto_username_pw_set(mosq, USERNAME, PASSWORD);
// 创建 mosquitto 客户端
rc = mosquitto_connect(mosq, BROKER_ADDRESS, BROKER_PORT, 60);
if (rc != MOSQ_ERR_SUCCESS) {
//fprintf(stderr, "Failed to connect to broker: %s\n", mosquitto_strerror(rc));
int rc = mosquitto_connect(mosq, BROKER_ADDRESS, BROKER_PORT, 60);
if (rc != MOSQ_ERR_SUCCESS) {
my_zlog_warn("Failed to connect to broker: %s", mosquitto_strerror(rc));
mosquitto_destroy(mosq);
//return EXIT_FAILURE;
// 不销毁 mosq,等待调用者处理重连
return rc;
}
return 0; // 成功
}
int mqtt_cycle(struct mosquitto *mosq) {//阻塞型
// 这个函数会阻塞直到连接断开或错误返回
int rc = mosquitto_loop_forever(mosq, -1, 1);
if (rc != MOSQ_ERR_SUCCESS) {
my_zlog_warn("mqtt loop error: %s", mosquitto_strerror(rc));
return rc;
}
}
void mqtt_cycle(struct mosquitto *mosq){
mosquitto_loop_forever(mosq, -1, 1); // -1 表示无限等待,1 表示处理消息的最大数量
}
// int mqtt_cycle(struct mosquitto *mosq) {//非阻塞型
// int rc;
// while (1) {
// rc = mosquitto_loop(mosq, 100, 1); // 每秒检查一次
// if (rc != MOSQ_ERR_SUCCESS) {
// my_zlog_warn("mosquitto loop error: %s,(code: %d)", mosquitto_strerror(rc),rc);
// return -1; // 跳出循环,重新连接
// }
// Delay_Ms(0, 3); // 防止空转
// }
// }
void mqtt_clean(struct mosquitto *mosq){
// 清理
mosquitto_destroy(mosq);
......
......@@ -10,9 +10,14 @@
#include "common.h"
#include "device_exit.h"
#include "thread_main.h"
#include "wifichange.h"
pthread_t thread[6]; // 全局线程句柄数组(或传参)
int gwebrtc_index=0;
int grc=0;
void* args[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
int thread_start(ThreadFunc AppExit, ThreadFunc Mqttbeat,
......@@ -37,7 +42,8 @@ int thread_start(ThreadFunc AppExit, ThreadFunc Mqttbeat,
return 0;
}
void *AppExit(void *arg) { //出现意外自动停止
//出现意外自动停止
void *AppExit(void *arg) {
while(1){
Delay_Ms(0,100);
gPwmCount++;
......@@ -58,15 +64,18 @@ void *AppExit(void *arg) { //出现意外自动停止
void *Mqttbeat(void *arg) {
//printf("Mqttbeat start\n");
my_zlog_info("Mqttbeat start");
Delay_Ms(15,0);
Delay_Ms(5,0);
wifi_change_sendmqtt_init();
gwebrtc_index=1;
while(1) {
ipaddr();//获取ip
if( AppExit_pin_pwm == 202) Delay_Ms(0,45);
if( AppExit_pin_pwm != 202) Delay_Ms(0,100);
heartbeat_count++;
mqtt_wirte();//心跳,3s一个
if(heartbeat_count>=30) heartbeat_count=0;
if(grc == 0){
ipaddr();//获取ip
mqtt_wirte();//心跳,3s一个
}
if(heartbeat_count>=30) heartbeat_count=0;
}
return NULL;
}
......@@ -74,24 +83,56 @@ void *Mqttbeat(void *arg) {
void *opensh(void *arg) {
Delay_Ms(5,0);
//printf("open cam\n");
my_zlog_info("open cam");
opencamsh();//10s后打开游览器并且进入网址
while(1){
if(gwebrtc_index==1) {
my_zlog_info("open cam");
opencamsh();//10s后打开游览器并且进入网址
}
}
return NULL;
}
void *Mqtt_onnect(void *arg) {//mqtt异常处理,断开自动重连,简单粗暴
//mqtt异常处理,断开自动重连,简单粗暴
void *Mqtt_onnect(void *arg) {
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;
}
void *delay_count(void *arg) {//专门用于计时的线程
//专门用于计时的线程
void *delay_count(void *arg) {
while (1) {
Delay_Ms(0,5);
device_delay_count++;
......@@ -100,7 +141,8 @@ void *delay_count(void *arg) {//专门用于计时的线程
return NULL;
}
void *play_mp3_thread(void* arg) {//专门处理MP3播放
//专门处理MP3播放
void *play_mp3_thread(void* arg) {
audioplay_cycle();
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
char wifi_Last_ssid[SSID_MAX_LEN]= {0} ;
char wifi_Last_password[SSID_MAX_LEN]= {0} ;
//获取当前连接wifi
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);
}
//找重复的WiFi名称
int find_ssid(wifi_info_t list[], int count, const char *ssid) {
for (int i = 0; i < count; i++) {
if (strcmp(list[i].ssid, ssid) == 0) {
return i;
}
}
return -1;
}
//进行qsort前,此未降序操作
int cmp_signal_desc(const void *a, const void *b) {
wifi_info_t *wa = (wifi_info_t *)a;
wifi_info_t *wb = (wifi_info_t *)b;
return wb->signal - wa->signal;
}
//显示以连接WiFi名称和周围已有的WiFi和过滤掉信号强度低于50的WiFi
void scan_wifi_json() {
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);
}
//连接WiFi
int connect_wifi(const char* ssid, const char* password) {
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);
ret = -5;
}
} else {
my_zlog_error("❌ 无法执行回退连接命令。");
ret = -5;
}
}
return ret;
}
//改变WiFi连接
int change_wifi_connect(const char *wifi_ssid,const char *wifi_password) {
get_current_wifi();
int ret = connect_wifi_with_fallback(wifi_ssid, wifi_password, current_ssid);
my_zlog_notice("返回代码:%d", ret);
return ret;
}
// 连续尝试 2 次 ping,任意一次成功即认为联网成功
int can_access_internet() {
for (int i = 0; i < 4; ++i) {
int ret = system("ping -c 1 -W 1 baidu.com > /dev/null 2>&1");
if (ret == 0) {
return 0; // 有一次成功就返回 true
}
}
return 1; // 都失败
}
//删除对应wifi
int delete_wifi_by_ssid(const char* ssid) {
if (ssid == NULL || strlen(ssid) == 0) {
fprintf(stderr, "SSID is empty.\n");
return -1;
}
char command[256];
// 直接尝试删除这个名字的连接(假设连接名就是 SSID)
snprintf(command, sizeof(command), "nmcli connection delete \"%s\"", ssid);
int ret = system(command);
if (ret == 0) {
my_zlog_debug("Successfully deleted WiFi connection named: %s", ssid);
} else {
my_zlog_warn("Failed to delete WiFi connection named: %s", ssid);
}
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;
}
// 执行命令并获取结果,通过此函数获取到WiFi密码
char *get_command_output(const char *cmd, char *buffer, size_t size) {
FILE *fp = popen(cmd, "r");
if (!fp) return NULL;
if (fgets(buffer, size, fp)) {
buffer[strcspn(buffer, "\n")] = '\0'; // 去除换行符
}
pclose(fp);
return buffer;
}
// 写入当前 WiFi SSID 和密码到配置文件
int write_wifi_conf() {
char ssid[128] = {0};
char cmd[256];
char password[128] = {0};
// 获取 SSID
if (!get_command_output("iwgetid -r", ssid, sizeof(ssid))) {
fprintf(stderr, "获取当前连接的 SSID 失败\n");
return -1;
}
// 从 NetworkManager 配置中获取密码
snprintf(cmd, sizeof(cmd),
"grep -r '^psk=' /etc/NetworkManager/system-connections/ | grep '%s' | head -n1 | cut -d'=' -f2",
ssid);
if (!get_command_output(cmd, password, sizeof(password))) {
fprintf(stderr, "获取 WiFi 密码失败(可能无权限或未使用 NetworkManager)\n");
return -1;
}
// 写入文件
FILE *fp = fopen(WIFI_CONF_PATH, "w");
if (!fp) {
my_zlog_error("打开配置文件失败");
return -1;
}
fprintf(fp, "SSID=%s\n", ssid);
fprintf(fp, "PASSWORD=%s\n", password);
fclose(fp);
my_zlog_debug("已写入到配置文件: %s\n", WIFI_CONF_PATH);
return 0;
}
//删除对应的存在ssid的conf
void delete_wifi_conf() {
DIR *dir = opendir(WIFI_CONF_DIR);
if (!dir) {
my_zlog_warn("opendir failed");
return;
}
struct dirent *entry;
char full_path[1024];
while ((entry = readdir(dir)) != NULL) {
// 只查找文件名为 "device_wifi.conf"
if (strcmp(entry->d_name, "device_wifi.conf") == 0) {
snprintf(full_path, sizeof(full_path), "%s/%s", WIFI_CONF_DIR, entry->d_name);
if (unlink(full_path) == 0) {
my_zlog_debug("Deleted: %s\n", full_path);
} else {
my_zlog_warn("Failed to delete");
}
break; // 找到并删除就退出
}
}
closedir(dir);
}
//提取WiFi名称和密码
int extract_wifi_file(){
FILE *fp = fopen(WIFI_CONF_PATH, "r");
if (fp == NULL) {
perror("无法打开配置文件");
return -1;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
// 去除换行符
line[strcspn(line, "\r\n")] = 0;
if (strncmp(line, "SSID=", 5) == 0) {
strncpy(wifi_Last_ssid, line + 5, sizeof(wifi_Last_ssid) - 1);
} else if (strncmp(line, "PASSWORD=", 9) == 0) {
strncpy(wifi_Last_password, line + 9, sizeof(wifi_Last_password) - 1);
}
}
fclose(fp);
my_zlog_debug("SSID: %s", wifi_Last_ssid);
my_zlog_debug("PASSWORD: %s", wifi_Last_password);
return 0;
}
// 从文件读取 SSID,比较当前连接的 WiFi 名称
int compare_ssid_with_file() {
char file_ssid[128] = {0};
get_current_wifi();
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);
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没有发生改变或其他问题");
return 0;
} else {
my_zlog_debug("wifi发生改变或其他问题");
return 1;
}
}
/*当wifi_status为0为连接jking,当wifi_status为1为修改成功,2是继续使用正常wifi,3是恢复到默认jking,4为wifi不存在
,5为密码错误,6为未知错误,7为回退失败,8为没网切回默认wifi*/
void wifichange_sendmqtt(int wifi_status) { //改WiFi发送
topic_middle_value();//指针中间函数
get_current_wifi();
cJSON *root = cJSON_CreateObject();
cJSON *body = cJSON_CreateObject();
cJSON *head = cJSON_CreateObject();
cJSON_AddNumberToObject(body, "wifi_status", wifi_status);//为0成功
cJSON_AddStringToObject(body, "wifi_ssid", current_ssid);//为0成功
cJSON_AddNumberToObject(head, "message_type",3004);
cJSON_AddItemToObject(root, "body", body);
cJSON_AddItemToObject(root, "head",head);
char *payload = cJSON_PrintUnformatted(root);
my_zlog_debug("%s",payload);
mosquitto_publish(mosq, NULL, TOPIC3, strlen(payload), payload, 0, false);
cJSON_Delete(root); // 释放 cJSON 对象
}
//默认连接jking
void connect_wifi_jking() {
if(check_or_create_wifi_conf() == 0) my_zlog_debug("文件已创建");
if(write_wifi_conf() == 0) my_zlog_debug("写入成功");
int ret=change_wifi_connect(default_SSID,default_password);
Delay_Ms(15,0);
if(can_access_internet()==0) {
system("sudo reboot");//重启香橙派
my_zlog_debug("重启成功");
}
}
//wifi改变初始化,放在main开头,必须要等mqtt直播就绪才行
int wifi_change_sendmqtt_init(){
int wififile_fd = compare_ssid_with_file();
if(wififile_fd==-1){
if(can_access_internet()!=0){
get_current_wifi();
if(strcmp(default_SSID,current_ssid)==0){
my_zlog_debug("没有更改WiFi");
return 0;
}
check_or_create_wifi_conf();
write_wifi_conf();
change_wifi_connect(default_SSID,default_password);
delete_wifi_by_ssid(current_ssid);
}
if(strcmp(default_SSID,current_ssid)==0) wifichange_sendmqtt(0);
}else if(wififile_fd==1){
get_current_wifi();
if(strcmp(default_SSID,current_ssid)==0){
extract_wifi_file();
if(change_wifi_connect(wifi_Last_ssid,wifi_Last_password)==0){
Delay_Ms(15,0);
if(can_access_internet()==0){
delete_wifi_by_ssid(current_ssid);
delete_wifi_conf();
my_zlog_debug("成功回朔到上次WiFi");
}else {
change_wifi_connect(default_SSID,default_password);
my_zlog_debug("成功回朔到上次WiFi但没网回到默认wifi");
}
}else {
change_wifi_connect(default_SSID,default_password);
my_zlog_debug("说明不止一次更换wifi过");
}
}else{
if(can_access_internet()==0){
wifichange_sendmqtt(1);
my_zlog_debug("wifi更改成功");
delete_wifi_conf();
}else {
if(change_wifi_connect(default_SSID,default_password)==0)delete_wifi_conf();
my_zlog_debug("WiFi无网切回");
Delay_Ms(10,0);
}
}
} else if(wififile_fd==0){
if(can_access_internet()==0) {
wifichange_sendmqtt(2);//2是继续使用正常wifi
my_zlog_debug("wifi更改失败,继续使用原WiFi,可使用查询指令查询");
delete_wifi_conf();
} else {//不需要删除文件,不同回删除conf源文件,相同也会删除
wifichange_sendmqtt(3);//3是恢复到默认jking
my_zlog_debug("在WiFi更改失败情况下使用默认连接jking");
delete_wifi_conf();
connect_wifi_jking();
}
}
return 0;
}
//接收mqtt消息
void wifi_change_recmqtt(cJSON *body){
cJSON *wifi_ssid = cJSON_GetObjectItem(body, "wifi_ssid");
cJSON *wifi_password = cJSON_GetObjectItem(body, "wifi_password");
cJSON *wifi_status = cJSON_GetObjectItem(body, "wifi_status");
if(cJSON_IsString(wifi_ssid) && cJSON_IsString(wifi_password)){
char *ssid = wifi_ssid->valuestring,*password=wifi_password->valuestring;
int wifi_statustemp = wifi_status->valueint;
if(check_or_create_wifi_conf() == 0) my_zlog_debug("文件已创建");
if(write_wifi_conf() == 0) my_zlog_debug("写入成功");
int ret = change_wifi_connect(ssid,password);
Delay_Ms(15,0);
if(strcmp(default_SSID,ssid)==0){
delete_wifi_by_ssid(current_ssid);
my_zlog_debug("ssid:%S",current_ssid);
delete_wifi_conf();
system("sudo reboot");//重启香橙派
my_zlog_debug("重启成功");
}
if(ret == 0){
if(can_access_internet()==0){
delete_wifi_by_ssid(current_ssid);
my_zlog_debug("ssid:%S",current_ssid);
system("sudo reboot");//重启香橙派
my_zlog_debug("重启成功");
}else {
delete_wifi_conf();
if(change_wifi_connect(default_SSID,default_password)==0) delete_wifi_by_ssid(current_ssid);
my_zlog_debug("无网切回默认WiFi");
Delay_Ms(15,0);
wifichange_sendmqtt(8);
}
}
if(ret == -1) {
wifichange_sendmqtt(4);
}else if(ret == -2){
wifichange_sendmqtt(5);
}else if(ret == -3){
wifichange_sendmqtt(6);
}else if(ret == -4 || ret == -5){
wifichange_sendmqtt(7);
system("sudo reboot");//重启香橙派
my_zlog_debug("重启成功");
}
}
}
\ 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