doubao_chat/apps/common/update/net_single_backup_update.c

1039 lines
34 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "app_config.h"
#include "update/update.h"
#include "fs/fs.h"
#include "syscfg/syscfg_id.h"
#include "update/update_loader_download.h"
#include "generic/errno-base.h"
#include "lwip/ip4_addr.h"
#include "wifi/wifi_connect.h"
#include "lwip/tcp.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
void sdfile_save_test(char *buf, int len, char one_file, char close);
void sdfile_read(void *buf, int offset, int len);
//========================网络单备份系统升级例子================================
#if (CONFIG_DOUBLE_BANK_ENABLE == 0)
#if 0
enum {
SEEK_SET = 0x01,
SEEK_CUR = 0x02
};
#endif
#ifdef CONFIG_WIFI_STA_MODE
#define HTTP_UPDATE_ENABLE 1 //1,STA模式下http断点续传OTA升级
#else
#define HTTP_UPDATE_ENABLE 0
#endif
#if HTTP_UPDATE_ENABLE
#define HTTP_UPDATE_PORT 80 //http端口
#define HTTP_RECV_BUF (20*1024) //http升级缓存大小
//HTTP升级的OTA升级文件网址
/*#define HTTP_UPDATE_URL "http://test02.jieliapp.com/file/2022/update-ota.ufw"*/
#define HTTP_UPDATE_URL "http://172.16.109.110:18888/update-ota.ufw"
#define HTTP_GET_HEAD "GET %s HTTP/1.1\r\n"\
"Host: %s\r\n"\
"User-Agent: User\r\n"\
"Accept: */*\r\n"\
"Connection: Close\r\n"\
"Range: bytes=%d-%d\r\n\r\n"
struct http_tcp {
struct ip4_addr ip_addr;
struct tcp_pcb *pcb;
unsigned char conneted: 1;
unsigned char lock: 7;
};
struct http_range_ota {
struct http_tcp tcp;
unsigned int file_size;//文件大小
unsigned int content_length;
unsigned int range_start;//断点续传起始
unsigned int range_end;//断点续传结束
unsigned int recv_offset;
unsigned int read_offset;
unsigned char *host;
unsigned char *file;
unsigned char *send_buf;
unsigned int buf_size;
unsigned char buf[0];
};
static struct http_range_ota *http_ota = NULL;
#endif
//升级端口
#define NET_UPDATE_PORT 3335
//升级状态
#define NET_UPDATE_STATUS_DOING (0 << 0)//设备端主动发送
#define NET_UPDATE_STATUS_OK (1 << 0)//设备端主动发送
#define NET_UPDATE_STATUS_ERR (1 << 1)//设备端主动发送
#define NET_UPDATE_STATUS_READ (1 << 2)//设备端主动发送
#define NET_UPDATE_STATUS_STOP (1 << 3)//APP主动的停止升级
#define NET_UPDATE_STATUS_SAME (1 << 4)//升级的是同一个固件
#define NET_OTA_FILE_RESV 0 //文件夹预留读取:0文件往后读取, 1往前读取
static struct tcp_pcb *client_pcb = 0;
static char client_accept = 0;
static char net_ota_stop = 0;
static char net_recv_err = 0;
#define OS_SEM_TIME_MAX 500 //5s
static OS_SEM read_sem;
//协议保持和APP和ota_loard一致
//协议:头部20字节
struct net_ota {
unsigned int sum_check;//设备端:头部16字节和校验,APP端:头部16字节+读取字节的和校验,(sum_check不加上和校验计算)
unsigned int seek_addr;//文件偏移地址
unsigned int read_size;//读取文件长度
unsigned int all_size;//升级过程中需要的文件总字节数(用在进度条),整个升级过程中会有一次的all_size > 0, 其他次all_size = 0
unsigned int status: 8; //升级转态,NET_UPDATE_STATUS_NONE正在升级,NET_UPDATE_STATUS_OK升级成功,NET_UPDATE_STATUS_ERR升级失败
unsigned int download_percent: 8; //升级过程中设备的百分比
unsigned int resv: 16; //预留,最后收到这4个字节代表成功和失败
unsigned char buf[0];
};
struct net_local { //除了buf以外,其他成员保持和struct net_ota一致
unsigned int sum_check;
unsigned int seek_addr;
unsigned int read_size;
unsigned int all_size;
unsigned int status: 8; //预留,最后发送这4个字节代表成功和失败
unsigned int download_percent: 8; //升级过程中设备的百分比
unsigned int resv: 16; //预留,最后发送这4个字节代表成功和失败
unsigned char *buf;//存留升级fread的地址
};
static u8 *ota_ram_addr = NULL; //OTA缓存地址,长度42*1024,42K
static struct net_local *net_local_addr = NULL;
static u32 ota_loard_size = 0;//OTA升级需要字节大小
static u32 ota_read_size = 0;//OTA升级代码后已读取的字节大小
#define NET_OTA_BUF_SIZE (20*1024) //务必<=40K,和APP相关
#define RECV_OFFSET_SIZE (sizeof(struct net_local))
#define RECV_BUF_MAX_SIZE (NET_OTA_BUF_SIZE - sizeof(struct net_local) - sizeof(struct net_ota))
#define NET_MAX_SIZE (RECV_BUF_MAX_SIZE)
#define NET_TCP_OTA (ota_ram_addr + sizeof(struct net_local))
#define UPDATE_IDLE 0
#define UPDATE_ERROR 1
#define UPDATE_DOING 2
#define UPDATE_SUCCES 3
#define UPDATE_STOP 4
static u8 update_succes_state = 0;
static unsigned int sumget(void *buf, int len)//和校验生成
{
unsigned char *pbuf = (unsigned char *)buf;
unsigned int sum = 0;
int i = 0;
while (i < len) {
sum += pbuf[i++];
}
return sum;
}
static int sumcheck(void *buf, int len, unsigned int sum)//和校验检测
{
unsigned char *pbuf = (unsigned char *)buf;
unsigned int sum_check = 0;
int i = 0;
while (i < len) {
sum_check += pbuf[i++];
}
if (sum_check != sum) {
printf("err sumcheck = 0x%x, 0x%x\n", sum_check, sum);
return -1;
}
return 0;
}
static int send_msg(struct tcp_pcb *pcb, u8 *buf, u32 len)//往TCP发送数据包
{
err_t err;
int size = tcp_sndbuf(pcb);
if (size < len) {
printf("err tcp no buf to send , %d , %d\n", size, len);
return 0;
}
size = MIN(size, len);
err = tcp_write(pcb, buf, size, 1);//往TCP发送数据包
if (err != ERR_OK) {
puts("tcp_write err \n");
return 0;
}
return size;
}
int msgsenddata(u8 *buf, u32 len, u8 no_wait)//读取缓冲区的指定地址和长度
{
int err = 0;
struct net_local *net_local = (struct net_local *)(buf);
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
if (len > RECV_OFFSET_SIZE) {
return 0;
}
if (client_pcb) {
int tcp_size = RECV_BUF_MAX_SIZE;
u32 read_size = 0;
if (net_local_addr->status == NET_UPDATE_STATUS_READ) {
if (!net_local->all_size) {
if (!net_ota->seek_addr && !net_ota->read_size) {
net_ota->seek_addr = net_local->seek_addr;
}
if (!net_ota->read_size || net_local->seek_addr < net_ota->seek_addr ||
((net_local->seek_addr + net_local->read_size) > (net_ota->seek_addr + net_ota->read_size))) {//没有数据则请求tcp
net_ota->all_size = 0;
net_ota->read_size = tcp_size;
net_ota->seek_addr = net_local->seek_addr;
} else {//二级缓存有数据则复制即可
memcpy(net_local->buf, net_ota->buf + (net_local->seek_addr - net_ota->seek_addr), net_local->read_size);
return net_local->read_size;
}
#if NET_OTA_FILE_RESV
if (net_ota->seek_addr > (RECV_BUF_MAX_SIZE - net_local->read_size)) {
net_ota->seek_addr -= (RECV_BUF_MAX_SIZE - net_local->read_size);
}
#endif
} else {
net_ota->all_size = net_local->all_size;
}
} else {
read_size = net_ota->read_size;
net_ota->read_size = 0;
net_ota->all_size = net_local->all_size ? net_local->all_size : net_ota->all_size;
}
os_sem_set(&read_sem, 0);
net_ota->download_percent = net_local_addr->download_percent;
net_ota->status = net_local_addr->status;//发送结果
net_ota->sum_check = sumget((char *)net_ota + sizeof(net_ota->sum_check), sizeof(struct net_ota) - sizeof(net_ota->sum_check));
err = send_msg(client_pcb, (u8 *)net_ota, len);
if (read_size) {
net_ota->read_size = read_size;
}
if (no_wait) {
return err;
}
if (os_sem_pend(&read_sem, OS_SEM_TIME_MAX)) {
return 0;
}
}
return err;
}
static err_t msgsend_buf(void *arg, struct tcp_pcb *pcb)
{
return ERR_OK;
}
static void msgerr(void *arg, err_t err)
{
}
static err_t msgpoll(void *arg, struct tcp_pcb *pcb)
{
return msgsend_buf(arg, pcb);
}
static err_t msgsent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
return msgsend_buf(arg, pcb);
}
static int msgclose(struct tcp_pcb *pcb)
{
if (pcb) {
if (client_accept > 0) {
client_accept--;
}
if (client_accept == 0 || client_pcb == pcb) {
client_pcb = NULL;
}
#if HTTP_UPDATE_ENABLE
http_ota->tcp.lock = 1;
#endif
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_err(pcb, NULL);
tcp_abort(pcb);//关闭tcp就发送RST复位断开tcp并释放tcp占用的内存池
/*tcp_close(pcb);*/
#if HTTP_UPDATE_ENABLE
if (http_ota && http_ota->tcp.pcb == pcb) {
http_ota->tcp.pcb = NULL;
http_ota->tcp.conneted = 0;
}
http_ota->tcp.lock = 0;
#endif
return ERR_ABRT;
}
return ERR_OK;
}
static err_t msgrecvmemcpy(void *arg, int len)
{
struct net_local *net_local = (struct net_local *)(ota_ram_addr);
struct net_ota *net_ota = (struct net_ota *)arg;
if (net_ota->status == NET_UPDATE_STATUS_STOP) {
net_local->status = net_ota->status;
net_ota_stop = 1;
} else if (net_local->read_size) {//复制当前请求的地址和大小到一级缓存
memcpy(net_local->buf, net_ota->buf + (net_local->seek_addr - net_ota->seek_addr), net_local->read_size);
}
os_sem_post(&read_sem);
return ERR_OK;
}
static err_t msgrecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
#if HTTP_UPDATE_ENABLE
struct http_range_ota *httpota = (struct http_range_ota *)arg;
if (!httpota) {
return ERR_OK;
}
if (err == ERR_OK && p != NULL) {
struct pbuf *q;
char Find = 0;
int tot_len = 0;
char *pt = (char *)httpota->buf + httpota->recv_offset;
int len = p->tot_len;
if ((httpota->recv_offset + len) <= httpota->buf_size) {
for (q = p; q != NULL; q = q->next) {
memcpy(pt, q->payload, q->len);
pt += q->len;
tot_len += q->len;
}
tcp_recved(pcb, tot_len);
/*printf("recv size : %d \n%s\n", tot_len, httpota->buf + httpota->recv_offset);*/
if (!httpota->recv_offset) {
char *p, *f, *c;
p = (char *)httpota->buf + httpota->recv_offset;
f = strstr(p, "HTTP/1.1 206");
/*sdfile_save_test(p, tot_len, 0, 1);*/
if (f) {
net_recv_err = 0;
c = strstr(f, "Content-Length:");
if (!c) {
c = strstr(f, "content-length:");
}
if (c) {
c += strlen("Content-Length:");
httpota->content_length = atoi(c);
}
c = strstr(f, "Content-Range:");
if (!c) {
c = strstr(f, "content-range:");
}
if (c) {
c += strlen("Content-Range:") + 1;
f = c;
while (c < (p + tot_len)) {
if (c[0] == '\r' && c[1] == '\n' && c[2] == '\r' && c[3] == '\n') {
c += 4;
Find = 1;
goto find;
}
if (c[0] == '\r' && c[1] == '\n') {
c += 2;
break;
}
if (c[0] == '/') {
httpota->file_size = atoi(++c);
/*printf("---> http ota file_size = %d \n", httpota->file_size);*/
}
c++;
}
f = strstr(f, "/");
if (f && f < c && !httpota->file_size) {
f += 1;
httpota->file_size = atoi(f);
/*printf("---> http ota file_size = %d \n",httpota->file_size);*/
}
} else {
c = f;
}
while (c < (p + tot_len)) {
if (c[0] == '\r' && c[1] == '\n' && c[2] == '\r' && c[3] == '\n') {
Find = 1;
c += 4;
break;
}
c++;
}
find:
if (Find) {
len = tot_len - (c - p);
memcpy(httpota->buf, c, len);
httpota->buf[len] = 0;
httpota->recv_offset += len;
} else {
printf("recv head data err\n");
goto err;
}
} else {
err:
printf("recv err \n");
net_recv_err++;
if (net_recv_err >= 3) {
net_recv_err = 0;
net_ota_stop = 1;
httpota->recv_offset = 0;
}
os_sem_post(&read_sem);
}
} else {
httpota->recv_offset += tot_len;
}
} else {
tcp_recved(pcb, p->tot_len);
}
pbuf_free(p);
/*printf("recv size : %d, request : %d \n", httpota->recv_offset, httpota->range_end - httpota->range_start);*/
//接收数据>=所请求字节,则接收数据完成
if (httpota->recv_offset && (httpota->recv_offset >= (httpota->range_end - httpota->range_start) || (http_ota->recv_offset >= http_ota->file_size && http_ota->file_size))) {
/*printf("---> recv size : %d, request : %d \n", httpota->recv_offset, httpota->range_end - httpota->range_start);*/
if (net_local_addr->buf && net_local_addr->read_size) {//复制到二级缓存20K里
memcpy(net_local_addr->buf, httpota->buf + (net_local_addr->seek_addr - httpota->range_start), net_local_addr->read_size);
}
os_sem_post(&read_sem);
}
}
#else
struct net_ota *net_ota = (struct net_ota *)arg;
if (!net_ota || !ota_ram_addr) {
return ERR_OK;
}
if (err == ERR_OK && p != NULL) {
struct pbuf *q;
char First = 0;
int tot_len = 0;
char *pt = (char *)net_ota + net_ota->all_size;
for (q = p; q != NULL; q = q->next) {
memcpy(pt, q->payload, q->len);
pt += q->len;
tot_len += q->len;
}
/*tcp_recved(pcb, p->tot_len);*/
tcp_recved(pcb, tot_len);
pbuf_free(p);
net_ota->all_size += tot_len;
if (net_ota->all_size >= (net_ota->read_size + sizeof(struct net_ota))) {//接收数据>=所请求字节,则接收数据完成
net_ota->all_size = 0;
//和校验检测,检测过才能复制到二级20K缓存
if (sumcheck((char *)net_ota + sizeof(net_ota->sum_check), net_ota->read_size + sizeof(struct net_ota) - sizeof(net_ota->sum_check), net_ota->sum_check)) {
} else { //和校验成功
msgrecvmemcpy(net_ota, tot_len);
}
}
}
#endif
else if (err == ERR_OK && p == NULL) {
puts("msgrecv close tcp\n");
return msgclose(pcb);
}
return ERR_OK;
}
static err_t msgaccept(void *arg, struct tcp_pcb *pcb, err_t err)
{
client_accept++;
if (client_accept > 1) {
printf("client_accept = %d \n", client_accept);
return msgclose(pcb);
} else {
client_pcb = pcb;
tcp_arg(pcb, NET_TCP_OTA);
tcp_recv(pcb, msgrecv);
tcp_sent(pcb, msgsent);
tcp_err(pcb, msgerr);
tcp_poll(pcb, msgpoll, 1);
int net_ota_single_back_update(void);//100ms后初始化单备份升级
sys_timeout_add_to_task("sys_timer", NULL, net_ota_single_back_update, 100);
puts("client accept ok\n");
}
return ERR_OK;
}
#if HTTP_UPDATE_ENABLE
static err_t tcp_dataconnected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct http_range_ota *httpota = (struct http_range_ota *)arg;
tcp_recv(pcb, msgrecv);
tcp_sent(pcb, msgsent);
tcp_err(pcb, msgerr);
httpota->tcp.conneted = 1;
puts("connet server ok\n");
return ERR_OK;
}
static int http_get(const char *url, char reset, int size)
{
int port = 0;
if (!url || !http_ota) {
goto exit;
}
char *p = strstr(url, "http://");
if (!p) {
goto exit;
}
p += strlen("http://");
char *e = strstr(p, ":");
int len = 0;
if (e) {
len = e - p;
if (len >= http_ota->buf_size) {
goto exit;
}
e++;
port = atoi(e);
e = strstr(p, "/");
} else {
e = strstr(p, "/");
if (e) {
len = e - p;
if (len >= http_ota->buf_size) {
goto exit;
}
} else {
http_ota->host = NULL;
http_ota->file = NULL;
http_ota->send_buf = NULL;
http_ota->recv_offset = 0;
http_ota->file_size = 0;
goto exit;
}
}
http_ota->host = http_ota->buf;
memcpy(http_ota->host, p, len);
http_ota->host[len] = 0;
http_ota->send_buf = http_ota->host + len + 1;
http_ota->file = NULL;
http_ota->recv_offset = 0;
if ((strlen(e) + len + 2) < http_ota->buf_size) {
http_ota->file = http_ota->host + len + 1;
len = strlen(e);
memcpy(http_ota->file, e, len);
http_ota->file[len] = 0;
http_ota->send_buf = http_ota->file + len + 1;
}
if (!http_ota->tcp.ip_addr.addr || reset) {
if (!atoi(http_ota->host)) {
printf("http gethostbyname\n");
struct hostent *host_ent = gethostbyname(http_ota->host);//域名解析
if (!host_ent) {
printf(" . ! lwip analayse ip err !!!\r\n");
goto exit;
}
http_ota->tcp.ip_addr.addr = *((u32_t *)host_ent->h_addr);
} else {
http_ota->tcp.ip_addr.addr = inet_addr(http_ota->host);
}
printf("http update DNS remoute ip : %s \n", inet_ntoa(http_ota->tcp.ip_addr.addr));
http_ota->file_size = 0;
}
while (http_ota->tcp.lock) {
os_time_dly(1);
}
http_ota->tcp.lock = 1;
struct tcp_pcb *pcb = tcp_new();
if (!pcb) {
goto exit;
}
ip_addr_t ip;
tcp_arg(pcb, http_ota);
IP_SET_TYPE_VAL(ip, IPADDR_TYPE_V4);
ip4_addr_copy(*ip_2_ip4(&ip), http_ota->tcp.ip_addr);
http_ota->tcp.pcb = pcb;
port = port ? port : HTTP_UPDATE_PORT;
if (tcp_connect(pcb, &ip, port, tcp_dataconnected) != ERR_OK) {
tcp_connect(pcb, &ip, 8080, tcp_dataconnected);
}
int cnt = 10 * 100;
while (!http_ota->tcp.conneted && --cnt) {
os_time_dly(10);
}
if (!cnt || net_ota_stop) {
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_err(pcb, NULL);
tcp_close(pcb);
http_ota->tcp.pcb = NULL;
http_ota->tcp.ip_addr.addr = 0;
goto exit;
}
size = size ? size : http_ota->buf_size;
if (http_ota->file_size && (http_ota->range_start + http_ota->buf_size) > http_ota->file_size) {
size = http_ota->file_size - http_ota->range_start;
}
http_ota->range_end = http_ota->range_start + size;
if (http_ota->send_buf) {
if (!http_ota->file) {
http_ota->file = "/";
}
sprintf(http_ota->send_buf, HTTP_GET_HEAD, http_ota->file, http_ota->host, http_ota->range_start, http_ota->range_end - 1);
/*printf("HTTP_GET_HEAD : \n%s\n", http_ota->send_buf);*/
len = strlen(http_ota->send_buf);
if (send_msg(pcb, http_ota->send_buf, len) != len) {//发送http数据头
goto exit;
}
}
http_ota->tcp.lock = 0;
return 0;
exit:
http_ota->tcp.lock = 0;
puts("http update err !!! \n");
return -EINVAL;
}
static int http_read(void *priv, char reset)
{
struct net_local *net_local = (struct net_local *)priv;
if (!http_ota || !net_local) {
return 0;
}
if (!http_ota->range_start && !http_ota->recv_offset) {
http_ota->range_start = net_local->seek_addr;
}
if (!http_ota->recv_offset || net_local->seek_addr < http_ota->range_start ||
((net_local->seek_addr + net_local->read_size) > (http_ota->range_start + http_ota->recv_offset))) {//没有数据或第一次则请求tcp
http_ota->recv_offset = 0;
http_ota->range_start = net_local->seek_addr;
} else {//二级缓存有数据则复制即可
memcpy(net_local->buf, http_ota->buf + (net_local->seek_addr - http_ota->range_start), net_local->read_size);
return net_local->read_size;
}
#if NET_OTA_FILE_RESV
if (http_ota->range_start > (http_ota->buf_size - net_local->read_size)) {
http_ota->range_start -= (http_ota->buf_size - net_local->read_size);
}
#endif
u8 cnt = 3;
redo:
os_sem_set(&read_sem, 0);
if (http_get(HTTP_UPDATE_URL, reset, 0)) {
return 0;
}
if (os_sem_pend(&read_sem, OS_SEM_TIME_MAX)) {
return 0;
}
if (net_recv_err && --cnt && !net_ota_stop) {
goto redo;
}
return net_local->read_size ? net_local->read_size : http_ota->buf_size;
}
static int http_stop(int err)
{
if (http_ota) {
http_ota->tcp.lock = 1;
if (http_ota->tcp.pcb) {
tcp_arg(http_ota->tcp.pcb, NULL);
tcp_sent(http_ota->tcp.pcb, NULL);
tcp_recv(http_ota->tcp.pcb, NULL);
tcp_err(http_ota->tcp.pcb, NULL);
tcp_close(http_ota->tcp.pcb);
}
http_ota->tcp.lock = 0;
http_ota->tcp.pcb = NULL;
http_ota->tcp.ip_addr.addr = 0;
http_ota->tcp.conneted = 0;
memset(http_ota->buf, 0, http_ota->buf_size);
memset(http_ota, 0, sizeof(struct http_range_ota));
}
return 0;
}
#endif
int net_ota_single_back_init(void)
{
#if HTTP_UPDATE_ENABLE
int size = HTTP_RECV_BUF;
if (!http_ota) {
http_ota = malloc(size);
}
if (http_ota) {
memset(http_ota, 0, size);
http_ota->buf_size = size - sizeof(struct http_range_ota);
puts("http update init ok \n");
} else {
return -1;
}
os_sem_create(&read_sem, 0);
syscfg_write(VM_HTTP_SINGLE_UPDATE_URL, (char *)HTTP_UPDATE_URL, strlen(HTTP_UPDATE_URL) + 1);
printf("---> HTTP_UPDATE_URL = %s \n", HTTP_UPDATE_URL);
#else
int err = 0;
int cnt = 0;
if (ota_ram_addr) {
printf("net_ota_single_back_init already\n");
return 0;
}
if (!ota_ram_addr) {
ota_ram_addr = malloc(NET_OTA_BUF_SIZE);
if (!ota_ram_addr) {
printf("net_ota_single_back_init err , no mem\n");
return -1;
}
}
memset(ota_ram_addr, 0, NET_OTA_BUF_SIZE);
struct tcp_pcb *pcb = tcp_new();
if (!pcb) {
printf("tcp_new err\n");
return -1;
}
tcp_bind(pcb, IP_ADDR_ANY, NET_UPDATE_PORT);
pcb = tcp_listen(pcb);
if (!pcb) {
tcp_close(pcb);
printf("tcp_new err\n");
return -1;
}
tcp_accept(pcb, msgaccept);
os_sem_create(&read_sem, 0);
puts("net_ota_open, wait APP accept .....\n");
#endif
return 0;
}
static u16 net_ota_single_back_fs_open(void)
{
#if HTTP_UPDATE_ENABLE
int size = HTTP_RECV_BUF;
if (!net_local_addr) {
net_local_addr = malloc(sizeof(struct net_local));
if (!net_local_addr) {
return false;
}
}
if (!http_ota) {
http_ota = malloc(size);
if (!http_ota) {
return false;
}
}
memset(http_ota, 0, size);
memset(net_local_addr, 0, sizeof(struct net_local));
http_ota->buf_size = size - sizeof(struct http_range_ota);
net_local_addr->download_percent = 1;
net_ota_stop = 0;
if (!http_read((void *)net_local_addr, 1)) {
puts("net_f_open err\n");
return false;
}
#else
int cnt = 500;//5秒
if (!ota_ram_addr) {
return false;
}
while (!client_pcb && --cnt) {
os_time_dly(10);
}
if (!cnt) { //等待APP连接超时
return false;
}
os_sem_set(&read_sem, 0);
//清空数据
net_local_addr = (struct net_local *)ota_ram_addr;
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
memset(net_ota, 0, sizeof(struct net_ota));
memset(net_local_addr, 0, sizeof(struct net_local));
net_ota_stop = 0;
net_local_addr->download_percent = 1;
#endif
printf("net_ota open ok\n");
return true;
}
static int net_ota_single_back_fs_seek(void *fp, u8 type, u32 offset)
{
#if HTTP_UPDATE_ENABLE
if (!net_local_addr) {
return -1;
}
#else
if (!net_local_addr || !ota_ram_addr) {
return (int) - 1;
}
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
return 0;
}
#endif
if (type == SEEK_SET) {
net_local_addr->seek_addr = offset;
} else {
net_local_addr->seek_addr += offset;
}
//printf("---> seek_addr = 0x%X \n",net_local_addr->seek_addr);
return 0;
}
static int net_ota_single_back_fs_need_size(void *p, u32 len)//第一次发送本次升级的总字节
{
#if HTTP_UPDATE_ENABLE
if (!net_local_addr || net_ota_stop || !len) {
return -1;
}
net_local_addr->all_size = len;
ota_loard_size = len ? len : 0;
ota_read_size = 0;
#else
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop || !len) {
return -1;
}
net_local_addr->seek_addr = 0;
net_local_addr->read_size = 0;
net_local_addr->all_size = len;
net_local_addr->status = len ? 0 : NET_UPDATE_STATUS_SAME;
net_local_addr->resv = 0;
ota_loard_size = len ? len : 0;
ota_read_size = 0;
msgsenddata(net_local_addr, sizeof(struct net_ota), 0);
#endif
return 0;
}
static u16 net_ota_single_back_fs_read(void *fp, u8 *buff, u16 len)
{
int err;
#if HTTP_UPDATE_ENABLE
int cnt = 3;
if (!net_local_addr || net_ota_stop) {
printf("err ota read\n");
return 0;
}
if (ota_loard_size) {
u8 percent = (unsigned long long)ota_read_size * 100 / ota_loard_size;
u8 last_percent = net_local_addr->download_percent;
net_local_addr->download_percent = percent > net_local_addr->download_percent ? percent : net_local_addr->download_percent;
net_local_addr->download_percent = net_local_addr->download_percent < 100 ? net_local_addr->download_percent : 99;
if (net_local_addr->download_percent != last_percent) {
/*printf("update >> %d%%\n", net_local_addr->download_percent);*/
}
}
net_local_addr->read_size = len;
net_local_addr->resv = 0;
net_local_addr->buf = buff;
/*os_sem_set(&read_sem, 0);*/
/*printf("---> read = %d, seek = %d \n", len, net_local_addr->seek_addr);*/
redo:
cnt--;
if (!http_read((void *)net_local_addr, 0)) {
if (cnt) {
goto redo;
}
puts("http_read err\n");
return 0;
}
#else
if (!net_local_addr || !ota_ram_addr) {
printf("err ota read\n");
return 0;
}
if (len > NET_MAX_SIZE) {
printf("err ota read size\n");
return 0;
}
net_local_addr->read_size = len;
net_local_addr->status = NET_UPDATE_STATUS_READ;
net_local_addr->resv = 0;
net_local_addr->buf = buff;
net_local_addr->all_size = 0;
if (ota_loard_size) {
u8 percent = (unsigned long long)ota_read_size * 100 / ota_loard_size;
net_local_addr->download_percent = percent > net_local_addr->download_percent ? percent : net_local_addr->download_percent;
net_local_addr->download_percent = net_local_addr->download_percent < 100 ? net_local_addr->download_percent : 99;
}
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
printf("err ota read net_ota_stop\n");
return 0;
}
if (!msgsenddata(net_local_addr, sizeof(struct net_ota), 0)) {
puts("net_f_read err\n");
}
if (net_local_addr->status == NET_UPDATE_STATUS_STOP || net_ota_stop) {
printf("err ota read net_ota_stop\n");
return 0;
}
#endif
net_local_addr->seek_addr += net_local_addr->read_size;
if (ota_loard_size) {
ota_read_size += net_local_addr->read_size;
}
return net_local_addr->read_size;
}
static u16 net_ota_single_back_fs_stop(u8 err)
{
u8 same = err & ~UPDATE_RESULT_FLAG_BITMAP;
switch (same) {
case UPDATE_RESULT_UPDATE_FILE_SAME:
update_succes_state = UPDATE_STOP;
break;
default:
break;
}
#if HTTP_UPDATE_ENABLE
if (!net_local_addr) {
return -1;
}
http_stop(err);
memset(net_local_addr, 0, sizeof(struct net_local));
#else
if (!net_local_addr || !ota_ram_addr) {
return (int) - 1;
}
memset(net_local_addr, 0, sizeof(struct net_local));
if (client_pcb) {
net_local_addr->read_size = 0;
if (!err) { //先发送100%
net_local_addr->status = 0;//发送结果
if (ota_loard_size) {
net_local_addr->download_percent = 100;
}
msgsenddata(net_local_addr, sizeof(struct net_ota), 0);
os_time_dly(50);
}
net_local_addr->status = err ? NET_UPDATE_STATUS_ERR : NET_UPDATE_STATUS_OK;//发送结果
msgsenddata(net_local_addr, sizeof(struct net_ota), 1);
net_local_addr->status = 0;
net_local_addr->download_percent = 0;
}
os_time_dly(50);
net_local_addr = NULL;
if (client_pcb) {
puts("client_pcb close\n");
msgclose(client_pcb);
}
//清空数据
struct net_ota *net_ota = (struct net_ota *)(NET_TCP_OTA);
memset(net_ota, 0, sizeof(struct net_ota));
#endif
net_ota_stop = 0;
ota_loard_size = 0;
ota_read_size = 0;
puts("net_ota_fs_stop ok\n");
return true;
}
static const update_op_api_t net_ota_single_back_fs_update_opt = {
.f_open = net_ota_single_back_fs_open,
.f_read = net_ota_single_back_fs_read,
.f_seek = net_ota_single_back_fs_seek,
.f_stop = net_ota_single_back_fs_stop,
.notify_update_content_size = net_ota_single_back_fs_need_size,
};
//单备份升级
static void net_ota_single_back_fs_update_param_private_handle(UPDATA_PARM *p)
{
}
static void net_ota_single_back_fs_update_state_cbk(int type, u32 state, void *priv)
{
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
switch (state) {
case UPDATE_CH_EXIT:
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
update_succes_state = UPDATE_SUCCES;
UPDATA_PARM *update_ram = UPDATA_FLAG_ADDR;
memset(update_ram, 0, 32);
UPDATA_PARM *p = UPDATA_FLAG_ADDR + sizeof(UPDATA_PARM);
if (support_dual_bank_update_en) {
memset(update_ram, 0, sizeof(UPDATA_PARM));
update_ram->magic = type;
update_result_set(UPDATA_SUCC);
printf(">>>>>>>>>>>>>>>>>>update ok , cpu reset ...\n");
} else {
//单备份
update_mode_api_v2(type, net_ota_single_back_fs_update_param_private_handle, NULL);
}
#if HTTP_UPDATE_ENABLE
wifi_enter_sta_mode("#@!$%^&*()##$$", "#@!$%^&*()##$$");
os_time_dly(200);
#else
void wifi_all_sta_discon(void);
wifi_all_sta_discon();//断开所有连接STA
os_time_dly(200);
#endif
system_reset();
} else {
if (update_succes_state == UPDATE_DOING) {
update_succes_state = UPDATE_ERROR;
}
update_result_set(UPDATA_DEV_ERR);
printf("\nupdate err !!! \n");
}
break;
}
}
#if HTTP_UPDATE_ENABLE
int net_ota_single_back_update(void);
int net_ota_single_back_update_state(void)
{
static u8 update_retry_cnt = 0;//升级失败尝试次数
switch (update_succes_state) {
case UPDATE_ERROR:
if (++update_retry_cnt < 6) {
sys_timeout_add(NULL, net_ota_single_back_update, 500);
} else {
update_retry_cnt = 0;
}
break;
case UPDATE_SUCCES:
case UPDATE_STOP:
update_retry_cnt = 0;
break;
default:
sys_timeout_add(NULL, net_ota_single_back_update_state, 500);
break;
}
return (int)update_succes_state;
}
#endif
//单备份网络升级例子
int net_ota_single_back_update(void)
{
printf("\n>>>>>>>>>>>>net_ota_single_back_update\n");
#if HTTP_UPDATE_ENABLE
if (net_ota_single_back_init()) {//http下先初始化
return -1;
}
sys_timeout_add(NULL, net_ota_single_back_update_state, 500);
#endif
update_mode_info_t info = {
.type = NET_UFW_UPDATA,
.state_cbk = net_ota_single_back_fs_update_state_cbk,
.p_op_api = &net_ota_single_back_fs_update_opt,
.task_en = 1,
};
update_succes_state = UPDATE_DOING;
app_active_update_task_init(&info);
return 0;
}
#endif
//===============sta模式下的http单备份升级例子===========================//
static void net_single_http_update_doing(void)
{
#if HTTP_UPDATE_ENABLE
int state = wifi_get_sta_connect_state();
switch (state) {
case WIFI_STA_NETWORK_STACK_DHCP_SUCC:
net_ota_single_back_update();//获取IP后启动单备份升级流程
return;
case WIFI_STA_CONNECT_TIMEOUT_NOT_FOUND_SSID:
puts("NOT_FOUND_SSID\n");
break;
case WIFI_STA_CONNECT_ASSOCIAT_TIMEOUT:
puts("CONNECT_ASSOCIAT_TIMEOUT\n");
break;
default:
break;
}
sys_timeout_add(NULL, net_single_http_update_doing, 500);//定时500ms检测是否连上网络
#endif
}
//应用层调用函数例子
void net_single_http_update_test(void)
{
#if HTTP_UPDATE_ENABLE
sys_timeout_add(NULL, net_single_http_update_doing, 500);//定时500ms检测是否连上网络
#endif
}