526 lines
16 KiB
C
526 lines
16 KiB
C
#include <stdarg.h>
|
|
#include "ql_type.h"
|
|
#include "ql_data_call.h"
|
|
#include "ql_rtos.h"
|
|
#include "ql_application.h"
|
|
#include <stdio.h>
|
|
#include "sockets.h"
|
|
#include "ql_uart.h"
|
|
#include "ql_func.h"
|
|
#include "netdb.h"
|
|
#include "ql_sim.h"
|
|
#include "ql_dev.h"
|
|
#include "ql_wtd.h"
|
|
#include "MQTTClient.h"
|
|
|
|
#include "ql_fs.h"
|
|
#include "ql_fota.h"
|
|
#include "ql_sim.h"
|
|
|
|
#include "ql_ping.h"
|
|
#include "ql_nw.h"
|
|
#include "ql_atcmd.h"
|
|
|
|
#include "cJSON.h"
|
|
#include "build_macro.h"
|
|
|
|
|
|
#define MQTT_SERVER_DOMAIN "47.113.99.138"
|
|
#define MQTT_SERVER_PORT 1883
|
|
|
|
#define FOTA_TITLE_DEFAULT "EG800AK_AI"
|
|
|
|
#define MQTT_DOWNLOAD_CHUNK 512
|
|
#define MAX_PAYLOAD_LEN 512 // 限制payload大小防止缓冲区溢出
|
|
|
|
|
|
//#define MINIFOTA
|
|
#define FULLFOTA
|
|
|
|
ql_task_t mqtt_auth_task = NULL;
|
|
int mqtt_task_run_flag = 0;
|
|
|
|
int mqtt_task_fota_check_flag = 0;
|
|
MQTTClient mqtt_client = {0};
|
|
|
|
static char g_imei_buf[32]={0};
|
|
int fota_start = 0;
|
|
|
|
typedef struct
|
|
{
|
|
int type;
|
|
uint8_t *buf;
|
|
int buf_len;
|
|
}app_queue_msg;
|
|
|
|
static ql_queue_t mqtt_data_task_msg_queue = NULL;
|
|
|
|
|
|
#define TARGET_VER_FILE "U:/target_ver_file.txt"
|
|
|
|
int read_target_ver(uint8_t *buff, int len)
|
|
{
|
|
QFILE * fp = NULL;
|
|
int ret = -1;
|
|
if(ql_access(TARGET_VER_FILE, 0)!=0){
|
|
printf("read %s not is exist\n", TARGET_VER_FILE);
|
|
return -1;
|
|
}
|
|
|
|
fp = ql_fopen(TARGET_VER_FILE, "r");
|
|
|
|
if(NULL == fp)
|
|
{
|
|
printf("[FS]ERROR!!! *** file open fail: %s \r\n", TARGET_VER_FILE);
|
|
return -1;
|
|
}
|
|
|
|
ret = ql_fread(buff, len, 1, fp);
|
|
if(ret < 0)
|
|
{
|
|
printf("[FS]ERROR!!! *** file read fail: %s \r\n", TARGET_VER_FILE);
|
|
}
|
|
|
|
ql_fclose(fp);
|
|
fp = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int save_target_ver(uint8_t *buff, int len)
|
|
{
|
|
QFILE * fp = NULL;
|
|
int ret = -1;
|
|
|
|
fp = ql_fopen(TARGET_VER_FILE, "w+");
|
|
|
|
if(NULL == fp)
|
|
{
|
|
printf("[FS]ERROR!!! *** file open fail: %s \r\n", TARGET_VER_FILE);
|
|
return -1;
|
|
}
|
|
|
|
ret = ql_fwrite(buff, len, 1, fp);
|
|
if(ret < 0)
|
|
{
|
|
printf("[FS]ERROR!!! *** file write fail: %s \r\n", TARGET_VER_FILE);
|
|
}
|
|
|
|
ql_fclose(fp);
|
|
fp = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void messageArrived(MessageData* data)
|
|
{
|
|
printf("Message arrived on topic %.*s: %.*s\r\n", data->topicName->lenstring.len, (char*)data->topicName->lenstring.data,data->message->payloadlen, (char*)data->message->payload);
|
|
if(!strncmp(data->topicName->lenstring.data,"v1/devices/me/attributes/response/",strlen("v1/devices/me/attributes/response/"))){
|
|
app_queue_msg *msg = NULL;
|
|
msg = malloc(sizeof(app_queue_msg));
|
|
if(msg){
|
|
msg->buf = malloc(data->message->payloadlen+1);
|
|
msg->buf_len = data->message->payloadlen;
|
|
msg->type = 1;
|
|
if(msg->buf){
|
|
memset(msg->buf,0,msg->buf_len+1);
|
|
memcpy(msg->buf,data->message->payload,msg->buf_len);
|
|
}
|
|
ql_rtos_queue_release(mqtt_data_task_msg_queue, sizeof(app_queue_msg *), (u8*)(&msg), 3000);
|
|
}
|
|
}
|
|
#if 0
|
|
else if(!strncmp(data->topicName->lenstring.data,"v2/fw/response/",strlen("v2/fw/response/"))){
|
|
app_queue_msg *msg = NULL;
|
|
msg = malloc(sizeof(app_queue_msg));
|
|
if(msg){
|
|
msg->buf = malloc(data->message->payloadlen);
|
|
msg->buf_len = data->message->payloadlen;
|
|
msg->type = 2;
|
|
if(msg->buf){
|
|
memset(msg->buf,0,msg->buf_len);
|
|
memcpy(msg->buf,data->message->payload,msg->buf_len);
|
|
}
|
|
ql_rtos_queue_release(mqtt_data_task_msg_queue, sizeof(app_queue_msg *), (u8*)(&msg), 3000);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void MQTTEchoTask(void *argv)
|
|
{
|
|
/* connect to m2m.eclipse.org, subscribe to a topic, send and receive messages regularly for 3 times */
|
|
Network network = {0};
|
|
MQTTMessage message={0};
|
|
char payload[128];
|
|
char tempbuf[128]={0};
|
|
unsigned char sendbuf[512] = {0};
|
|
int rc = 0;
|
|
static uint32_t request_id = 1;
|
|
MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
|
|
unsigned char *readbuf=NULL;
|
|
qlFotaImgProcCtxPtr fota_ctx = NULL;
|
|
app_queue_msg *msg = NULL;
|
|
uint32_t file_size = 0;
|
|
int i;
|
|
int read_len = 0;
|
|
int dl_len = 0;
|
|
int update_flag = 0;
|
|
char target_ver[128]={0};
|
|
char buf_fw_url[128]={0};
|
|
char download_url1[128]={0};
|
|
char download_url2[128]={0};
|
|
char buf_talkingq_id[64]={0};
|
|
char buf_talkingq_sn[64]={0};
|
|
char buf_talkingq_url[64]={0};
|
|
char build_ver[128]={0};
|
|
cJSON *recv = NULL;
|
|
|
|
readbuf = malloc(MQTT_DOWNLOAD_CHUNK+128);
|
|
if(readbuf == NULL){
|
|
printf("MQTTEchoTask: malloc readbuf failed\r\n");
|
|
goto exit;
|
|
}
|
|
|
|
hal_os_get_build_ver(build_ver);
|
|
|
|
NetworkInit(&network, NULL, 1);
|
|
MQTTClientInit(&mqtt_client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, MQTT_DOWNLOAD_CHUNK+128);
|
|
|
|
char* address = MQTT_SERVER_DOMAIN;
|
|
if ((rc = NetworkConnect(&network, address, MQTT_SERVER_PORT)) != 0)
|
|
{
|
|
printf("Return code from network connect is %d\r\n", rc);
|
|
MQTTClientDeinit(&mqtt_client);
|
|
goto exit;
|
|
}
|
|
|
|
connectData.MQTTVersion = 3;
|
|
connectData.clientID.cstring = g_imei_buf;
|
|
connectData.username.cstring = g_imei_buf;
|
|
connectData.password.cstring = g_imei_buf;
|
|
|
|
if ((rc = MQTTConnect(&mqtt_client, &connectData)) != 0)
|
|
{
|
|
printf("Return code from MQTT connect is %d\r\n", rc);
|
|
NetworkDisconnect(&network);
|
|
MQTTClientDeinit(&mqtt_client);
|
|
goto exit;
|
|
}
|
|
else{
|
|
printf("MQTT Connected\r\n");
|
|
}
|
|
|
|
//上次更新是否成功
|
|
read_target_ver(target_ver,sizeof(target_ver));
|
|
if(strlen(target_ver)>0){
|
|
|
|
printf("read target:%s\r\n", target_ver);
|
|
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
|
|
if(!strcmp(target_ver,build_ver)){
|
|
// 安全修复:使用snprintf防止缓冲区溢出
|
|
snprintf(payload, sizeof(payload), "{\"current_fw_title\":\"%s\",\"current_fw_version\":\"%s\",\"fw_state\":\"UPDATED\"}",FOTA_TITLE_DEFAULT,build_ver);
|
|
message.payloadlen = strlen(payload);
|
|
}else{
|
|
snprintf(payload, sizeof(payload), "{\"current_fw_title\":\"%s\",\"current_fw_version\":\"%s\",\"fw_state\":\"FAILED\"}",FOTA_TITLE_DEFAULT,build_ver);
|
|
message.payloadlen = strlen(payload);
|
|
}
|
|
if ((rc = MQTTPublish(&mqtt_client, "v1/devices/me/telemetry", &message)) != 0){
|
|
printf("Return code from MQTT publish v1/devices/me/telemetry UPDATED is %d\r\n", rc);
|
|
}
|
|
memset(target_ver,0,sizeof(target_ver));
|
|
//把版本信息清除
|
|
save_target_ver(target_ver,sizeof(target_ver));
|
|
}
|
|
memset(target_ver,0,sizeof(target_ver));
|
|
|
|
#if defined(MQTT_TASK)
|
|
if ((rc = MQTTStartTask(&mqtt_client)) != 0)
|
|
{
|
|
printf("Return code from start tasks is %d\r\n", rc);
|
|
NetworkDisconnect(&network);
|
|
MQTTClientDeinit(&mqtt_client);
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
if ((rc = MQTTSubscribe(&mqtt_client, "v1/devices/me/attributes/response/+", 1, messageArrived)) != 0)
|
|
{
|
|
printf("Return code from MQTT subscribe attributes/response is %d", rc);
|
|
|
|
goto dis_exit;
|
|
}
|
|
|
|
if ((rc = MQTTSubscribe(&mqtt_client, "v1/devices/me/attributes", 1, messageArrived)) != 0)
|
|
{
|
|
printf("Return code from MQTT subscribe attributes is %d", rc);
|
|
|
|
goto dis_exit;
|
|
}
|
|
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
// 安全修复:使用snprintf防止缓冲区溢出
|
|
snprintf(payload, sizeof(payload), "{\"current_fw_title\":\"%s\",\"current_fw_version\":\"%s\"}",FOTA_TITLE_DEFAULT,build_ver);
|
|
message.payloadlen = strlen(payload);
|
|
|
|
if ((rc = MQTTPublish(&mqtt_client, "v1/devices/me/telemetry", &message)) != 0){
|
|
printf("Return code from MQTT publish current_fw is %d\r\n", rc);
|
|
}
|
|
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
#if 0
|
|
sprintf(payload, "{\"sharedKeys\":\"fw_checksum,fw_checksum_algorithm,fw_size,fw_title,fw_version\"}");
|
|
#else
|
|
// 安全修复:使用snprintf
|
|
snprintf(payload, sizeof(payload), "{\"sharedKeys\":\"talkingq_url,talkingq_id,talkingq_sn,fw_title,fw_version,fw_url\"}");
|
|
#endif
|
|
message.payloadlen = strlen(payload);
|
|
// 安全修复:使用snprintf
|
|
snprintf(tempbuf, sizeof(tempbuf), "v1/devices/me/attributes/request/%d",request_id);
|
|
if ((rc = MQTTPublish(&mqtt_client, tempbuf, &message)) != 0){
|
|
printf("Return code from MQTT publish request is %d\r\n", rc);
|
|
goto dis_exit;
|
|
}
|
|
|
|
if(0!=ql_rtos_queue_wait(mqtt_data_task_msg_queue, (u8*)(&msg), sizeof(msg), 5000)){
|
|
printf("wait for request req errrrrrrrr\r\n");
|
|
goto dis_exit;
|
|
}
|
|
|
|
if(msg->type!=1){
|
|
printf("wait for request type errrrrrrrr %d\r\n",msg->type);
|
|
goto dis_exit;
|
|
}
|
|
|
|
if(msg->buf==NULL){
|
|
printf("msg->buf null errrrrrrrr \r\n");
|
|
goto dis_exit;
|
|
}
|
|
|
|
//maybe cJSON
|
|
|
|
recv = cJSON_Parse(msg->buf);
|
|
if(recv){
|
|
cJSON *sharedkeys = cJSON_GetObjectItem(recv,"shared");
|
|
if(sharedkeys){
|
|
cJSON *item = cJSON_GetObjectItem(sharedkeys,"talkingq_url");
|
|
if(item){
|
|
strcpy(tempbuf,item->valuestring);
|
|
printf("talkingq_url: %s\r\n",tempbuf);
|
|
hal_os_get_talkingq_url(buf_talkingq_url);
|
|
if(strlen(tempbuf)>0 && strcmp(tempbuf,buf_talkingq_url)){
|
|
hal_os_set_talkingq_url(tempbuf);
|
|
}
|
|
}else{
|
|
printf("not find talkingq_url,\r\n");
|
|
}
|
|
item = cJSON_GetObjectItem(sharedkeys,"talkingq_id");
|
|
if(item){
|
|
strcpy(tempbuf,item->valuestring);
|
|
printf("talkingq_id: %s\r\n",tempbuf);
|
|
hal_os_get_device_id(buf_talkingq_id);
|
|
if(strlen(tempbuf)>0 && strcmp(tempbuf,buf_talkingq_id)){
|
|
hal_os_set_device_id(tempbuf);
|
|
}
|
|
}else{
|
|
printf("not find talkingq_id,\r\n");
|
|
}
|
|
|
|
item = cJSON_GetObjectItem(sharedkeys,"talkingq_sn");
|
|
if(item){
|
|
strcpy(tempbuf,item->valuestring);
|
|
printf("talkingq_sn: %s\r\n",tempbuf);
|
|
hal_os_get_device_sn(buf_talkingq_sn);
|
|
if(strlen(tempbuf)>0 && strcmp(tempbuf,buf_talkingq_sn)){
|
|
hal_os_set_device_sn(tempbuf);
|
|
}
|
|
}else{
|
|
printf("not find talkingq_sn,\r\n");
|
|
}
|
|
|
|
item = cJSON_GetObjectItem(sharedkeys,"fw_version");
|
|
if(item){
|
|
strcpy(target_ver,item->valuestring);
|
|
printf("fw_version: %s\r\n",target_ver);
|
|
}else{
|
|
printf("not find fw_version,\r\n");
|
|
memset(target_ver,0,sizeof(target_ver));
|
|
}
|
|
|
|
item = cJSON_GetObjectItem(sharedkeys,"fw_url");
|
|
if(item){
|
|
strcpy(buf_fw_url,item->valuestring);
|
|
printf("fw_url: %s\r\n",buf_fw_url);
|
|
}else{
|
|
printf("not find fw_url\r\n");
|
|
memset(buf_fw_url,0,sizeof(buf_fw_url));
|
|
}
|
|
}else{
|
|
printf("shared item not json error.\r\n");
|
|
memset(target_ver,0,sizeof(target_ver));
|
|
memset(buf_fw_url,0,sizeof(buf_fw_url));
|
|
goto dis_exit;
|
|
}
|
|
cJSON_Delete(recv);
|
|
recv = NULL;
|
|
}else{
|
|
printf("shared keys parse not json error.\r\n");
|
|
goto dis_exit;
|
|
}
|
|
|
|
memset(buf_talkingq_id,0,sizeof(buf_talkingq_id));
|
|
memset(buf_talkingq_sn,0,sizeof(buf_talkingq_sn));
|
|
memset(buf_talkingq_url,0,sizeof(buf_talkingq_url));
|
|
|
|
hal_os_get_device_id(buf_talkingq_id);
|
|
hal_os_get_device_sn(buf_talkingq_sn);
|
|
hal_os_get_talkingq_url(buf_talkingq_url);
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
// 安全修复:使用snprintf防止溢出
|
|
snprintf(payload, sizeof(payload), "{\"current_talkingq_url\":\"%s\",\"current_talkingq_id\":\"%s\",\"current_talkingq_sn\":\"%s\"}",buf_talkingq_url,buf_talkingq_id,buf_talkingq_sn);
|
|
message.payloadlen = strlen(payload);
|
|
|
|
if ((rc = MQTTPublish(&mqtt_client, "v1/devices/me/telemetry", &message)) != 0){
|
|
printf("Return code from MQTT publish current_talkingq is %d\r\n", rc);
|
|
}
|
|
|
|
if(!strcmp(build_ver,target_ver)){
|
|
printf("version not need update!!!!!!\r\n");
|
|
mqtt_task_fota_check_flag = 1;
|
|
goto dis_exit;
|
|
}
|
|
|
|
if(strlen(buf_fw_url)<=0 || strlen(target_ver)<=0){
|
|
printf("no buf_fw_url or target_ver not need update!!!!!!\r\n");
|
|
goto dis_exit;
|
|
}
|
|
|
|
/*
|
|
.\adiff.exe system_old.img system_new.img jx_fota.bin -a1 customer_app customer_app.bin -u updater.bin
|
|
*/
|
|
//download url:"http://405j9o6444.qicp.vip/jx_fota.bin_1"
|
|
printf("download url:%s\r\n", buf_fw_url);
|
|
if(strstr(buf_fw_url, "bin")!=NULL)
|
|
{
|
|
//#define FOTA_SERVER_ADDRESS_STEP1 "http://405j9o6444.qicp.vip/jx_fota.bin_1"
|
|
//#define FOTA_SERVER_ADDRESS_STEP2 "http://405j9o6444.qicp.vip/jx_fota.bin_2"
|
|
//进入升级前 保存升级版本信息
|
|
save_target_ver(target_ver,strlen(target_ver)+1);
|
|
|
|
memcpy(download_url1,buf_fw_url, strlen(buf_fw_url)+1);
|
|
//memcpy(download_url2,buf_fw_url, strlen(buf_fw_url)+1);
|
|
//download_url2[strlen(download_url2)] = '2';
|
|
|
|
|
|
printf("download_url1:%s\r\n", download_url1);
|
|
//printf("download_url2:%s\r\n", download_url2);
|
|
|
|
update_flag = 1;
|
|
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
// 安全修复:使用snprintf防止溢出
|
|
snprintf(payload, sizeof(payload), "{\"current_fw_title\":\"%s\",\"current_fw_version\":\"%s\",\"fw_state\":\"UPDATING\"}",FOTA_TITLE_DEFAULT,build_ver);
|
|
message.payloadlen = strlen(payload);
|
|
if ((rc = MQTTPublish(&mqtt_client, "v1/devices/me/telemetry", &message)) != 0){
|
|
printf("Return code from MQTT publish v1/devices/me/telemetry DOWNLOADED is %d\r\n", rc);
|
|
}
|
|
|
|
app_play_tips_file(3);
|
|
fota_start = 1;
|
|
|
|
ql_rtos_task_sleep_ms(5000);
|
|
|
|
#ifdef MINIFOTA
|
|
//printf("download_url1:%s\r\n",download_url1);
|
|
//printf("download_url2:%s\r\n",download_url2);
|
|
ql_fota_mini_system(1, QL_FOTA_DWNLD_MOD_HTTP, download_url1 ,download_url2, NULL,NULL);
|
|
#endif
|
|
#ifdef FULLFOTA
|
|
ql_fullfota_app_start(download_url1);
|
|
#endif
|
|
}
|
|
|
|
dis_exit:
|
|
request_id++;
|
|
mqtt_task_fota_check_flag = 1;
|
|
if(update_flag){
|
|
message.qos = 1;
|
|
message.retained = 0;
|
|
message.payload = payload;
|
|
// 安全修复:使用snprintf防止溢出
|
|
snprintf(payload, sizeof(payload), "{\"current_fw_title\":\"%s\",\"current_fw_version\":\"%s\",\"fw_state\":\"FAILED\"}",FOTA_TITLE_DEFAULT,build_ver);
|
|
message.payloadlen = strlen(payload);
|
|
if ((rc = MQTTPublish(&mqtt_client, "v1/devices/me/telemetry", &message)) != 0){
|
|
printf("Return code from MQTT publish v1/devices/me/telemetry DOWNLOADED is %d\r\n", rc);
|
|
}
|
|
}
|
|
|
|
if(msg!=NULL){
|
|
if(msg->buf!=NULL){
|
|
free(msg->buf);
|
|
}
|
|
free(msg);
|
|
msg = NULL;
|
|
}
|
|
|
|
rc = MQTTDisconnect(&mqtt_client);
|
|
if(rc == SUCCESS)
|
|
printf("MQTT Disconnected by client\r\n");
|
|
else
|
|
printf("MQTT Disconnected failed by client\r\n");
|
|
|
|
NetworkDisconnect(&network);
|
|
|
|
MQTTClientDeinit(&mqtt_client);
|
|
mqtt_task_run_flag = 2;
|
|
exit:
|
|
|
|
if(readbuf){
|
|
free(readbuf);
|
|
}
|
|
|
|
if(recv){
|
|
cJSON_Delete(recv);
|
|
}
|
|
|
|
printf("========== mqtt test end ==========");
|
|
if(mqtt_task_run_flag==1)
|
|
mqtt_task_run_flag = 0;
|
|
|
|
ql_rtos_task_delete(NULL);
|
|
}
|
|
|
|
|
|
void app_fota_init(void)
|
|
{
|
|
char build_ver[128]={0};
|
|
memset(g_imei_buf,0,sizeof(g_imei_buf));
|
|
ql_dev_get_imei(g_imei_buf,sizeof(g_imei_buf));
|
|
printf("g_imei_buf:%s\r\n", g_imei_buf);
|
|
|
|
hal_os_get_build_ver(build_ver);
|
|
|
|
printf("\r\n\r\n************************************\r\nVERSION:%s\r\n************************************\r\n\r\n", build_ver);
|
|
|
|
ql_rtos_queue_create(&mqtt_data_task_msg_queue, sizeof(app_queue_msg), 1);
|
|
|
|
if(mqtt_task_run_flag==0){
|
|
if(mqtt_task_fota_check_flag==1)return;
|
|
mqtt_task_run_flag = 1;
|
|
ql_rtos_task_create(&mqtt_auth_task, 10*1024, 100, "mqtt_auth", MQTTEchoTask, NULL);
|
|
}
|
|
|
|
}
|