lv_timer_t *Wifi_conn_timer;
void Wifi_conn_timer_callback(lv_timer_t *timer)
{
if (load_network_info(&netInfo) == 0)
{
EventBuf e;
e.eventType = EVENT_CONNECTWIFI;
strncpy((char *)e.databuf, netInfo.wifi_name, 31);
e.databuf[31] = '\0';
strncpy((char *)e.databuf + 32, netInfo.wifi_pass, 31);
e.databuf[63] = '\0';
sendImageMsg(e);
SW_Network = true;
printf("Loaded WiFi: %s\n", netInfo.wifi_name);
}
else
{
SW_Network = false;
}
lv_timer_del(Wifi_conn_timer);
Wifi_conn_timer = NULL;
}
// 函数:检查指定网络接口是否为无线接口
bool is_truly_wireless(const char *interface_name)
{
char wireless_dir[256];
snprintf(wireless_dir, sizeof(wireless_dir), "/sys/class/net/%s/wireless", interface_name);
struct stat st;
if (stat(wireless_dir, &st) == 0 && S_ISDIR(st.st_mode))
{
// "/sys/class/net/<interface_name>/wireless" 目录存在,表明它是一个无线接口
return true;
}
return false;
}
// 函数:检查指定网络接口是否处于UP状态
// 返回 true 如果接口是UP,否则 false
bool is_interface_up(const char *interface_name)
{
int sock_fd;
struct ifreq ifr;
// 创建一个UDP socket,用于ioctl操作
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0)
{
perror("socket error");
return false;
}
// 设置接口名称
strncpy(ifr.ifr_name, interface_name, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0'; // 确保字符串以null结尾
// 获取接口标志
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0)
{
// perror("ioctl SIOCGIFFLAGS error"); // 接口不存在或其他错误
close(sock_fd);
return false;
}
close(sock_fd);
// 检查IFF_UP标志是否设置
return (ifr.ifr_flags & IFF_UP) != 0;
}
// 函数:设置指定网络接口的状态 (UP/DOWN)
// 参数: interface_name - 接口名称, should_be_up - true为UP,false为DOWN
// 返回 true 表示成功,否则 false
bool set_interface_state(const char *interface_name, bool should_be_up)
{
int sock_fd;
struct ifreq ifr;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0)
{
perror("socket error in set_interface_state");
return false;
}
strncpy(ifr.ifr_name, interface_name, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
// 首先获取当前标志
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("ioctl SIOCGIFFLAGS error in set_interface_state");
close(sock_fd);
return false;
}
if (should_be_up)
{
ifr.ifr_flags |= IFF_UP; // 设置IFF_UP标志
}
else
{
ifr.ifr_flags &= ~IFF_UP; // 清除IFF_UP标志
}
// 设置新的标志
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0)
{
// 常见的错误是 EPERM (Operation not permitted),表示没有权限
perror("ioctl SIOCSIFFLAGS error in set_interface_state");
close(sock_fd);
return false;
}
close(sock_fd);
return true;
}
// 函数:检查指定无线接口是否被RF-killed (射频阻断)
// 注意:rfkill通常是针对整个无线设备,而不是单个接口
// 返回 true 如果未被RF-killed,否则 false
bool is_wireless_rf_unblocked()
{
DIR *d;
struct dirent *dir_entry;
char path[256];
char buf[16];
FILE *fp;
d = opendir("/sys/class/rfkill/");
if (d == NULL)
{
// 如果rfkill子系统不存在或无法访问,假定没有rfkill阻断
// 在某些嵌入式系统中可能没有rfkill
// perror("Error opening /sys/class/rfkill/");
return true;
}
while ((dir_entry = readdir(d)) != NULL)
{
if (strncmp(dir_entry->d_name, "rfkill", 6) == 0) // 查找类似 rfkill0, rfkill1 的目录
{
// 检查rfkill设备的类型
snprintf(path, sizeof(path), "/sys/class/rfkill/%s/type", dir_entry->d_name);
fp = fopen(path, "r");
if (fp)
{
if (fgets(buf, sizeof(buf), fp) != NULL)
{
// 去除换行符
buf[strcspn(buf, "\n")] = 0;
if (strcmp(buf, "wlan") == 0) // 如果是无线LAN设备
{
fclose(fp); // 关闭type文件
// 检查其状态
snprintf(path, sizeof(path), "/sys/class/rfkill/%s/state", dir_entry->d_name);
fp = fopen(path, "r");
if (fp)
{
if (fgets(buf, sizeof(buf), fp) != NULL)
{
if (strcmp(buf, "1\n") == 0) // '1' 表示被阻断 (blocked)
{
fclose(fp);
closedir(d);
return false; // 发现无线被RF-killed
}
}
fclose(fp);
}
}
else
{
fclose(fp); // 如果不是wlan类型,也要关闭文件
}
}
else
{
fclose(fp); // fgets failed
}
}
}
}
closedir(d);
return true; // 没有发现无线被RF-killed
}
// 函数:检查系统中是否存在任何活动的无线网络接口
bool check_for_active_wlan()
{
DIR *d;
struct dirent *dir_entry;
bool wlan_found = false;
d = opendir("/sys/class/net/");
if (d == NULL)
{
perror("Error opening /sys/class/net/");
return false;
}
while ((dir_entry = readdir(d)) != NULL)
{
if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0)
{
continue;
}
if (strncmp(dir_entry->d_name, "wlan", 4) == 0 ||
strncmp(dir_entry->d_name, "wlp", 3) == 0 ||
strncmp(dir_entry->d_name, "wifi", 4) == 0)
{
if (is_truly_wireless(dir_entry->d_name))
{
// printf("Found active wireless interface: %s\n", dir_entry->d_name);
wlan_found = true;
break;
}
}
}
closedir(d);
return wlan_found;
}
// 函数:检查系统中是否存在任何活动的、未被阻断的无线网络接口
// 如果找到一个可用的无线接口,则返回 true,否则 false
bool check_for_act_wlan_interf()
{
DIR *d;
struct dirent *dir_entry;
bool wlan_fully_ready = false; // 修改变量名以反映更全面的检查
char found_interface_name[IFNAMSIZ]; // 存储找到的接口名
// 首先检查是否存在全局的RF-kill阻断
//if (!is_wireless_rf_unblocked())
//{
// printf("Wireless is RF-killed (soft/hard blocked).\n");
// return false; // 如果被rf-killed,直接返回false
//}
d = opendir("/sys/class/net/");
if (d == NULL)
{
perror("Error opening /sys/class/net/");
return false;
}
while ((dir_entry = readdir(d)) != NULL)
{
if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0)
{
continue;
}
// 过滤可能的无线接口名称
if (strncmp(dir_entry->d_name, "wlan", 4) == 0 ||
strncmp(dir_entry->d_name, "wlp", 3) == 0 ||
strncmp(dir_entry->d_name, "wifi", 4) == 0)
{
// 1. 检查是否真的是无线接口
if (is_truly_wireless(dir_entry->d_name))
{
// 2. 检查无线接口是否处于UP状态
if (is_interface_up(dir_entry->d_name))
{
// 如果代码执行到这里,说明:
// - 接口是无线接口
// - 接口处于UP状态
// - 且全局没有RF-kill阻断(已在函数开头检查)
// 可以选择在这里存储接口名称,如果只需要一个可用的接口
strncpy(found_interface_name, dir_entry->d_name, IFNAMSIZ);
found_interface_name[IFNAMSIZ - 1] = '\0';
printf("Found a fully ready wireless interface: %s\n", found_interface_name);
wlan_fully_ready = true;
break; // 找到一个就足够了,如果需要列出所有,则移除break
}
else
{
printf("Found wireless interface %s, but it is DOWN.\n", dir_entry->d_name);
}
}
}
}
closedir(d);
return wlan_fully_ready;
}
void FindWlanProc(EventBuf evt)
{
bool is_wlan_up = check_for_active_wlan();
if (is_wlan_up)
{
// WLAN 接口实际存在
if (!FindWlanFlag)
{ // 如果之前的状态是“未加载”
FindWlanFlag = true; // 更新状态:wifi已经加载
printf("Wlan in (verified by direct system check)!!!\n");
Wifi_conn_timer = lv_timer_create(Wifi_conn_timer_callback, 10000, NULL);
if (Wifi_conn_timer == NULL)
{
printf("Error: Failed to create Wifi_conn_timer!\n");
}
printf("Debug: Wifi_conn_timer would be created/reset here.\n");
}
}
else
{
// WLAN 接口不存在或未被识别
if (FindWlanFlag)
{
// 如果之前的状态是“已加载”
FindWlanFlag = false; // 更新状态:wifi没有加载
printf("Wlan out (verified by direct system check)!!!\n");
}
// 1. 获取输入框内容
const char *ip = "127.0.0.1";
const char *port_str = "9003";
// 3. 复制IP(字符串形式)
strncpy(socketconnInfo.ip, ip, sizeof(socketconnInfo.ip) - 1);
socketconnInfo.ip[sizeof(socketconnInfo.ip) - 1] = '\0';
// 2. 输入验证
if (!ip || !port_str)
{
printf("ERROR: IP或端口不能为空\n");
return;
}
// IP格式验证
struct in_addr addr;
if (inet_pton(AF_INET, ip, &addr) != 1)
{
printf("ERROR: 无效的IP地址格式\n");
lv_label_set_text(guider_ui.SettingScreen_label_server_conn_status, "Wrong IP!");
return;
}
// 端口号转换和验证
char *endptr;
long port = strtol(port_str, &endptr, 10);
if (*endptr != '\0' || port < 0 || port > 65535)
{
printf("ERROR: 端口号必须为0-65535的整数\n");
lv_label_set_text(guider_ui.SettingScreen_label_server_conn_status, "Wrong PORT!");
return;
}
socketconnInfo.port = (uint16_t)port; // 或htons((uint16_t)port)
// 3. 构造数据缓冲区
uint8_t buffer[21] = {0}; // 16+4+1=21字节
// 格式化IP部分(16字节)
size_t ip_len = strlen(ip);
if (ip_len > 15)
{
printf("WARNING: IP地址超过15字符将被截断\n");
ip_len = 15;
}
memcpy(buffer, ip, ip_len);
// 填充空格
if (ip_len < 15)
{
memset(buffer + ip_len, ' ', 15 - ip_len);
}
// 格式化端口部分(4字节网络序)
uint32_t net_port = htonl(port);
memcpy(buffer + 16, &net_port, 4);
// 添加状态码(1字节)
buffer[20] = 0x01; // 连接成功状态
// 4. 发送网络消息
int ret = sendNetMsg(EVENT_SOCKET_CONNECT, (const char *)buffer);
// 5. 处理发送结果
if (ret == 0)
{
printf("INFO: 连接信息发送成功\n");
printf("IP: %-15s Port: %-5d\n", ip, (int)port);
}
else
{
printf("ERROR: 发送失败,错误码: %d\n", ret);
}
}
}
我现在的机器连接无线网稍微有点问题,就是在连接无线网的时候,如果此时直接把路由器的电直接断掉,此时就会断开,但是断开后在重启机器就会有问题,此时会一直去连接上次的那个WiFi,但是由于路由器断电了,导致了无法连接,此时WiFi列表也没有其他的WiFi了,并且其他的一些界面的按钮点不动,你觉得会不会是上面的代码的问题,我的想法是在重连的时候,如果重连的有10s以后还是无法连接就判断超时了,然后显示WiFi列表,这样可行吗,并且我发现有如下的问题,
Found a fully ready wireless interface: wlan0
WiFi SSID: 你好
我发现即使路由器断电了,这个WiFi也是一样的显示有,但是其实WiFi已经没有了,这就导致了重试连接以后会显示已经连接上了,因此不会因为超时而显示WiFi列表,这个应该怎么办,按理说检测实际的物理接口应该可以判断出是否在线吧