#include #include "ql_type.h" #include "ql_data_call.h" #include "ql_rtos.h" #include "ql_application.h" #include #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); } }