萤火工场 GD32VW553-IOT
分享作者:wx17579048808993
评测品牌:萤火工场
评测型号:GD32VW553-IOT-V2
发布时间:2025-10-23 09:50:09
1
前言
实现了使用WIFI功能进行HTTPS请求获取timeis网站的时间信息,实现开发板与互联网时间同步
开源口碑分享内容

在程序中编写代码完成了WIFI模块的初始化,HTTPS请求,HTTPS获取的HTML文件解析

下面是HTTPS请求的代码

static void https_client_test(void)

{

int ret, len;

mbedtls_net_context server_fd;

unsigned int flags;

unsigned char buf[2048]; // HTML响应可能较长


mbedtls_ssl_context ssl;

mbedtls_ssl_config conf;

mbedtls_x509_crt ca_cert;


mbedtls_debug_set_threshold(1);

mbedtls_net_init(&server_fd);

mbedtls_ssl_init(&ssl);

mbedtls_ssl_config_init(&conf);

mbedtls_x509_crt_init(&ca_cert);


// ====== 加载证书 ======

ret = mbedtls_x509_crt_parse(&ca_cert,

(const unsigned char *)timeis_ca_crt,

strlen(timeis_ca_crt) + 1);

if (ret < 0) {

printf("Failed to parse CA cert -0x%x\r\n", -ret);

goto exit;

}


// ====== 建立 TCP 连接 ======

printf("Connecting to %s:%s...\r\n", SERVER_NAME, SERVER_PORT);

if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT,

MBEDTLS_NET_PROTO_TCP)) != 0) {

printf("TCP connect failed %d\r\n", ret);

goto exit;

}


// ====== 配置 SSL ======

if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,

MBEDTLS_SSL_TRANSPORT_STREAM,

MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {

printf("ssl_config_defaults failed %d\r\n", ret);

goto exit;

}

mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);

mbedtls_ssl_conf_rng(&conf, my_random, NULL);

mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);

mbedtls_ssl_conf_ca_chain(&conf, &ca_cert, NULL);

mbedtls_ssl_conf_verify(&conf, my_verify, NULL);

//启用服务器要求的曲线

{

const mbedtls_ecp_group_id curve_list[] = {

MBEDTLS_ECP_DP_SECP256R1,

MBEDTLS_ECP_DP_SECP384R1,

MBEDTLS_ECP_DP_NONE

};

mbedtls_ssl_conf_curves(&conf, curve_list);

printf("Configured curve list: SECP256R1, SECP384R1\n");

}

if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {

printf("ssl_setup failed %d\r\n", ret);

goto exit;

}


if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {

printf("set_hostname failed %d\r\n", ret);

goto exit;

}


mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);


// ====== TLS 握手 ======

printf("TLS handshake...\r\n");

while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {

if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {

printf("Handshake failed -0x%x\r\n", -ret);

goto exit;

}

}

printf("Handshake success!\r\n");


// ====== 发送 HTTP 请求 ======

len = snprintf((char *)buf, sizeof(buf),

"GET / HTTP/1.1\r\n"

"Host: %s\r\n"

"User-Agent: GD32HTTPSClient\r\n"

"Connection: close\r\n"

"\r\n",

SERVER_NAME);


ret = mbedtls_ssl_write(&ssl, buf, len);

if (ret <= 0) {

printf("SSL write failed %d\r\n", ret);

goto exit;

}


// ====== 读取响应并提取时间 ======

printf("Reading response...\r\n");

memset(buf, 0, sizeof(buf));

size_t total_len = 0;

do {

ret = mbedtls_ssl_read(&ssl, buf + total_len, sizeof(buf) - total_len - 1);

if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)

continue;

if (ret <= 0)

break;

total_len += ret;

} while (total_len < sizeof(buf) - 1);


buf[total_len] = '\0';

printf("Received %u bytes.\r\n", (unsigned)total_len);


struct tm parsed;

if (parse_time_from_title((char *)buf, &parsed) == 0) {

printf("Parsed time from <title>: %04d-%02d-%02d %02d:%02d:%02d\r\n",

parsed.tm_year + 1900, parsed.tm_mon + 1, parsed.tm_mday,

parsed.tm_hour, parsed.tm_min, parsed.tm_sec);

} else {

printf("Could not parse time from HTML <title>.\r\n");

}



mbedtls_ssl_close_notify(&ssl);


exit:

if (ret < 0) {

char errbuf[128];

mbedtls_strerror(ret, errbuf, sizeof(errbuf));

printf("Error: %s\r\n", errbuf);

}


mbedtls_net_free(&server_fd);

mbedtls_x509_crt_free(&ca_cert);

mbedtls_ssl_free(&ssl);

mbedtls_ssl_config_free(&conf);

}

下面是HTML解析的代码:


static int parse_time_from_title(const char *html, struct tm *out_tm)

{

const char *expires_start = strstr(html, "Expires: ");

if (expires_start) {

// 跳过 "Expires: " 前缀

expires_start += 9;


// 解析日期时间格式: Wed, 22 Oct 2025 21:07:4

char day[4], month[4];

int day_num, year, hour, min, sec;


if (sscanf(expires_start, "%3s, %d %3s %d %d:%d:%d",

day, &day_num, month, &year, &hour, &min, &sec) == 7) {


// 将月份名称转换为数字

int month_num = -1;

const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",

"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

for (int i = 0; i < 12; i++) {

if (strncmp(month, months[i], 3) == 0) {

month_num = i;

break;

}

}


if (month_num != -1) {

memset(out_tm, 0, sizeof(struct tm));

out_tm->tm_year = year - 1900;

out_tm->tm_mon = month_num;

out_tm->tm_mday = day_num;

out_tm->tm_hour = hour;

out_tm->tm_min = min;

out_tm->tm_sec = sec;

out_tm->tm_isdst = -1;

return 0;

}

}

}

return 0;

}

全部评论
暂无评论
0/144