【XR806开发板试用】通过http请求从心知天气网获取天气预报信息
1. 开发环境搭建
本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中,关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统(WSL)
(1) 在WSL的Ubuntu20.04下安装必要的工具的.
- 安装git:
sudo apt-get install git
- 安装gcc编译器套件:
sudo apt-get install build-essential
- 安装bear,该工具用来生成编译数据库文件:compile_commands.json,可以实现编辑代码时智能提示和代码跳转.
sudo apt-get install bear
- 安装ncurses库,使用make menuconfig配置工程时依赖该库.
sudo apt-get install libncurses5-dev
(2)安装windows下必要的工具
我们编译的固件要通过串口烧录到XR806,由于WSL2下不能直接使用windows的串口,所以需要在windows下使用工具 usbipd共享串口给WSL2使用,可以参考文章:WSL2下的usb串口设备使用
此外,我们编辑和阅读代码使用vscode,关于vscode的C/C++环境配置可参考文章:vscode配置C/C++环境
(3)搭建XR806编译开发环境
可以参考:搭建基于FreeRTOS的XR806开发环境, 需要注意的是文章中提供的编译工具链gcc-arm-none-eabi-8-2019-q3-update下载链接无效,在终端中使用如下命令下载编译工具链:
wget https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/8-2019q3/RC1.1/gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2
2. 创建工程
创建工程可以参考: 新工程创建, 我们工程命名为wifi_sta,我们工程所在目录如下图:
我们在终端中进入工程跟目录,按如下步骤来配置工程和编译代码生成镜像:
# 复制默认配置文件到顶层目录(不切换工程可不要此步骤)
$ make PRJ=demo/wifi_sta defconfig
# 检查SDK 基础配置,如工程名、芯片型号、高频晶振、板级配置是否正确
$ make menuconfig
# 清理,切换工程时需要
$ make build_clean
# 编译代码并生成镜像文件,生成的镜像文件为“out/xr_system.img”
$ bear make build -j 12
依次执行上述命令后,在工程根目录执行如下命令,使用vscode打开工程
code .
在vscode中打开工程目录后,敲击F1键,弹出如下选择项,我们选择C/C++:编辑配置(UI)
在编译器路径输入框中输入XR806交叉编译器完整路径,如下图所示:
在高级设置下的编译命令输入框中输入编译数据库文件compile_commands.json的路径,如下图所示:
3. 编辑工程代码
想要从心知天气网获取天气预报,首先需要注册该网站账号. 注册账号并登陆,打开获取天气预报相关的API文档页: 未来15天逐日天气预报和昨日天气 阅读该文档了解到获取未来3天天气预报的接口地址为:
https://api.seniverse.com/v3/weather/daily.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c&start=-1&days=5
其中参数"your_api_key"是你获取天气预报信息的API密钥,该API密钥可以从心知天气网主页进入控制台页面,然后点击左侧的"免费版",即可看到自己的私钥,该私钥即为API 密钥,如下图所示:
接下来我们编写代码实现通过http请求从心知天气网获取未来3天的天气信息.
- 首先在main.c中添加必要的头文件:
#include <stdio.h>
#include <string.h>
#include "kernel/os/os.h"
#include "net/wlan/wlan.h"
#include "net/wlan/wlan_defs.h"
#include "common/framework/net_ctrl.h"
#include "common/framework/platform_init.h"#include <errno.h>
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "sys/select.h"#include "cjson/cJSON.h"
- 然后定义关于天气信息的结构体类型:
/* 天气数据结构体 */
typedef struct tagWeather
{/* 实况天气数据 */char id[32]; //idchar name[32]; //地名char country[32]; //国家char path[32]; //完整地名路径char timezone[32]; //时区char timezone_offset[32]; //时差char text[32]; //天气预报文字char code[32]; //天气预报代码char temperature[32]; //气温char last_update[32]; //最后一次更新的时间/* 今天、明天、后天天气数据 */char date[3][32]; //日期char text_day[3][64]; //白天天气现象文字char code_day[3][32]; //白天天气现象代码char code_night[3][64]; //晚间天气现象代码char high[3][32]; //最高温char low[3][32]; //最低温char wind_direction[3][64]; //风向char wind_speed[3][32]; //风速,单位km/h(当unit=c时)char wind_scale[3][32]; //风力等级
} Weather_T;
- 再定义通过http的GET请求方式获取天气预报的请求头部:
#define WEB_SERVER "api.seniverse.com" // 天气预报网服务器地址
#define WEB_PORT "80" // 天气预报网服务器端口号
#define CONFIG_API_KEY "xxxxxxxxxxxxxx" // 你的API密钥,从心知天气网控制台页面获取
/* 获取天气预报信息的http请求头部 */
#define GET_REQUEST_PACKAGE \"GET https://api.seniverse.com/v3/weather/daily.json?key=" CONFIG_API_KEY "&location=%s&language=zh-Hans&unit=c\r\n\r\n"#define HTTPC_DEMO_THREAD_STACK_SIZE (8 * 1024) /* 任务栈大小 */
- 定义WiFi的ssid和password:
char *sta_ssid = "xxxxxx"; // 你要连接的WiFi名
char *sta_psk = "xxxxxxxx"; // 你要连接的WiFi密码
char httpc_response_buf[2048]; //用于保存获取到的天气信息的原始数据
int write_idx = 0; // 写数据到httpc_response_buf的数组下标
static OS_Thread_t httpc_demo_thread; // 获取天气的线程ID
- 编写WiFi联网初始化函数:
void sta_start(void)
{/* switch to sta mode */net_switch_mode(WLAN_MODE_STA);#if STA_MODE_USE_WPA2_ONLY/* set ssid and password to wlan, only use WPA2 mode to connect AP. */wlan_sta_config((uint8_t *)sta_ssid, strlen(sta_ssid), (uint8_t *)sta_psk, 0);
#else/* set ssid and password to wlan, use WPA2|WPA3 compatible mode to connect AP. */wlan_sta_set((uint8_t *)sta_ssid, strlen(sta_ssid), (uint8_t *)sta_psk);
#endif/* start scan and connect to ap automatically */wlan_sta_enable();
}
- 在mian函数中添加如下代码
int main(void)
{observer_base *net_ob;platform_init();/* create an observer to monitor the net work state */net_ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK,NET_CTRL_MSG_ALL,net_cb,NULL);if (net_ob == NULL) {return -1;}if (sys_ctrl_attach(net_ob) != 0) {return -1;}sta_start();return 0;
}
其中,函数sys_callback_observer_create创建一个事件监听器,当函数第1个参数CTRL_MSG_TYPE_NETWORK和第2个参数NET_CTRL_MSG_ALL所指定的事件发生时自动调用回调函数net_cb,此处表示所有的网络事件发生时均会调用回调函数net_cb,net_cb定义如下:
static void net_cb(uint32_t event, uint32_t data, void *arg)
{uint16_t type = EVENT_SUBTYPE(event);switch (type) {case NET_CTRL_MSG_NETWORK_UP: // WiFi sta连接AP成功并自动分配了ip地址{/* 打印本机的IP地址,网关,子网掩码 */struct netif *nif = wlan_netif_get(WLAN_MODE_STA);while (!NET_IS_IP4_VALID(nif)) {OS_MSleep(100);}printf("local ip: %s\n", ipaddr_ntoa(&nif->ip_addr));printf("gw: %s\n", ipaddr_ntoa(&nif->gw));printf("netmask: %s\n", ipaddr_ntoa(&nif->netmask));}/*创建线程,通过http请求获取天气预报信息*/if (!OS_ThreadIsValid(&httpc_demo_thread)) {OS_ThreadCreate(&httpc_demo_thread,"httpc_demo_thread",httpc_demo_fun,(void *)NULL,OS_THREAD_PRIO_APP,HTTPC_DEMO_THREAD_STACK_SIZE);}break;case NET_CTRL_MSG_NETWORK_DOWN: //WiFi连接断开事件break;default:break;}
}
httpc_demo_fun函数的定义如下:
static void httpc_demo_fun(void *arg)
{http_get_weather("beijing");// 获取天气预报信息结束后,删除本线程OS_ThreadDelete(&httpc_demo_thread);
}
其中http_get_weather函数的参数即为想要获取天气预报的城市的汉语拼音名,定义如下:
static void http_get_weather(char *city)
{int32_t ret;char request_head[sizeof(REQUEST) + 64];const struct addrinfo hints = {.ai_family = AF_INET,.ai_socktype = SOCK_STREAM,};struct addrinfo *res;struct in_addr *addr;int s, r;Weather_T weather_data = {0};bzero(httpc_response_buf, sizeof(httpc_response_buf));/* 通过服务器域名和端口获取服务器的IP地址相关信息 */ret = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res);if (ret != 0 || res == NULL) {printf("DNS lookup failed ret=%d res=%p\n", ret, res);return;}// Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;printf("DNS lookup succeeded. IP=%s\n", inet_ntoa(*addr));/* 创建soocket */s = socket(res->ai_family, res->ai_socktype, 0);if(s < 0) {printf("... Failed to allocate socket.\n");freeaddrinfo(res);return;}printf("... allocated socket\n");/* 使用第1步获取的服务器IP地址连接服务器 */if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {printf("... socket connect failed errno=%d\n", errno);close(s);freeaddrinfo(res);return;}printf("... connected\n");freeaddrinfo(res);/* 使用城市名生成完整的http的GET请求头部并发送到服务器*/snprintf(request_head, sizeof(request_head), GET_REQUEST_PACKAGE, city);if (write(s, request_head, strlen(request_head)) < 0) {printf("... socket send failed\n");close(s);return;}printf("... socket send success\n");/* 读取服务器返回的应答数据 *//* Read HTTP response */do {r = read(s, &httpc_response_buf[write_idx], sizeof(httpc_response_buf) - write_idx -1);if (r > 0) {write_idx += r;}} while(r > 0 && write_idx < (sizeof(httpc_response_buf) - 1));printf("... done reading from socket. Last read return=%d write_idx=%u errno=%d.\n", r, write_idx, errno);/* 打印服务器返回的数据 */for (int i = 0; i < write_idx; ++i) {putchar(httpc_response_buf[i]);}puts("");/* 解析天气预报数据 */ret = cJSON_DailyWeatherParse(httpc_response_buf, &weather_data);if (ret == 0) {/* 格式化打印天气预报信息 */DisplayWeather(&weather_data);}close(s);
}
由于服务器返回的天气预报数据为json字符串, 我们编写函数cJSON_DailyWeatherParse解析天气预报json数据并保存到结构体变量weather_data中,cJSON_DailyWeatherParse函数和DisplayWeather函数的定义如下:
static int cJSON_DailyWeatherParse(char *JSON, Weather_T *result)
{cJSON *json,*arrayItem,*object,*subobject,*item,*sub_child_object,*child_Item;json = cJSON_Parse(JSON); //解析JSON数据包if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效{printf("Error before: [%s]\n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置return 1;}else{if ((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL) //匹配字符串"results",获取数组内容{// int size = cJSON_GetArraySize(arrayItem); //获取数组中对象个数
#if DEBUGprintf("Get Array Size: size=%d\n",size);
#endifif((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容{/* 匹配子对象1------结构体location */if((subobject = cJSON_GetObjectItem(object,"location")) != NULL){if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子对象1成员"name"{memcpy(result->name, item->valuestring,strlen(item->valuestring)); // 保存数据供外部调用}}/* 匹配子对象2------数组daily */if((subobject = cJSON_GetObjectItem(object,"daily")) != NULL){int sub_array_size = cJSON_GetArraySize(subobject);
#if DEBUGprintf("Get Sub Array Size: sub_array_size=%d\n",sub_array_size);
#endiffor(int i = 0; i < sub_array_size; i++){if((sub_child_object = cJSON_GetArrayItem(subobject,i))!=NULL){// 匹配日期if((child_Item = cJSON_GetObjectItem(sub_child_object,"date")) != NULL){memcpy(result->date[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配白天天气现象文字if((child_Item = cJSON_GetObjectItem(sub_child_object,"text_day")) != NULL){memcpy(result->text_day[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配白天天气现象代码if((child_Item = cJSON_GetObjectItem(sub_child_object,"code_day")) != NULL){memcpy(result->code_day[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配夜间天气现象代码if((child_Item = cJSON_GetObjectItem(sub_child_object,"code_night")) != NULL){memcpy(result->code_night[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配最高温度if((child_Item = cJSON_GetObjectItem(sub_child_object,"high")) != NULL){memcpy(result->high[i], child_Item->valuestring,strlen(child_Item->valuestring)); //保存数据}// 匹配最低温度if((child_Item = cJSON_GetObjectItem(sub_child_object,"low")) != NULL){memcpy(result->low[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配风向if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_direction")) != NULL){memcpy(result->wind_direction[i],child_Item->valuestring,strlen(child_Item->valuestring)); //保存数据}// 匹配风速,单位km/h(当unit=c时)if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_speed")) != NULL){memcpy(result->wind_speed[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}// 匹配风力等级if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_scale")) != NULL){memcpy(result->wind_scale[i], child_Item->valuestring,strlen(child_Item->valuestring)); // 保存数据}}}}/* 匹配子对象3------最后一次更新的时间 */if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL){//printf("%s:%s\n",subobject->string,subobject->valuestring);}}}}cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间return 0;
}/*******************************************************************************************************
** 函数: DisplayWeather,显示天气数据
**------------------------------------------------------------------------------------------------------
** 参数: weather_data:天气数据
** 返回: void
********************************************************************************************************/
static void DisplayWeather(Weather_T *weather_data)
{printf("===========%s近三天的天气情况如下===========\n",weather_data->name);printf("【%s】\n",weather_data->date[0]);printf("天气:%s\n",weather_data->text_day[0]);printf("最高温:%s℃\n",weather_data->high[0]);printf("最低温:%s℃\n",weather_data->low[0]);printf("风向:%s\n",weather_data->wind_direction[0]);printf("风速:%skm/h\n",weather_data->wind_speed[0]);printf("风力等级:%s\n",weather_data->wind_scale[0]);printf("\n");printf("【%s】\n",weather_data->date[1]);printf("天气:%s\n",weather_data->text_day[1]);printf("最高温:%s℃\n",weather_data->high[1]);printf("最低温:%s℃\n",weather_data->low[1]);printf("风向:%s\n",weather_data->wind_direction[1]);printf("风速:%skm/h\n",weather_data->wind_speed[1]);printf("风力等级:%s\n",weather_data->wind_scale[1]);printf("\n");printf("【%s】\n",weather_data->date[2]);printf("天气:%s\n",weather_data->text_day[2]);printf("最高温:%s℃\n",weather_data->high[2]);printf("最低温:%s℃\n",weather_data->low[2]);printf("风向:%s\n",weather_data->wind_direction[2]);printf("风速:%skm/h\n",weather_data->wind_speed[2]);printf("风力等级:%s\n",weather_data->wind_scale[2]);
}
- 编译工程
bear make build -j 8
- 烧录镜像到xr806
首先使用USB线将开发板连上电脑,可能需要重新安装CP2102驱动,下载地址为CP2102驱动,在Windows中打开powershell,输入如下命令:
PS C:\Users\30751\Desktop> usbipd wsl list
BUSID VID:PID DEVICE STATE
2-1 10c4:ea60 Silicon Labs CP210x USB to UART Bridge (COM3) Not attached
2-3 248a:8367 USB 输入设备 Not attached
2-6 0c45:6a1b Integrated Webcam Not attached
2-10 8087:0026 英特尔(R) 无线 Bluetooth(R) Not attached
我们可以看到开发板连接的USB端口的的BUSID为2-1,接着使用如下命令将该USB串口共享给WSL:
PS C:\Users\30751\Desktop> usbipd wsl attach --busid 2-1
usbipd: info: Using default WSL distribution 'Ubuntu-20.04'; specify the '--distribution' option to select a different one.
接下来我们在Ubuntu终端中进入工程源码目录下的tools目录下,开启固件烧录USB串口的读写权限:
sudo chmod 666 /dev/ttyUSB0
使用如下命令烧录镜像到xr806
./phoenixMC
烧录成功信息如下:
我们再次在Windows中打开powershell,输入如下命令将开发板连接到windows:
usbipd wsl detach --busid 2-1
我们在windows中打开终端软件Tera Term,连上开发板串口,复位开发板将会看到如下信息:
use default flash chip mJedec 0x0
[FD I]: mode: 0x10, freq: 96000000Hz, drv: 0
[FD I]: jedec: 0x0, suspend_support: 1
mode select:ewlan information ===================================================
firmware:version : R0-XR_C07.08.52.67_ULP_R_02.132 Jan 10 2023 19:14:11-Y02.132buffer : 8
driver:version : XR_V02.06.10
mac address:in use : 8c:6d:08:3d:14:01in use : 8c:6d:08:3d:14:02
====================================================================wlan mode:aplatform information ===============================================
XR806 SDK v1.2.2 Oct 21 2023 23:46:57 62800400heap space [0x217098, 0x24bc00), size 215912cpu clock 160000000 Hz
HF clock 40000000 Hzsdk option:XIP : enableINT LF OSC : enableINT LDO : selectINT LDO / EXT PWR: enableSIP flash : enablemac address:efuse : 80:74:84:05:b9:cain use : 8c:6d:08:3d:14:01
====================================================================[net INF] no need to switch wlan mode 0
[net INF] msg <wlan scan success>
en1: Trying to associate with 8c:ab:8e:fd:c3:58 (SSID='302' freq=2412 MHz)
en1: Associated with 8c:ab:8e:fd:c3:58
en1: WPA: Key negotiation completed with 8c:ab:8e:fd:c3:58 [PTK=CCMP GTK=TKIP]
en1: CTRL-EVENT-CONNECTED - Connection to 8c:ab:8e:fd:c3:58 completed [id=0 id_str=]
[net INF] msg <wlan connected>
[net INF] netif is link up
[net INF] start DHCP...
WAR drop=1135, fctl=0x00d0.
[net INF] netif (IPv4) is up
[net INF] address: 192.168.2.107
[net INF] gateway: 192.168.2.1
[net INF] netmask: 255.255.255.0
[net INF] msg <network up>
local ip: 192.168.2.107
gw: 192.168.2.1
netmask: 255.255.255.0
DNS lookup succeeded. IP=116.62.81.138
... allocated socket
... connected
... socket send success
... done reading from socket. Last read return=0 write_idx=995 errno=107.
{"results":[{"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2023-10-22","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"21","low":"6","rainfall":"0.00","precip":"0.00","wind_direction":"无持续风向","wind_direction_degree":"","wind_speed":"8.4","wind_scale":"2","humidity":"61"},{"date":"2023-10-23","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"21","low":"7","rainfall":"0.00","precip":"0.00","wind_direction":"无持续风向","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"75"},{"date":"2023-10-24","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"23","low":"9","rainfall":"0.00","precip":"0.00","wind_direction":"无持续风向","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"75"}],"last_update":"2023-10-20T08:00:00+08:00"}]}
===========北京近三天的天气情况如下===========
【2023-10-22】
天气:晴
最高温:21℃
最低温:6℃
风向:无持续风向
风速:8.4km/h
风力等级:2【2023-10-23】
天气:晴
最高温:21℃
最低温:7℃
风向:无持续风向
风速:3.0km/h
风力等级:1【2023-10-24】
天气:晴
最高温:23℃
最低温:9℃
风向:无持续风向
风速:3.0km/h
风力等级:1
可以看到我们已经成功获取了北京的未来三天的天气情况.
4. 总结
通过本次开发板评测,掌握了XR806的WiFi相关API的使用,系统事件监听API的使用掌,握了sokect网络编程相关知识,掌握了cJSON的使用. XR806是一款性价比很高的WiFi/BLE MCU,官方提供的SDK完善,文档丰富,是物联网相关的项目的理想选择.
附件:工程源码仓库
相关文章:

【XR806开发板试用】通过http请求从心知天气网获取天气预报信息
1. 开发环境搭建 本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中,关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统(WSL) (1) 在WSL的Ubuntu20.04下安装必要的工具的. 安装git: sudo apt-get install git …...
NPM介绍与使用
什么是NPM? NPM(Node Package Manager)是一个强大的包管理工具,专门用于Node.js应用程序的依赖管理。它允许开发者轻松地分享、安装、更新和管理项目中使用的库、工具和框架。 NPM的安装 在使用NPM之前,请确保你的机…...
servlet +thymeleaf渲染引擎
servlet thymeleaf渲染引擎 一、maven坐标 <dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf</artifactId><version>3.0.12.RELEASE</version> <!-- 使用适当的Thymeleaf版本 --> </dependency> &…...
10分钟了解nextTick,并实现简易版本的nextTick
在 Vue.js 中,有一个特殊的方法 nextTick,它在 DOM 更新后执行一段代码,起到等待 DOM 绘制完成的作用。本文会详细介绍 nextTick 的原理和使用方法,并实现一个简易版的 nextTick,加深对它的理解。 一. 什么是 nextTic…...
oracle表空间对象迁移到其他表空间
oracle数据库的磁盘空间满了,除了简单粗暴的增加磁盘空间外,还可以缩小表空间的datafile,因为正常业务运行中,表数据的删除和增加,会造成表空间里面里面有很多空的地方。方案有很多种,我这里简单介绍一下&a…...
<stdlib.h>头文件: C 语言常用标准库函数详解
文章目录 引言1. <stdlib.h> 概览1.1 头文件包含 2. 内存管理函数2.1 malloc 函数2.2 calloc 函数2.3 realloc 函数2.4 free 函数 3. 随机数生成函数3.1 rand 函数3.2 srand 函数 4. 字符串转换函数4.1 atoi 函数4.2 atof 函数4.3 itoa 函数4.4 ltoa 函数4.5 ultoa函数 5…...

Qt前端技术:3.QSS字体样式
small-caps就是让这个文本中的小写字母用大写的形式写出来并且在用大写的形式表达出来后他本身的大小会变小 有绝对尺寸和相对尺寸的区别 绝对尺寸一般是cm,英寸之类的 相对尺寸如px之类的是由显示器的屏幕分辨率来决定的 如windows用户分辨率一般是96像素点每英…...

阿里面试官:面试了一个能力相当不错的候选人,但背调时,他前同事和领导都说他人品很差,纠结该不该要他?...
* 你好,我是前端队长,在职场,玩副业,文末有福利! 在职场中,背调是个躲不开的事情。不管是各行各业背调可能都存在,只是形式不同而已。而且现在大环境不好,可能对个人的要求还更高一些。 背调的主…...

如何设计树形结构
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 前置知识:前…...

限量25台,川崎亮相Ninja ZX-10RR冬季限量款
最近川崎发布了自家ZX-10RR的超级限量版,官方称之为冬季测试版,之前也有一些车型推出过冬季测试版,通常是在年底推出,因为这个时候北半球都是非常寒冷的冬天。 不过这台ZX-10RR冬季测试版,并不仅仅只是限量那么简单&am…...

【QT八股文】系列之篇章1 | QT的基础知识及事件/机制
【QT八股文】系列之篇章1 | QT的基础知识及事件/机制 前言0. 基础Qt/PyQt5介绍/关联Qt的优缺点(为什么要用qt来做界面)Qt 的核心机制请简要介绍一下Qt中的主窗口(MainWindow)类,它有哪些重要的函数和成员变量ÿ…...

SpringBoot 3 集成Hive 3
前提条件: 运行环境:Hadoop 3.* Hive 3.* MySQL 8 ,如果还未安装相关环境,请参考:Hive 一文读懂 Centos7 安装Hadoop3 单机版本(伪分布式版本) SpringBoot 2 集成Hive 3 pom.xml <?xml ver…...

STL中优先队列的模拟实现与仿函数的介绍
文章目录 仿函数优先队列的模拟实现 仿函数 上回我们说到,优先队列的实现需要用到仿函数的特性 让我们再回到这里 这里我们发现他传入的用于比较的东西竟然是一个类模板,而不是我们所见到的函数 我们可以先创建一个类,用于比较大小 struc…...
LeetCode刷题--- 目标和
个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述递归递归、搜…...
【.NET Core】反射(Reflection)详解(二)
【.NET Core】反射(Reflection)详解(二) 文章目录 【.NET Core】反射(Reflection)详解(二)一、概述二、Type类2.1 Type对象表示哪些类型2.2 获取Type及其关联对象类型的方式2.3 Type…...

【错误记录/js】保存octet-stream为文件后数据错乱
目录 说在前面场景解决方式其他 说在前面 后端:go、gin浏览器:Microsoft Edge 120.0.2210.77 (正式版本) (64 位) 场景 前端通过点击按钮来下载一些文件,但是文件内容是一些非文件形式存储的二进制数据。 后端代码 r : gin.Default()r.Stat…...
sql_lab之sqli中的post注入
Post注入 用burpsuit抓包去做 Post第一关:(gxa5) 1.判断是否存在注入 username1or 11 #&password123&submit%E7%99%BB%E5%BD%95 有回显 username1or 12 #&password123&submit%E7%99%BB%E5%BD%95 没有回显 则证明存在sq…...

智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.白冠鸡算法4.实验参数设定5.算法结果6.参考文…...

DETR++: Taming Your Multi-Scale Detection Transformer论文解读
文章目录 前言一、摘要二、引言三、相关研究四、模型方法1、Removing the Encoder方法2、Multi-Head方法3、Shifted Windows方法4、Bi-directional Feature Pyramid方法5、DETR方法 五、实验结果总结 前言 今天查看了一篇DETR论文,本想网络上找博客大概浏览一下&am…...

高级数据结构 <二叉搜索树>
本文已收录至《数据结构(C/C语言)》专栏! 作者:ARMCSKGT 目录 前言正文二叉搜索树的概念二叉搜索树的基本功能实现二叉搜索树的基本框架插入节点删除节点查找函数中序遍历函数析构函数和销毁函数(后序遍历销毁)拷贝构造和赋值重载(前序遍历创建)其他函数…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...