【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 目录 前言正文二叉搜索树的概念二叉搜索树的基本功能实现二叉搜索树的基本框架插入节点删除节点查找函数中序遍历函数析构函数和销毁函数(后序遍历销毁)拷贝构造和赋值重载(前序遍历创建)其他函数…...
蚂蚁集团5大开源项目获开放原子 “2023快速成长开源项目”
12月16日,在开放原子开源基金会主办的“2023开放原子开发者大会”上,蚂蚁集团主导开源的图数据库TuGraph、时序数据库CeresDB、隐私计算框架隐语SecretFlow、前端框架OpenSumi、数据域大模型开源框架DB-GPT入选“2023快速成长开源项目”。 (图…...
SpringBoot+JaywayJsonPath实现Json数据的DSL(按照指定节点表达式解析json获取指定数据)
场景 若依前后端分离版手把手教你本地搭建环境并运行项目: 若依前后端分离版手把手教你本地搭建环境并运行项目_前后端分离项目本地运行-CSDN博客 在上面搭建SpringBoot项目的基础上,并且在项目中引入fastjson、hutool等所需依赖后。 Jayway JsonPat…...
气压计LPS28DFW开发(2)----水压检测
气压计LPS28DFW开发.2--水压检测 概述视频教学样品申请完整代码下载水压计算设置速率和分辨率轮询读取数据测试结果 概述 本文将介绍如何使用 LPS28DFW 传感器来读取的压强数据,来估算水下深度,可以利用液体静压的原理。 最近在弄ST和瑞萨RA的课程&…...
设计模式之-装饰模式,快速掌握装饰模式,通俗易懂的讲解装饰模式以及它的使用场景
系列文章目录 设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列 设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点 设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式,每一种模式的概念、使用…...
计算机网络个人小结
不同层的数据报的名称 应用层: data TCP层: segment IP 层: packet MAC层: frame MTU vs MSS: MTU:一个网络包的最大长度,以太网中一般为 1500 字节。 https://www.xiaolincoding.com/network/1_base/how_os_deal_network_package.html#linux-%E7%BD%91…...
酒店网站搭建的作用是什么
线上已经成为各行业商家增长破局的必要手段,传统酒店行业因信息扩展度不够,导致品牌难以传播、无法实现用户对酒店所有信息全面知悉,也无法实现在线预约及其它赋能用户消费的路径。 面对获客转化难题,很多酒店商家通过建立自营商…...
俄罗斯联邦税务局遭乌克兰入侵,数据库和副本被清空,政府数据安全不容忽视
俄罗斯联邦税务局遭乌克兰入侵,数据库和副本被清空,政府数据安全不容忽视 据相关报道,2023年12月12日,乌克兰国防情报局(GUR)称其成功入侵了俄罗斯联邦税务局(FNS)系统,并清除了该机构的数据库和…...
WPF组合控件TreeView+DataGrid之TreeView封装
(关注博主后,在“粉丝专栏”,可免费阅读此文) wpf的功能非常强大,很多控件都是原生的,但是要使用TreeViewDataGrid的组合,就需要我们自己去封装实现。 我们需要的效果如图所示&#x…...
redisson 哨兵模式配置
背景:项目redis由集群改为哨兵模式,漏洞扫描未授权访问漏洞(CNVD-2019-21763),要求对redis哨兵也设置密码,redisson依赖版本为3.11.5 spring-boot版本为2.1.13。 redisson依赖升级 <dependency>&l…...
免费的ChatGPT分享
免费的ChatGPT 以下是一些免费的ChatGPT平台和工具: 零声教学AI助手 零声教育内部使用的ChatGPT,提供智能对话和问题解答功能。 Ora.ai 一个可以自定义的AI聊天机器人,可以根据个人需求进行定制和训练。 ChatGPT 人工智能聊天机器人&a…...
网站克隆好后该怎么做/如何做好宣传推广
安装环境 操作系统:Windows 10。 被测平台:Android 模拟器或真实Android手机。 appium 服务器:appium Desktop。 appium 客户端:python-client。 Android Studio 我们既可以通过 Android 手机连接 PC 来运行 appium 自动化测试…...
如何查看用wordpress建的站点/阿拉营销网站
文章目录一、题目1、题目描述2、基础框架3、原题链接二、解题报告1、思路分析2、时间复杂度3、代码详解三、本题小知识四、加群须知一、题目 1、题目描述 设计一种算法,将一个新节点插入到一个完全二叉树中,并在插入后保持其完整。实现 CBTInserter类: …...
大淘客网站商品做淘口令/站长之家工具查询
今天周六,突然想看看自己这一周项目的进度,看看每天在GitHub提交了什么模块。 通过百度,找到了一个很简单的方法: 1.打开项目,点击“x commits” 2.查看历史的提交 补充:如果在我们在写代码、数次修改并提…...
网站权重怎么查询/百度app大全
MySQL的图形化界面的基本使用方法 一、首先将java.war放进tomact安装包下面的webapps下,然后运行bin/startup.bat,然后查看webapps下面时候新生成了一个和你的war包名相同的文件夹。二、编辑新生成的文件下的WEB-INF/classes/db-config.properties 原图如图…...
做网站广告哪家好/国内搜索引擎优化的公司
目录 404: (1)访问资源路径错误: (2)classes项目输出路径错误: (3)tomcat没有配置上下文context: 404: (1)访问资源路径错…...
php网站开发环境一/百度深圳总部
Java的字节码一般是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard的主要作用就是混淆。当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。 一、Android Eclipse开发环境…...