随手用libcurl写个ota框框

本文介绍了一个基于C语言实现的OTA固件更新流程,通过使用libcurl库进行HTTP请求,实现了从服务器下载固件文件的功能,并详细展示了状态管理、进度回调及错误处理等关键部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include <time.h>
#include <string.h>

#define SOCK_TIMEOUT 5

#define OTA_STATE_NOTREADY           0
#define OTA_STATE_READY              1
#define OTA_STATE_CONNECTING         2
#define OTA_STATE_GETHEAD            3
#define OTA_STATE_DOWNLOADING        4
#define OTA_STATE_DOWNLOADFINISH     5
#define OTA_STATE_ERROR              6

#define MAIN_LOG(format, ...) printf("[%u][%s:%d]:"format"\r\n",(unsigned int)time(NULL),__FILE__,__LINE__, ##__VA_ARGS__)

static int ota_state = OTA_STATE_NOTREADY;
static float download_ratio = 0.0;
static int force_stop_ota = 0;
static CURLcode last_code = CURLE_OK;
static char *target_url = NULL;

static void (*get_event_cb)(int, void*) = NULL;

void set_event_cb(void(*func)(int, void*))
{
	get_event_cb = func;
}

void set_target_url(char *target)
{
	if(target_url){
		free(target_url);
	}

	target_url = strdup(target);
}

int ota_get_last_error()
{
	return last_code;
}

void stop_ota()
{
	force_stop_ota = 1;
}

static void ota_set_state(int state)
{
	ota_state = state;
	MAIN_LOG("%d", state);
	if(get_event_cb){
		if(state != OTA_STATE_DOWNLOADING){
			get_event_cb(state, NULL);
		}else{
			get_event_cb(state, &download_ratio);
		}
	}
}

int ota_get_state()
{
	return ota_state;
}

float ota_get_download_ratio()
{
	return download_ratio;
}

size_t header_cb(void *ptr, size_t size, size_t nmemb, void *stream) 
{

	if(OTA_STATE_ERROR != ota_get_state() && OTA_STATE_GETHEAD != ota_get_state()){
		ota_set_state(OTA_STATE_GETHEAD);
	}
	//printf("%s",ptr);
	return force_stop_ota ? (size * nmemb + 1) : (size * nmemb);
}

size_t wirte_cb(void *ptr, size_t size, size_t nmemb, void *stream)
{

	if(OTA_STATE_ERROR != ota_get_state() && OTA_STATE_DOWNLOADING != ota_get_state()){
		ota_set_state(OTA_STATE_DOWNLOADING);
	}

	//printf("%s",ptr);

	return force_stop_ota ? (size * nmemb + 1) : (size * nmemb);
}

int progress_cb(void *ptr, double t, double d, double ultotal, double ulnow)
{

	printf("%d / %d (%f %%)\n", (int)d, (int)t, d*100.0/t);

	float tmp = d*100.0/t;
	
	if(ota_state == OTA_STATE_DOWNLOADING && get_event_cb && download_ratio < tmp){
		download_ratio = tmp;
		get_event_cb(ota_state, &download_ratio);
	} 

	return 0;
}

void print_event(int event, void *args)
{
	MAIN_LOG("event is %d", event);
	if(args)MAIN_LOG("ratio is %f",*(float*)args);
}

int main(int argc, char **argv)
{
	CURL *curl_handle = NULL;
	CURLcode r = CURLE_GOT_NOTHING;
	struct curl_slist* headers = NULL;

	curl_global_init(CURL_GLOBAL_ALL);
	curl_handle = curl_easy_init();

	set_event_cb(print_event);

	headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
	headers = curl_slist_append(headers, "username:jun");
	headers = curl_slist_append(headers, "password:123456");
	curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);

	set_target_url("http://192.168.233.1/ota.bin");
	if(!target_url){
		goto exit;
	}
	curl_easy_setopt(curl_handle, CURLOPT_URL, target_url);

	curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, SOCK_TIMEOUT);
	curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, SOCK_TIMEOUT);

	curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_cb);
	curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, NULL);

	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, wirte_cb);
	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, NULL);

	curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L);
	curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, progress_cb);
	curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, NULL);

	curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);

	ota_set_state(OTA_STATE_CONNECTING);

	r = curl_easy_perform(curl_handle);
	last_code = r;
	if (r == CURLE_OK){
		ota_set_state(OTA_STATE_DOWNLOADFINISH);
	} else {
		ota_set_state(OTA_STATE_ERROR);
		fprintf(stderr, "%s\n", curl_easy_strerror(r));
	}

exit:
	if(!target_url){
		free(target_url);
		target_url = NULL;
	}

	force_stop_ota = 0;

	curl_slist_free_all(headers);
	curl_easy_cleanup(curl_handle);
	curl_global_cleanup();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值