188 lines
4.8 KiB
C
188 lines
4.8 KiB
C
/********************************测试例程说明************************************
|
||
* 功能说明:
|
||
* 通过HTTP协议,下载URL指定的网络升级文件存储至指定路径,并进行升级固件。
|
||
*/
|
||
|
||
#include "system/includes.h"
|
||
#include "os/os_api.h"
|
||
#include "http/http_cli.h"
|
||
#include "fs/fs.h"
|
||
#include <stdlib.h>
|
||
#include "storage_device.h"
|
||
#include "net_update.h"
|
||
#include "app_config.h"
|
||
#include "wifi/wifi_connect.h"
|
||
|
||
#ifdef USE_HTTP_UPGRADE_DEMO1
|
||
|
||
#define OTA_URL_ADDR "https://test02.jieliapp.com/tmp/2021/12/29/update-ota.ufw"
|
||
|
||
#define DEFAULT_RECV_BUF_SIZE (4*1024) //数据缓存BUF大小
|
||
#define MAX_RECONNECT_CNT 10 //最大重连次数
|
||
|
||
struct download_hdl {
|
||
char *url; //下载链接
|
||
u32 file_size; //需要下载的文件大小
|
||
u8 *recv_buf; //数据缓存BUF
|
||
u32 recv_buf_size; //数据缓存BUF大小
|
||
u32 download_len; //已下载的数据长度
|
||
u32 reconnect_cnt; //重连次数
|
||
httpcli_ctx ctx; //http请求参数
|
||
const struct net_download_ops *download_ops; //http操作集
|
||
};
|
||
|
||
struct download_parm {
|
||
char *url; //下载链接
|
||
};
|
||
|
||
//http回调函数
|
||
static int http_user_cb(void *ctx, void *buf, unsigned int size, void *priv, httpin_status status)
|
||
{
|
||
struct download_hdl *hdl = (struct download_hdl *)priv;
|
||
|
||
if (status == HTTPIN_HEADER) {
|
||
//第一次连接时,记录文件总长度
|
||
if (hdl->ctx.lowRange == 0) {
|
||
hdl->file_size = hdl->ctx.content_length;
|
||
}
|
||
|
||
log_e("http_need_download_file=%d KB", hdl->file_size / 1024);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void download_task(void *priv)
|
||
{
|
||
struct download_hdl *hdl = priv;
|
||
void *update_fd = NULL;
|
||
int ret = 0;
|
||
int err = 0;
|
||
char sock_err = 0;
|
||
|
||
update_fd = net_fopen(CONFIG_UPGRADE_OTA_FILE_NAME, "w");
|
||
if (!update_fd) {
|
||
log_e("open update_fd error\n");
|
||
goto _out_;
|
||
}
|
||
|
||
_reconnect_:
|
||
//发起连接请求,建立socket连接
|
||
ret = hdl->download_ops->init(&hdl->ctx);
|
||
|
||
if (ret != HERROR_OK) {
|
||
if (hdl->ctx.req_exit_flag == 0) {
|
||
if (hdl->reconnect_cnt < MAX_RECONNECT_CNT) {
|
||
hdl->reconnect_cnt++;
|
||
goto _reconnect_;
|
||
} else {
|
||
log_e("download reconnect upto max count.\n");
|
||
goto _out_;
|
||
}
|
||
}
|
||
}
|
||
|
||
while (hdl->ctx.req_exit_flag == 0) {
|
||
ret = hdl->download_ops->read(&hdl->ctx, (char *)hdl->recv_buf, hdl->recv_buf_size);//最大接收为recv_buf_size
|
||
if (ret < 0) { //读取数据失败
|
||
sock_err = 1;
|
||
goto _out_;
|
||
} else {
|
||
hdl->download_len += ret;
|
||
err = net_fwrite(update_fd, hdl->recv_buf, ret, 0);
|
||
if (err != ret) {
|
||
goto _out_;
|
||
}
|
||
}
|
||
|
||
if (hdl->download_len >= hdl->file_size) {
|
||
goto _finish_;
|
||
}
|
||
}
|
||
|
||
_finish_:
|
||
printf("download success.\n");
|
||
|
||
net_fclose(update_fd, sock_err);
|
||
system_reset();
|
||
|
||
_out_:
|
||
//关闭网络连接
|
||
hdl->download_ops->close(&hdl->ctx);
|
||
|
||
net_fclose(update_fd, sock_err);
|
||
free(hdl->url);
|
||
free(hdl->recv_buf);
|
||
memset(hdl, 0, sizeof(struct download_hdl));
|
||
free(hdl);
|
||
}
|
||
|
||
static int http_create_download_task(void)
|
||
{
|
||
struct download_parm parm = {0};
|
||
struct download_hdl *hdl = NULL;
|
||
|
||
parm.url = OTA_URL_ADDR;
|
||
|
||
//申请堆内存
|
||
hdl = (struct download_hdl *)calloc(1, sizeof(struct download_hdl));
|
||
|
||
if (hdl == NULL) {
|
||
return -ENOMEM;
|
||
}
|
||
|
||
hdl->download_ops = &http_ops;
|
||
hdl->recv_buf_size = DEFAULT_RECV_BUF_SIZE;
|
||
|
||
hdl->url = (char *)calloc(1, strlen(parm.url) + 1);
|
||
|
||
if (hdl->url == NULL) {
|
||
return -ENOMEM;
|
||
}
|
||
|
||
hdl->recv_buf = (u8 *)calloc(1, hdl->recv_buf_size);
|
||
|
||
if (hdl->recv_buf == NULL) {
|
||
return -ENOMEM;
|
||
}
|
||
|
||
strcpy(hdl->url, parm.url);
|
||
|
||
//http请求参数赋值
|
||
hdl->ctx.url = hdl->url;
|
||
hdl->ctx.cb = http_user_cb;
|
||
hdl->ctx.priv = hdl;
|
||
hdl->ctx.connection = "close";
|
||
|
||
//创建下载线程
|
||
return thread_fork("download_task", 20, 2 * 1024, 0, NULL, download_task, hdl);
|
||
}
|
||
|
||
static void http_upgrade_start(void *priv)
|
||
{
|
||
enum wifi_sta_connect_state state;
|
||
|
||
while (1) {
|
||
printf("Connecting to the network...\n");
|
||
state = wifi_get_sta_connect_state();
|
||
if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
|
||
printf("Network connection is successful!\n");
|
||
break;
|
||
}
|
||
|
||
os_time_dly(1000);
|
||
}
|
||
|
||
http_create_download_task();
|
||
}
|
||
|
||
//应用程序入口,需要运行在STA模式下
|
||
void c_main(void *priv)
|
||
{
|
||
if (thread_fork("http_upgrade_start", 10, 512, 0, NULL, http_upgrade_start, NULL) != OS_NO_ERR) {
|
||
printf("thread fork fail\n");
|
||
}
|
||
}
|
||
|
||
late_initcall(c_main);
|
||
#endif
|