#include "includes.h" #define LEARN_HTTP_URL "test.rtpoc.com" #define LEARN_PORT 8000 #define PAGE_SIZE 5//一页能显示多少条 #define LEARN_LIST "learnLists" //任务简表总表 #define LEARN_LIST_TMP "learnListsTmp" //临时任务简表总表 #define LEARN_RANK "learnRank" //排名临时表,不需要删除 #define LEARN_CLASS "learnClass" #define LEARN_NOTICE "learnNotice" #define LEARN_UPDATE_MAX 10 //一次性最多拉取任务个数 #define SHOW_TABLE_MAX_BYTES 40 #define OBJECT_LIST "list" #define OBJECT_TID "tid" #define OBJECT_VER "ver" #define OBJECT_TITLE "t" #define OBJECT_SCORE "s" #define OBJECT_CONTENT "c" #define OBJECT_FINISH "f" #define OBJECT_UID "uid" #define OBJECT_GID "gid" #define OBJECT_GNAME "groupName" #define OBJECT_NNAME "nickname" #define OBJECT_TYPE "type" #define OBJECT_TOKEN "token" #define OBJECT_CONTENT_DETAIL "content" #define OBJECT_SPEED_PARAM "scoreSpeedParam" #define OBJECT_VOLUME_PARAM "scoreVolumeParam" static void httpCallBack(char *msg, int len); typedef enum{ LEARN_DB_GET_INFO,//获取用户信息 LEARN_DB_WAIT_INFO,//等待用户信息 LEARN_GET_LIST,//获取任务列表 LEARN_WAIT_LIST,//等待列表 LEARN_DB_SYNC,//同步数据 LEARN_DB_SYNC_DEL,//同步本地多了的任务(删除) LEARN_DB_SYNC_ADD,//同步本地没有的任务(获取) LEARN_DB_SYNC_ADD_PAGE_WAIT,//等待页任务获取 LEARN_DB_SYNC_ADD_SOME_WAIT,//等待部分任务获取 LEARN_DB_SYNC_DONE,//同步完成 LEARN_DB_SYNC_FAILED,//同步失败 LEARN_READ_TASK_INFO,//读取任务用于显示 LEARN_READ_FAILED,//用于读取任务过程出现失败或错误时退出使用 LEARN_SHOW_MENU, LEARN_WAIT_RESPONSE,//按键响应 LEARN_RECORD_UPLOAD, LEARN_RELEASE_DB, LEARN_END, LEARN_RANK_GET_DETAIL, LEARN_CLASS_GET_DETAIL, LEARN_NOTICE_GET_DETAIL, LEARN_NOTICE_GET_DETAIL_SHOW, LEARN_GET_PARAM, }LEARN_STATUS; static unsigned char charaNum;//单词个数 static unsigned int taskID[LEARN_UPDATE_MAX]; static unsigned int taskNum=0; static unsigned char learnAddNum;//添加任务时,添加的个数 static LEARN_STATUS learnStatus; static unsigned short learnPage; static unsigned int learnTick; static int learnTaskNum; static int learnPageNum; static bool learnDetailEnd; unsigned char rankType;//获取的排名类型 0 月排名 其它 周排名 static void pocAudioCtl(bool status){ if(status==false){ msgAtSend("AT+POC=0C0000\r\n");//停止POC录音 msgAtSend("AT+HTTS=0\r\n");//停止TTS,防止TTS播放还未完成时,就使用学习录音了 sutApp.skipTTS=1;//本地也不能再使用TTS msgAtSend("AT+POC=060000\r\n");//强制停止POC使用对讲播放 nwy_sleep(50);//给点时间POC完成切换 }else{//恢复 sutApp.skipTTS=0; msgAtSend("AT+POC=070000\r\n"); } } bool isLearnBusy(void){ static bool pocIsEnable=true; if(sutUIstatus.Status==UIS_MENU_TASK_QUERY){//需要禁止POC if(true==pocIsEnable){ pocIsEnable=false; pocAudioCtl(pocIsEnable); MSG_INFO(1, "Disable poc ctl"); } return true; }else{//需要开启POC if(false==pocIsEnable){ pocIsEnable=true; pocAudioCtl(pocIsEnable); MSG_INFO(1, "Enable poc ctl"); } return false; } } static char *getLearnFileJson(const char *fname); void sdCardCtl(bool status){ if(status==true){ CTL_SD_PWR(1); if(true!=nwy_sdk_sdcard_mount()){ MSG_ERR(1, "SD card mount failed"); CTL_SD_PWR(0); }else MSG_INFO(1, "SD card mount ok"); }else{ nwy_sdk_sdcard_unmount(); CTL_SD_PWR(0); MSG_INFO(1, "SD card unmount"); } } static void learnUpdateStatus(LEARN_STATUS newStatus){ learnStatus=newStatus; } static LEARN_STATUS getLearnStatus(void){ return learnStatus; } void showInfoBox(const char *info,int dly){ guiShowMessageBox(info); uTimerStart(&learnTick, dly); } void releaseBuf(unsigned char **pointer){ if(*pointer==NULL) return; free(*pointer); MSG_INFO(1, "[mem free]%x",*pointer); *pointer=NULL; } void releaseJson(cJSON** json){ if(*json==NULL) return; cJSON_Delete(*json); MSG_INFO(1, "[json del]%x",*json); *json=NULL; } void *createBuf(unsigned int size){ void *buf; buf=malloc(size); if(buf != NULL) MSG_INFO(1, "[mem malloc]%x", buf); return buf; } cJSON* createJson(char *msg){ cJSON* tmp; tmp=cJSON_Parse(msg); if(tmp != NULL) MSG_INFO(1, "[json add]%x", tmp); return tmp; } //从json中获取objString的Value,只用于获取key:value格式 static char *learnJsonGetItem(cJSON* json, const char *objString){ if(NULL==json) return NULL; cJSON* t=cJSON_GetObjectItem(json, objString); if(NULL==t) return NULL; else return t->valuestring; } //删除simpleList,simpleListTmp重命名为simpleList void learnUpdateListFile(void){ char oldFile[50],newFile[50]; snprintf(oldFile, sizeof(oldFile), "%s/%s",SD_TOKEN, LEARN_LIST); snprintf(newFile, sizeof(newFile), "%s/%s",SD_TOKEN, LEARN_LIST_TMP); //删除文件 if(true==nwy_sdk_fexist(oldFile)) nwy_sdk_file_unlink(oldFile); //重命名文件 if(true==nwy_sdk_fexist(newFile)){ nwy_sdk_frename(newFile, oldFile); MSG_INFO(1, "Learn Rename file:%s->%s",LEARN_LIST_TMP,LEARN_LIST); } } void learnGetNextPage(short direction){ if(direction==0) learnPage=0; else if(direction>0){ if(++learnPage>=learnPageNum) learnPage=0; }else{ if(learnPage==0) learnPage=learnPageNum-1; else learnPage--; } //得到page后,先检测本地是否已存有任务 } /*********************从文件中获取用户信息******************************/ typedef struct{ bool paramReady; double scoreSpeedParam; double scoreVolumeParam; bool ready; unsigned char type; unsigned int uid; unsigned int gid; char gname[30]; char nname[30]; char token[20]; }USER_INFO; USER_INFO usr={false,1,1,false,0xff}; unsigned int getLearnUid(void){return usr.uid;} unsigned int getLearnGid(void){return usr.gid;} char *getLearnGName(void){return usr.gname;} char *getLearnToken(void){return usr.token;} double getLearnSpeedParam(void){return usr.scoreSpeedParam;} bool isUserInfoReady(void){return usr.ready;} bool isUserStudent(void){//type为0是老师,否则为学生 if(usr.type==0) return false; else return true; } void learnUserInfoClear(void){usr.ready=false;} /* {"uid":"5028","groupName":"测试组3","gid":"21731","nickname":"用户30","type":"1","token":"120a1a7436"} */ bool cJSONProcessUinfo(char *msg){ cJSON* json,*item; json=createJson(msg); memset((unsigned char *)&usr, 0, sizeof(USER_INFO)); if(json==NULL){ MSG_WARN(1, "cJSONProcessUinfo json null"); return false; } //uid item=cJSON_GetObjectItem(json, OBJECT_UID); if(NULL!=item) usr.uid=atoi(item->valuestring); //gid item=cJSON_GetObjectItem(json, OBJECT_GID); if(NULL!=item) usr.gid=atoi(item->valuestring); //type item=cJSON_GetObjectItem(json, OBJECT_TYPE); if(NULL!=item) usr.type=atoi(item->valuestring); //groupName item=cJSON_GetObjectItem(json, OBJECT_GNAME); if(NULL!=item) snprintf(usr.gname, sizeof(usr.gname), "%s",item->valuestring); //nickname item=cJSON_GetObjectItem(json, OBJECT_NNAME); if(NULL!=item) snprintf(usr.nname, sizeof(usr.nname), "%s",item->valuestring); //token item=cJSON_GetObjectItem(json, OBJECT_TOKEN); if(NULL!=item) snprintf(usr.token, sizeof(usr.token), "%s",item->valuestring); releaseJson(&json); MSG_INFO(1, "usr:%d,%s,%d,%s,%s", usr.uid, usr.gname, usr.gid, usr.nname, usr.token); usr.ready=true; return true; } /*************************从文件中获取用户信息******************************/ bool learnTaskUpdate(LEARN_STATUS type, void *para1, void *para2, bool needShow){ char url[200],tmp[10]; unsigned char *msg=NULL; unsigned int len=0,i; UHTTP_ENUM httpType; //触发获取任务列表操作 if(sutApp.pocPpp==0 || sutPocStatus.logined==0){ if(true==needShow) showInfoBox("无网络/未登录",2000); learnUpdateStatus(LEARN_END); return false; } if(type==LEARN_DB_GET_INFO){//获取用户信息 httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/UserInfo?account=%d&password=%s", LEARN_HTTP_URL, sutApp.account.psn, sutApp.account.password); MSG_INFO(1, "Learn get user info"); }else if(type==LEARN_GET_LIST){//获取任务列表 httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/BriefTask?gid=%d&uid=%d&token=%s", LEARN_HTTP_URL, getLearnGid(),getLearnUid(),getLearnToken()); MSG_INFO(1, "Learn get total list"); }else if(type==LEARN_DB_SYNC_ADD_PAGE_WAIT){//根据页获取详细表 int *page=(int *)para1; int *size=(int *)para2; httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/DetailedTask?gid=%d&uid=%d&page=%d&size=%d&token=%s", LEARN_HTTP_URL, getLearnGid(),getLearnUid(),*page,*size,getLearnToken()); MSG_INFO(1, "Learn get detail,page:%d,size:%d", *page,*size); }else if(type==LEARN_DB_SYNC_ADD_SOME_WAIT){//根据tid获取详细表 unsigned int *tids=(unsigned int *)para1; unsigned char *num=(unsigned char *)para2; httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/DetailedTask?gid=%d&uid=%d&token=%s&tids=[%d", LEARN_HTTP_URL,getLearnGid(),getLearnUid(),getLearnToken(),tids[0]); for(i=1;i<*num;i++){ snprintf(tmp, sizeof(tmp),",%d", tids[i]); strcat(url, tmp); } strcat(url, "]"); MSG_INFO(1, "Learn get detail,tid num:%d", *num); }else if(type==LEARN_RECORD_UPLOAD){//上传语音数据到服务器 msg=(unsigned char *)para1; len=*((unsigned int *)para2); httpType=UHTTP_POST; snprintf(url, sizeof(url), "%s/api/cai/HandIn",LEARN_HTTP_URL); MSG_INFO(1, "Learn upload audio:%d bytes", len); }else if(type==LEARN_RANK_GET_DETAIL){ httpType=UHTTP_FILE_GET; unsigned char *rankType=(unsigned char *)para1; snprintf(url, sizeof(url), "%s/api/cai/%slyRanking?uid=%d&gid=%d&token=%s", LEARN_HTTP_URL,(*rankType==0)?"Month":"Week" ,getLearnUid(),getLearnGid(),getLearnToken()); MSG_INFO(1, "Learn get %s rank", (*rankType==0)?"month":"week"); }else if(type==LEARN_CLASS_GET_DETAIL){ httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/Timetable?uid=%d&gid=%d&token=%s", LEARN_HTTP_URL, getLearnUid(), getLearnGid(), getLearnToken()); MSG_INFO(1, "Learn get class detail"); }else if(type==LEARN_NOTICE_GET_DETAIL){ httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/NotificationBrief?uid=%d&gid=%d&token=%s", LEARN_HTTP_URL, getLearnUid(), getLearnGid(), getLearnToken()); MSG_INFO(1, "Learn get notice detail"); }else if(type==LEARN_NOTICE_GET_DETAIL_SHOW){ int *id=(int *)para1; httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/NotificationContent?uid=%d&id=%d&token=%s", LEARN_HTTP_URL, getLearnUid(), *id, getLearnToken()); MSG_INFO(1, "Learn get notice detail show"); }else if(type==LEARN_GET_PARAM){ httpType=UHTTP_FILE_GET; snprintf(url, sizeof(url), "%s/api/cai/Config?uid=%d&token=%s", LEARN_HTTP_URL, getLearnUid(), getLearnToken()); MSG_INFO(1, "Learn get param"); } if(true==needShow) showInfoBox("请稍候",5000); learnHttpStart(httpType,url, LEARN_PORT, httpCallBack,msg, len); return true; } static void LearnTaskProcess(void); static void sutJsonInit(void); //学习任务菜单 static unsigned char needUpdate=1;//是否需要更新,我们只从主菜单进此菜单时才同步,从里面的子菜单返回不同步 void uiShowLearnTask(char update){ if(update){ sutJsonInit(); guiClearAll(guiGetBackColor()); guiShowCaption(30,"学习任务",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); guiShowMessageBox("请稍候"); uiMenuShowBottomIndacitor("查看", "返回"); sdMount(); #if 1 if(isUserInfoReady()==false){ if(true==learnTaskUpdate(LEARN_DB_GET_INFO,NULL, NULL,true)) learnUpdateStatus(LEARN_DB_WAIT_INFO); }else{ if(needUpdate!=0){ MSG_INFO(1, "learn task need sync"); if(true==learnTaskUpdate(LEARN_GET_LIST,NULL, NULL,true)) learnUpdateStatus(LEARN_WAIT_LIST); }else learnUpdateStatus(LEARN_DB_SYNC_DONE);//子菜单返回时,直接读取显示,不去同步 } needUpdate=0; #else if(needUpdate!=0){ MSG_INFO(1, "learn task need sync"); if(true==learnTaskUpdate(LEARN_GET_LIST,NULL, NULL,true)) learnUpdateStatus(LEARN_WAIT_LIST); }else learnUpdateStatus(LEARN_DB_SYNC_DONE);//子菜单返回时,直接读取显示,不去同步 #endif } LearnTaskProcess(); } static void learnTaskDel(const char *delFileName); typedef struct{//用于显示的时候使用的 bool initStatus; unsigned char direction;//获取任务方向 0第一次获取,1向下,2向上 unsigned char lastDirection;//上一次获取方向 unsigned short index;//当前正查看询的索引 unsigned short selIndex;//最后读出来的项目,未经处理后的项目索引值,用于显示第几条使用 unsigned char validNum;//当前页有效项目数 unsigned short totalNum;//总任务数 cJSON* jsonList;//用于读取简表 char *bufList;//用于读取简表文件时使用的内存 cJSON* jsonTask[PAGE_SIZE];//用于读取每个任务详情 char *bufTask[PAGE_SIZE];//用于读取每个任务文件使用的内存 char showTable[PAGE_SIZE][SHOW_TABLE_MAX_BYTES];//用于菜单显示时使用 char finishedFlag[PAGE_SIZE];//完成状态 }LEARN_SHOW_DEF; LEARN_SHOW_DEF sutJson={false}; static void sutJsonInit(void){ if(sutJson.initStatus==true) return; MSG_INFO(1, "sutJson init"); memset((unsigned char *)&sutJson, 0, sizeof(LEARN_SHOW_DEF)); sutJson.initStatus=true; } static unsigned char learnGetNextPageInfo(LEARN_SHOW_DEF *learn){ cJSON* item, * element, * t; cJSON* tmpJson,*sele; char *tmpBuf; char file[50]; int i; MSG_INFO(1, "GET PAGE INFO START"); item=cJSON_GetObjectItem(learn->jsonList, OBJECT_LIST); if(NULL==item) return 1;//没有找到有元素数组 int num=cJSON_GetArraySize(item); if(num<=0) return 0;//没有任务,返回时会显示"无任务" learn->totalNum=num; int index=learn->index;//这里不处理learn->index if(learn->direction==1 && learn->lastDirection==2 && num<=PAGE_SIZE){//上次是向上,现在向下 index += learn->validNum; if(index>=num) index=0; }else if(learn->direction==2 && learn->lastDirection==1 && num<=PAGE_SIZE){//上次是向下,现在是向上 index -= learn->validNum; if(index>0 && index<5) index=0; else if(index<=0){ if(num==PAGE_SIZE) index=0;//如果与本页显示数目匹配,直接设置成0 else index=num-num%PAGE_SIZE; }else index -= PAGE_SIZE; }else if(learn->direction==0){ learn->direction=1; } //需要先释放上次进来时使用过的资源 for(i=0;ibufTask[learn->validNum]); releaseJson(&learn->jsonTask[learn->validNum]); } learn->validNum=0; for(;;){ element=cJSON_GetArrayItem(item, index); if(NULL==element){ if(index==num){//读到结尾了 learn->selIndex=index-learn->validNum; learn->index=0;//重置 goto P_END; }else return 2;//出错了 }else{ //获取tid t=cJSON_GetObjectItem(element, OBJECT_TID); if(NULL==t) goto P_CONTINUE; if(t->valuestring==NULL) goto P_CONTINUE;//没有找到值 //找到TID,根据TID获取文件内容出来/*{"s":4,"c":"What is your name?","t":"学习任务1","f":1,"tid":5126*/ snprintf(file, sizeof(file), "%s.task", t->valuestring); tmpBuf=getLearnFileJson(file); if(NULL==tmpBuf) goto P_CONTINUE; tmpJson=createJson(tmpBuf); if(NULL==tmpJson){ releaseBuf(&tmpBuf); goto P_CONTINUE; } //获取OBJECT_FINISH sele=cJSON_GetObjectItem(tmpJson, OBJECT_FINISH); if(NULL==sele){//获取finish失败 releaseBuf(&tmpBuf); releaseJson(&tmpJson); goto P_CONTINUE; } if(sele->valuestring==NULL) goto P_CONTINUE; i=atoi(sele->valuestring); if(i==0) learn->finishedFlag[learn->validNum]=0; else learn->finishedFlag[learn->validNum]=1; //获取OBJECT_TITLE sele=cJSON_GetObjectItem(tmpJson, OBJECT_TITLE); if(NULL==sele){//获取TITLE失败 releaseBuf(&tmpBuf); releaseJson(&tmpJson); goto P_CONTINUE; } if(sele->valuestring==NULL) goto P_CONTINUE; //格式化TITLE到显示Buff用于显示(看一下是否要转换编码格式) snprintf(learn->showTable[learn->validNum], SHOW_TABLE_MAX_BYTES, "%s", sele->valuestring); learn->jsonTask[learn->validNum]=tmpJson; learn->bufTask[learn->validNum]=tmpBuf; if(++learn->validNum>=PAGE_SIZE){ //获取够了,暂时不需要去释放资源,因为如果按确定查看内容时,还需要读取任务详细内容 index++; learn->selIndex=index-learn->validNum; if(index>=num) index=0; learn->index=index; goto P_END; } } P_CONTINUE: index++; } P_END: learn->lastDirection=learn->direction; return 0; } static void learnUIShowIndexAndTotal(unsigned int index, unsigned int total){ char info[20]; int i; snprintf(info, sizeof(info), "%d/%d", index, total); i=guiGetStrXLen(info,FONT_MODE_12X12); guiClearRect(GLCD_WIDTH-8*8, UI_STATUS_ITEM_Y, GLCD_WIDTH-1, UI_STATUS_ITEM_Y+UI_STATUS_ITEM_HEIGH-1, guiGetForeColor()); guiShowStr(GLCD_WIDTH-i, UI_STATUS_ITEM_Y+1, info, FONT_MODE_12X12, REVERSED_NO, guiGetBackColor(), guiGetForeColor()); } void LearnTaskSelResponse(void){ unsigned short key; if(LEARN_WAIT_RESPONSE==getLearnStatus()){ key=getKeyValue(); if(sutJson.validNum!=0){ if(sutListBox.handle==0 && MKEY_VALUE_UP==key){ sutJson.direction=2; learnUpdateStatus(LEARN_READ_TASK_INFO); }else if(((sutListBox.handle+1) == sutListBox.itemnum) && MKEY_VALUE_DOWN==key){ sutJson.direction=1; learnUpdateStatus(LEARN_READ_TASK_INFO); } key=ListBoxResponse(&sutListBox); if(MKEY_VALUE_ESC==key) learnUpdateStatus(LEARN_RELEASE_DB); else if(MKEY_VALUE_MENU==key){ uiPushStack(sutListBox.handle); uISetNextStatus(UIS_MENU_TASK_QUERY); //里面的菜单如果不返回本菜单,直接退出此任务操作,需要释放资源LEARN_RELEASE_DB }else if(MKEY_VALUE_UP || MKEY_VALUE_DOWN){ learnUIShowIndexAndTotal(sutJson.selIndex+sutListBox.handle+1,sutJson.totalNum); } }else if(MKEY_VALUE_ESC==key) learnUpdateStatus(LEARN_RELEASE_DB); } } //为了给电源键直接返回主界面,此两变量设置全局 static char *simpleList=NULL; static char *simpleListTmp=NULL; static void LearnTaskProcess(void){ unsigned char ret; // static char *simpleList=NULL; // static char *simpleListTmp=NULL; static cJSON* json=NULL,*item; cJSON* element,*subEle; static cJSON* jsonTmp=NULL,*itemTmp; cJSON* elementTmp,*subEleTmp; static int index; char tid[10],ver[10]; static bool updateAll; int i,j,page,size; cJSON* readJson=NULL; static char *readBuf=NULL; static unsigned int tidTable[LEARN_UPDATE_MAX]; static const char *learnIcon[]={ "TASK1.bmp", "TASK2.bmp", "" }; static char *menuTable[PAGE_SIZE+1]; switch(getLearnStatus()){ case LEARN_DB_WAIT_INFO: ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "LEARN_DB_WAIT_INFO:%d",ret); switch(ret){ case 0://获取用户信息成功,获取简表信息 if(true==learnTaskUpdate(LEARN_GET_LIST,NULL, NULL,true)) learnUpdateStatus(LEARN_WAIT_LIST); else{ showInfoBox("更新失败",2000); learnUpdateStatus(LEARN_END); } break; case 2://列表获取失败 showInfoBox("更新失败",2000); learnUpdateStatus(LEARN_END); break; default://获取超时 hearnHttpOverTime(); showInfoBox("更新超时",2000); learnUpdateStatus(LEARN_END); break; } } break; case LEARN_WAIT_LIST: ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "LEARN_WAIT_LIST:%d",ret); switch(ret){ case 0://获取列表成功,同步数据 learnUpdateStatus(LEARN_DB_SYNC); break; case 2://列表获取失败 showInfoBox("更新失败",2000); learnUpdateStatus(LEARN_END); break; default://获取超时 hearnHttpOverTime(); showInfoBox("更新超时",2000); learnUpdateStatus(LEARN_END); break; } } break; case LEARN_DB_SYNC://根据LEARN_LIST表同步数据 //读取LEARN_LIST_TMP数据用于同步 simpleListTmp=getLearnFileJson(LEARN_LIST_TMP); if(NULL==simpleListTmp){ learnUpdateStatus(LEARN_DB_SYNC_FAILED); break; } //加载到CJSON jsonTmp=createJson(simpleListTmp); if(NULL==jsonTmp){ learnUpdateStatus(LEARN_DB_SYNC_FAILED); break; } itemTmp=cJSON_GetObjectItem(jsonTmp, OBJECT_LIST); if(NULL==itemTmp){ learnUpdateStatus(LEARN_DB_SYNC_FAILED); break; } index=0; learnUpdateStatus(LEARN_DB_SYNC_ADD);//获取新任务 //再检测LEARN_LIST simpleList=getLearnFileJson(LEARN_LIST); if(NULL==simpleList){//读取失败,则直接认为没有主简表,则直接全部更新 updateAll=true;//全部拉取更新 break; } //加载到CJSON json=createJson(simpleList); if(NULL==json){//加载失败,全部更新 updateAll=true;//全部拉取更新 break; } item=cJSON_GetObjectItem(json, OBJECT_LIST); if(NULL==item){//无OBJECT_LIST项目,全部更新 updateAll=true;//全部拉取更新 break; } MSG_INFO(1, "LEARN_DB_SYNC_DEL"); learnUpdateStatus(LEARN_DB_SYNC_DEL); updateAll=false; //开始同步(先同步任务文件,最后更新任务简表总表) break; case LEARN_DB_SYNC_DEL://先删除多余的任务 //读取主简表中有,但临时简表中没有的任务,然后删除之 i=0; MSG_INFO(1, "LEARN_DB_SYNC_DEL Start"); for(;;){ element=cJSON_GetArrayItem(item, i); if(element!=NULL){ subEle=cJSON_GetObjectItem(element, OBJECT_TID); if(subEle!=NULL){//找到了一个任务,检测在TMP任务中是否存在 if(subEle->valuestring==NULL) goto C_NEXT;//tid值为空,忽视此项 j=0; for(;;){ elementTmp=cJSON_GetArrayItem(itemTmp, j); if(elementTmp!=NULL){ subEleTmp=cJSON_GetObjectItem(elementTmp, OBJECT_TID); if(subEleTmp!=NULL){//比对 if(subEleTmp->valuestring==NULL) break;//tid值为空,忽视此项,认为不存在 if(0==strcmp(subEleTmp->valuestring, subEle->valuestring)) goto C_NEXT;//存在,不处理 } }else break;//检查完了 j++; } //在新(临时)任务简表总表中未找到此任务,即为多余任务,需要删除掉 learnTaskDel(subEle->valuestring); } }else break;//检测完了 C_NEXT: i++; } if(updateAll==true){//全部更新,就不需要再使用simpleList,simpleListTmp,json,jsonTmp releaseBuf(&simpleList); releaseBuf(&simpleListTmp); releaseJson(&json); releaseJson(&jsonTmp); MSG_INFO(1, "Free resorce"); }else{/*不是全部更新时还是需要*/} MSG_INFO(1, "LEARN_DB_SYNC_DEL end"); learnUpdateStatus(LEARN_DB_SYNC_ADD);//添加新任务了 break; case LEARN_DB_SYNC_ADD: if(true==updateAll){//全部更新,同一次获取多个 page=index/LEARN_UPDATE_MAX; size=LEARN_UPDATE_MAX; learnAddNum=0; learnUpdateStatus(LEARN_DB_SYNC_ADD_PAGE_WAIT); learnDetailEnd=false;//检测是否下载完毕使用 learnTaskUpdate(LEARN_DB_SYNC_ADD_PAGE_WAIT,(void *)&page, (void *)&size,true); uTimerStart(&learnTick, 2000); }else{//根据两个简表,添加回LEARN_LIST中没有,但LEARN_LIST_TMP中有的任务 for(i=0;ivaluestring==NULL) continue;//tid值为空,忽视此项 //找到任务ID subEleTmp->valuestring,遍历LEARN_LIST中是否不存在,是则需要获取 int w=0; bool taskExist=false; for(;;){ element=cJSON_GetArrayItem(item,w++); if(NULL==element) break;//遍历完了 subEle=cJSON_GetObjectItem(element, OBJECT_TID); if(NULL==subEle) continue; if(subEle->valuestring==NULL) continue;//tid值为空,忽视此项 if(strcmp(subEle->valuestring, subEleTmp->valuestring)==0){//任务存在 //对比OBJECT_VER是否一样 cJSON* tver, *tverTmp; tver=cJSON_GetObjectItem(element, OBJECT_VER); tverTmp=cJSON_GetObjectItem(elementTmp, OBJECT_VER); if(tver==NULL || tverTmp==NULL) break;//有找不到OBJECT_VER字段的,认为需要得新获取处理 if(strcmp(tver->valuestring, tverTmp->valuestring)!=0) break;//OBJECT_VER变化了,需要获取处理 taskExist=true; break; } } if(taskExist==false){//任务不存在添加到列表 tidTable[learnAddNum++]=atoi(subEleTmp->valuestring); if(learnAddNum>=LEARN_UPDATE_MAX) break;//列表满了,需要先获取 } } if(learnAddNum==0){//同步完成 MSG_INFO(1, "LEARN_DB_SYNC_ADD_SOME_WAIT done"); releaseBuf(&simpleList); releaseBuf(&simpleListTmp); releaseJson(&json); releaseJson(&jsonTmp); learnUpdateListFile(); learnUpdateStatus(LEARN_DB_SYNC_DONE); break; } //发起新的文件获取(根据任务ID获取) //文件ID表在tidTable中,个数为learnAddNum个 learnUpdateStatus(LEARN_DB_SYNC_ADD_SOME_WAIT); learnTaskUpdate(LEARN_DB_SYNC_ADD_SOME_WAIT,(void *)tidTable, (void *)&learnAddNum,true); MSG_ERR(1, "update tids:%d", learnAddNum); } break; case LEARN_DB_SYNC_ADD_PAGE_WAIT: case LEARN_DB_SYNC_ADD_SOME_WAIT: ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "LEARN_DB_SYNC_ADD_PAGE/SOME_WAIT:%d,%d",getLearnStatus(),ret); switch(ret){ case 0://获取任务详表成功 if(getLearnStatus()==LEARN_DB_SYNC_ADD_PAGE_WAIT){ if(learnDetailEnd==false){ index += learnAddNum; learnUpdateStatus(LEARN_DB_SYNC_ADD); }else{//同步完成了 releaseBuf(&simpleList); releaseBuf(&simpleListTmp); releaseJson(&json); releaseJson(&jsonTmp); //删除simpleList,simpleListTmp重命名为simpleList learnUpdateListFile(); learnUpdateStatus(LEARN_DB_SYNC_DONE); } }else learnUpdateStatus(LEARN_DB_SYNC_ADD);//继续 break; case 2://失败 learnUpdateStatus(LEARN_DB_SYNC_FAILED); break; default://获取超时 hearnHttpOverTime(); learnUpdateStatus(LEARN_DB_SYNC_FAILED); break; } } break; case LEARN_DB_SYNC_DONE://同步完成,可以读取用于显示 MSG_INFO(1, "LEARN_DB_SYNC_DONE"); //释放 releaseJson(&json); releaseJson(&jsonTmp); releaseBuf(&sutJson.bufList); releaseJson(&sutJson.jsonList); for(i=0;iFastUiChange)uISetNextStatus(UIS_STANDBY); else uISetNextStatus(UIS_MENU_MAIN); needUpdate=1; break; case LEARN_END: if(uTimerExpired(&learnTick)){ sdUnmount(); uISetNextStatus(UIS_MENU_MAIN); needUpdate=1; } break; } } /*学习任务选择菜单时按了电源键返回主菜单*/ void taskSelBackToStandby(bool status){ int i; if(LEARN_WAIT_RESPONSE==getLearnStatus() || status==true){ MSG_INFO(1, "Release DB For pwr to standby"); releaseBuf(&simpleList); releaseBuf(&simpleListTmp); releaseBuf(&sutJson.bufList); releaseJson(&sutJson.jsonList); for(i=0;i0) nwy_sdk_fclose(fd); return buf; } //delFileName:任务ID //删除以delFileName为名字的.task .rec文件 static void learnTaskDel(const char *delFileName){ char file[50]; //删除.task文件 snprintf(file, sizeof(file), "%s/%s.task", SD_TOKEN, delFileName); if(true==nwy_sdk_fexist(file)){ nwy_sdk_file_unlink(file); MSG_INFO(1, "Del %s.task", delFileName); } //删除.rec文件 snprintf(file, sizeof(file), "%s/%s.rec", SD_TOKEN, delFileName); if(true==nwy_sdk_fexist(file)){ nwy_sdk_file_unlink(file); MSG_INFO(1, "Del %s.rec", delFileName); } MSG_INFO(1, "Del tid %s end", delFileName); } void printfJsonValue(cJSON* json){ if(NULL==json) return; char *buf=cJSON_Print(json); if(NULL==buf) return; MSG_INFO(1, "json:%s",buf); free(buf); } //解析JSON得到tid作为文件名,同时将任务JCSON保存起来 static void cJSONSaveTaskFile(const char *jsonMsg){ int i,fd; cJSON* json,*item,*element,*t; char *buf; #ifdef USE_TEST_TASK static char nextFlag=0; const *testBuf1="{\"uid\":\"12348\",\"list\":[{\"s\":\"4\",\"c\":\"What is your name?0123一二三四567890123一二三四567890123一二三四567890123一二三四567890123一二三四567890123一二三四567890123一二三四567890123一二三四567890123一二三四56789\",\"t\":\"学习任务1\",\"f\":\"1\",\"tid\":\"5126\"}, \ {\"s\":\"3\",\"c\":\"Where are you?\",\"t\":\"学习任务2\",\"f\":\"1\",\"tid\":\"5127\"}, \ {\"s\":\"5\",\"c\":\"How do you do!\",\"t\":\"学习任务3\",\"f\":\"1\",\"tid\":\"8867\"}, \ {\"s\":\"3\",\"c\":\"Good morning!\",\"t\":\"学习任务4\",\"f\":\"1\",\"tid\":\"8868\"}, \ {\"s\":\"0\",\"c\":\"How old are you?\",\"t\":\"学习任务5\",\"f\":\"0\",\"tid\":\"1221\"}, \ {\"s\":\"0\",\"c\":\"I am come from Shenzhen, China\",\"t\":\"学习任务6\",\"f\":\"0\",\"tid\":\"2546\"} \ ]}"; const *testBuf2="{\"uid\":\"12348\",\"list\":[]}"; char *ptr; if(nextFlag==0){ ptr=testBuf1; nextFlag=1; }else if(nextFlag==1){ ptr=testBuf2; nextFlag=0; } json=createJson(ptr); #else json=createJson(jsonMsg); #endif if(json==NULL){ MSG_WARN(1, "cJSONSaveTaskFile json null"); return; } item=cJSON_GetObjectItem(json, OBJECT_LIST); if(NULL==item){ MSG_WARN(1, "cJSONSaveTaskFile item null"); goto S_END; } //获取OBJECT_LIST元素个数 int num=cJSON_GetArraySize(item); MSG_INFO(1, "Num:%d", num); if(0==num){//获取完成了 learnDetailEnd=true; MSG_INFO(1, "cJSONSaveTaskFile done"); }else{ //解析每个任务的任务ID i=0; for(;;){ element=cJSON_GetArrayItem(item, i); if(NULL==element){ MSG_INFO(1, "json array end"); break; } t=cJSON_GetObjectItem(element, OBJECT_TID); if(NULL != t){ //得到一个任务ID,内容为cJSON_Print(element),保存起来 buf=cJSON_Print(element); if(NULL==buf){ MSG_ERR(1, "cJSONSaveTaskFile cJSON_Print null"); break; } learnSaveTaskFile(t->valuestring, buf); releaseBuf(&buf); //MSG_INFO(1, "[mem free]%x",buf); //free(buf); learnAddNum++;//已添加一个文件(任务) MSG_INFO(1, "Save one task:%s.task", t->valuestring); }else MSG_WARN(1, "No find tid"); i++; } } S_END: releaseJson(&json); //cJSON_Delete(json); } static void learnSaveTaskFile(const char *fname, const char *msg){ int fd; char file[50]; if(fname==NULL) return; snprintf(file, sizeof(file), "%s/%s.task", SD_TOKEN, fname); fd = nwy_sdk_fopen(file, NWY_CREAT | NWY_RDWR|NWY_TRUNC);//清0式 if(fd<0){ MSG_WARN(1, "learnSaveTaskFile fopen failed,%s", fname); return; } nwy_sdk_fwrite(fd, msg, strlen(msg)); nwy_sdk_fclose(fd); MSG_INFO(1, "Save task %s", fname); } unsigned char haveNextPage; unsigned char taskIndex; char tidString[20];//保存正在查看的任务的tid串 char *learnGetTid(void){return tidString;} /* 统计有多少个单词 原理:单词间用标点(, .)或空格分开 */ static void calWordNum(char *msg){ int i,len=strlen(msg); unsigned char num=0; unsigned char lashChara=0; MSG_INFO(1, "content:%s",msg); for(i=0;ivaluestring); eleScore=cJSON_GetObjectItem(sutJson.jsonTask[taskIndex], OBJECT_SCORE); eleContent=cJSON_GetObjectItem(sutJson.jsonTask[taskIndex], OBJECT_CONTENT); //制造分数串 if(NULL==eleScore){//没有找到分数字段,显示'--' snprintf(info, sizeof(info), "分数:--"); }else if(eleScore->valuestring==NULL){ snprintf(info, sizeof(info), "分数:--"); }else snprintf(info, sizeof(info), "分数:%s", eleScore->valuestring); //内容 if(NULL!=eleContent && eleContent->valuestring!=NULL){ isDetailValid=1; calWordNum(eleContent->valuestring);//计算单词个数 } if(0!=newMessageInit(FONT_MODE_12X12, info, eleContent->valuestring, NULL)){ MSG_WARN(1, "learn task show get error"); } } unsigned char recoderVolume=0; LEARN_REC_STATUS learnRecordStatus; void learnRecSetStatus(LEARN_REC_STATUS newStatus){ learnRecordStatus=newStatus; } void learnRecSetVol(unsigned char newVol){ recoderVolume=newVol; } static void learnShowResult(void); static void learnShowStartScreen(void){ //const char *repeatListen="[PTT]录音"; if(isUserStudent()==true) uiMenuShowBottomIndacitor("[OK]重听", "[PTT]录音"); else uiMenuShowBottomIndacitor(NULL, "返回"); } /*播放录音中止/完成后,返回原定界面及操作*/ void learnRetrunStatus(void){ if(0==learnGetAudioType()){//返回原定界面及操作 learnRecSetStatus(LEARN_REC_DONE); uiMenuShowBottomIndacitor("[OK]播放","[F1]提交");//选择提交还是播放 learnShowResult(); }else{//返回原定界面及操作 learnRecSetStatus(LEARN_REC_IDLE); learnShowStartScreen(); } } static void learnRecordDoneProcess(void); static void learnDetailBackToTaskListMenu(void){ uISetNextStatus(UIS_MENU_TASK_SEL);//返回上层菜单 } /*学习任务直接返回待机界面操作*/ void taskBackToStandby(void){ bool needtoreleased=false; bool needtofreeed=false; switch(learnRecordStatus){ case LEARN_REC_IDLE: case LEARN_REC_DONE: case LEARN_UPLOAD_CONFIRM: needtofreeed=true; needtoreleased=true; break; case LEARN_REC_PLY: learnStopPlaying(); needtofreeed=true; needtoreleased=true; break; case LEARN_REC_BUSY: learnRecordFree(); learnStopRecord(); needtofreeed=true; needtoreleased=true; break; default:break;//其它状态不能动 } if(true==needtofreeed) learnRecordBufRelease(); if(true==needtoreleased) taskSelBackToStandby(true); } /*任务查看*/ void uiShowLearnTaskDetail(char update){ unsigned char ret; if(update){ guiClearAll(guiGetBackColor()); guiShowCaption(0,"任务详情",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); taskIndex=sutListBox.handle; learnRecSetStatus(LEARN_REC_IDLE); readTaskToShow(); learnShowStartScreen(); learnTick=0; } switch(learnRecordStatus){ case LEARN_REC_BUSY://动态显示正在录音效果 learnRecordVolShow(recoderVolume); break; if(uTimerExpired(&learnTick)){ uTimerStart(&learnTick, 500); learnRecordVolShow(recoderVolume); } break; case LEARN_REC_OT://录音已超过最大时间,停止录音 learnRecordDoneProcess(); #ifdef SAVE_PCM_SD pcmFileClose(); #endif break; case LEARN_REC_PLY://正在播放 switch(learnPlyGetResult()){ case LEARN_PLY_PRE_ERR://播放失败 guiShowMessageBox("播放失败"); nwy_sleep(1500); learnDetailBackToTaskListMenu(); break; case LEARN_PLY_FAILED://播放异常 guiShowMessageBox("播放异常");//返回上层菜单 nwy_sleep(1500); learnDetailBackToTaskListMenu(); break; case LEARN_PLY_DONE://播放成功,结束 learnRetrunStatus(); break; } break; case LEARN_RECORD_UPLOAD://等待上传结果 ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "LEARN_RECORD_UPLOAD:%d",ret); switch(ret){ case 0://上传完成 guiShowMessageBox("上传完成"); recordSaveTmpToLocal(tidString); break; case 2://上传失败 guiShowMessageBox("上传失败"); break; default://上传超时 hearnHttpOverTime(); guiShowMessageBox("上传超时"); break; } nwy_sleep(1500); //返回任务详情内容页面,录音临时信息及资源回收 learnRecordBufRelease(); learnShowStartScreen(); newMessageShow(SHOW_HEAD); learnRecSetStatus(LEARN_REC_IDLE); } break; } } //根据录制的语音内容算出平均值用于显示 //volLev:经过计算后得出的0~10等级数值 void learnRecordVolShow(unsigned char volLev){ unsigned char vol=volLev; unsigned short y1,y2,x,i; unsigned int colorID; static unsigned char lashVel=99; unsigned char width=8;//一格音量宽度 unsigned char tx=1;//音量柱间隔 unsigned char sx=0;//音量柱开始坐标 if(lashVel == volLev) return; lashVel=volLev; //然后使用绿色显示实际音量 for(i=0;i=ranks.item) tIndex=0; }else if(direction==2){ if(tIndex==0) tIndex=ranks.item-1; else tIndex--; } } guiClearRect(0,UI_CONTENT_SHOW_Y,GLCD_WIDTH-1,UI_BOTTOM_SHOW_Y-2,guiGetBackColor()); //显示 if(ranks.rankResult==NULL){ MSG_WARN(1, "rank no data"); return; } char info[50]; int x=1,y=UI_CONTENT_SHOW_Y; //显示排名类型 if(0==ranks.rankResult[tIndex]->type) snprintf(info, sizeof(info), "month:%d", ranks.rankResult[tIndex]->typeIndex); else snprintf(info, sizeof(info), "week:%d", ranks.rankResult[tIndex]->typeIndex); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示avg snprintf(info, sizeof(info), "avg:%d", ranks.rankResult[tIndex]->avg); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示score snprintf(info, sizeof(info), "score:%d", ranks.rankResult[tIndex]->score); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示ranking snprintf(info, sizeof(info), "ranking:%d", ranks.rankResult[tIndex]->ranking); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示num snprintf(info, sizeof(info), "num:%d", ranks.rankResult[tIndex]->num); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); } void uiShowLearnRankDetail(char update){ int ret; static bool needGetUinfo=false; if(update){ guiClearAll(guiGetBackColor()); if(rankType==0) guiShowCaption(0,"月排名",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); else guiShowCaption(0,"周排名",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); uiMenuShowBottomIndacitor(NULL, "返回"); if(sutApp.pocPpp==0){ guiShowMessageBox("无网络"); nwy_sleep(1500); uISetNextStatus(UIS_MENU_RANK_SEL); return; } rankShowReady=false; showInfoBox("请稍候",3000); if(isUserInfoReady()==false){//如果未获取用户信息,先获取用户信息 needGetUinfo=true; learnUpdateStatus(LEARN_DB_WAIT_INFO); learnTaskUpdate(LEARN_DB_GET_INFO,NULL, NULL,true); }else{//否则可以直接获取排名 needGetUinfo=false; learnUpdateStatus(LEARN_RANK_GET_DETAIL); learnTaskUpdate(LEARN_RANK_GET_DETAIL,(void*)&rankType, NULL,true); MSG_ERR(1, "update rank detail %s", (rankType==0)?"month":"week"); } } if(false==rankShowReady){ ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "WAIT %s RESULT:%d",(rankType==0)?"MONTH":"WEEK",ret); switch(ret){ case 0://功获取到了信息 if(needGetUinfo==true){ needGetUinfo=false; learnUpdateStatus(LEARN_RANK_GET_DETAIL); learnTaskUpdate(LEARN_RANK_GET_DETAIL,(void*)&rankType, NULL,true); MSG_ERR(1, "update rank detail %s", (rankType==0)?"month":"week"); }else{ rankShowReady=true; getRankShowMessage(rankType); rankInfoDetailShow(0); } return; case 2://获取失败 guiShowMessageBox("获取失败"); break; default://获取超时 hearnHttpOverTime(); guiShowMessageBox("获取超时"); break; } nwy_sleep(1500); getStackStruct()->ok_back=1; uISetNextStatus(UIS_MENU_RANK_SEL); } } } static void learnRankReleaseDB(void); void LearnRankDetailSelResponse(void){ if(rankShowReady==true){ switch(getKeyValue()){ case MKEY_VALUE_ESC: learnRankReleaseDB(); uISetNextStatus(UIS_MENU_RANK_SEL); break; case MKEY_VALUE_DOWN:rankInfoDetailShow(1);break; case MKEY_VALUE_UP:rankInfoDetailShow(2);break; } } } void rankSelBackToStandby(void){ sdUnmount(); uISetNextStatus(UIS_STANDBY); } void rankBackToStandby(void){ learnRankReleaseDB(); rankSelBackToStandby(); } typedef struct{ int week; char time[15]; char subject[30*2]; }CLASS_DEF; typedef struct{ unsigned int item;//rankResult实际使用的个数 unsigned int num;//rankResult分配的个数(释放时使用) CLASS_DEF **classResult; }CLASS_RESULT_DEF; CLASS_RESULT_DEF classes={0,0,0,NULL}; bool classShowReady; static void classInfoDetailShow(unsigned char direction){ static int tIndex=0; if(classes.item==0){ guiShowMessageBox("无数据"); return; }else if(classes.item==1) tIndex=0; else{ if(direction==0) tIndex=0; else if(direction==1){ if(++tIndex>=classes.item) tIndex=0; }else if(direction==2){ if(tIndex==0) tIndex=classes.item-1; else tIndex--; } } guiClearRect(0,UI_CONTENT_SHOW_Y,GLCD_WIDTH-1,UI_BOTTOM_SHOW_Y-2,guiGetBackColor()); //显示 if(classes.classResult==NULL){ MSG_WARN(1, "class no data"); return; } #if 0 char info[50]; int x=1,y=UI_CONTENT_SHOW_Y; //显示week snprintf(info, sizeof(info), "week:%d", classes.classResult[tIndex]->week); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示time snprintf(info, sizeof(info), "time:%s", classes.classResult[tIndex]->time); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示subject snprintf(info, sizeof(info), "subject:%s", classes.classResult[tIndex]->subject); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); #else const char *weekTable[]={ "天","一","二","三","四","五","六","" }; char info1[50],info2[100]; unsigned char index; //显示索引和总数 learnUIShowIndexAndTotal(tIndex+1,classes.item); //显示内容 index=classes.classResult[tIndex]->week; if(index>6) index=7; snprintf(info1, sizeof(info1), "星期%s%c时间:%s", weekTable[index],0x0a,classes.classResult[tIndex]->time); snprintf(info2, sizeof(info2), "课程:%s", classes.classResult[tIndex]->subject); newMessageInit(FONT_MODE_16X16,info1, info2, NULL); #endif } static void getClassShowMessage(void); /*课程表*/ void uiShowLearnClassDetail(char update){ int ret; static bool needGetUinfo=false; if(update){ guiClearAll(guiGetBackColor()); guiShowCaption(30,"课程表",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); uiMenuShowBottomIndacitor(NULL, "返回"); if(sutApp.pocPpp==0){ guiShowMessageBox("无网络"); nwy_sleep(1500); uISetNextStatus(UIS_MENU_LOCATION_SEL); return; } classShowReady=false; showInfoBox("请稍候",3000); sdMount(); if(isUserInfoReady()==false){//如果未获取用户信息,先获取用户信息 needGetUinfo=true; learnUpdateStatus(LEARN_DB_WAIT_INFO); learnTaskUpdate(LEARN_DB_GET_INFO,NULL, NULL,true); }else{//否则可以直接获取课程表 needGetUinfo=false; learnUpdateStatus(LEARN_CLASS_GET_DETAIL); learnTaskUpdate(LEARN_CLASS_GET_DETAIL,NULL, NULL,true); MSG_ERR(1, "update class detail"); } } if(false==classShowReady){ ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "WAIT CLASS:%d",ret); switch(ret){ case 0://功获取到了信息 if(needGetUinfo==true){ needGetUinfo=false; learnUpdateStatus(LEARN_CLASS_GET_DETAIL); learnTaskUpdate(LEARN_CLASS_GET_DETAIL,NULL, NULL,true); MSG_ERR(1, "update class detail"); }else{//处理 MSG_INFO(1, "class info get ok"); classShowReady=true; getClassShowMessage(); classInfoDetailShow(0); } return; case 2://获取失败 guiShowMessageBox("获取失败"); break; default://获取超时 hearnHttpOverTime(); guiShowMessageBox("获取超时"); break; } nwy_sleep(1500); getStackStruct()->ok_back=1; uISetNextStatus(UIS_MENU_LOCATION_SEL); } } } static void learnClassReleaseDB(void); void LearnClassDetailResponse(void){ if(classShowReady==true){ switch(getKeyValue()){ case MKEY_VALUE_ESC: learnClassReleaseDB(); uISetNextStatus(UIS_MENU_LOCATION_SEL); break; case MKEY_VALUE_DOWN:classInfoDetailShow(1);break; case MKEY_VALUE_UP:classInfoDetailShow(2);break; } } } void classBackToStandby(void){ if(classShowReady==false) return; learnClassReleaseDB(); sdUnmount(); uISetNextStatus(UIS_STANDBY); } typedef struct{ int id; char time[15]; char title[60]; }NOTICE_DEF; typedef struct{ unsigned int item;//rankResult实际使用的个数 unsigned int num;//rankResult分配的个数(释放时使用) NOTICE_DEF **noticeResult; }NOTICE_RESULT_DEF; NOTICE_RESULT_DEF notices={0,0,0,NULL}; bool noticeShowReady; static int noticetIndex=0; static void noticeInfoDetailShow(unsigned char direction){ char time[35]; char title[100]; if(notices.item==0){ guiShowMessageBox("无数据"); return; }else if(notices.item==1) noticetIndex=0; else{ if(direction==0) noticetIndex=0; else if(direction==1){ if(++noticetIndex>=notices.item) noticetIndex=0; }else if(direction==2){ if(noticetIndex==0) noticetIndex=notices.item-1; else noticetIndex--; } } guiClearRect(0,UI_CONTENT_SHOW_Y,GLCD_WIDTH-1,UI_BOTTOM_SHOW_Y-2,guiGetBackColor()); //显示 if(notices.noticeResult==NULL){ MSG_WARN(1, "notice no data"); return; } #if 0 char info[50]; int x=1,y=UI_CONTENT_SHOW_Y; //显示title snprintf(info, sizeof(info), "title:%s", notices.noticeResult[noticetIndex]->title); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); y+=17; //显示time snprintf(info, sizeof(info), "time:%s", notices.noticeResult[noticetIndex]->time); guiShowStr(x, y, info, FONT_MODE_16X16, REVERSED_NO, COLOR_BLACK, guiGetBackColor()); #else snprintf(time, sizeof(time), "时间:%s", notices.noticeResult[noticetIndex]->time); snprintf(title, sizeof(title), "标题:%s", notices.noticeResult[noticetIndex]->title); learnUIShowIndexAndTotal(noticetIndex+1,notices.item); newMessageInit(FONT_MODE_16X16, time, title, NULL); #endif } static void getNoticeShowMessage(void); /*消息通知*/ void uiShowLearnNoticeDetail(char update){ int ret; static bool needGetUinfo=false; if(update){ guiClearAll(guiGetBackColor()); guiShowCaption(30,"消息通知",UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); uiMenuShowBottomIndacitor("阅读", "返回"); if(sutApp.pocPpp==0){ guiShowMessageBox("无网络"); nwy_sleep(1500); uISetNextStatus(UIS_MENU_LOCATION_SEL); return; } if(noticeShowReady==false){ showInfoBox("请稍候",3000); sdMount(); if(isUserInfoReady()==false){//如果未获取用户信息,先获取用户信息 needGetUinfo=true; learnUpdateStatus(LEARN_DB_WAIT_INFO); learnTaskUpdate(LEARN_DB_GET_INFO,NULL, NULL,true); }else{//否则可以直接获取课程表 needGetUinfo=false; learnUpdateStatus(LEARN_NOTICE_GET_DETAIL); learnTaskUpdate(LEARN_NOTICE_GET_DETAIL,NULL, NULL,true); MSG_ERR(1, "update notice detail"); } } } if(false==noticeShowReady){ ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "WAIT NOTICE:%d",ret); switch(ret){ case 0://功获取到了信息 if(needGetUinfo==true){ needGetUinfo=false; learnUpdateStatus(LEARN_NOTICE_GET_DETAIL); learnTaskUpdate(LEARN_NOTICE_GET_DETAIL,NULL, NULL,true); MSG_ERR(1, "update notice detail"); }else{//处理 MSG_INFO(1, "notice info get ok"); noticeShowReady=true; getNoticeShowMessage(); noticeInfoDetailShow(0); } return; case 2://获取失败 guiShowMessageBox("获取失败"); break; default://获取超时 hearnHttpOverTime(); guiShowMessageBox("获取超时"); break; } nwy_sleep(1500); getStackStruct()->ok_back=1; uISetNextStatus(UIS_MENU_LOCATION_SEL); } } } static void learnNoticeReleaseDB(void); unsigned char noticeHandle; void LearnNoticeResponse(void){ if(noticeShowReady==true){ switch(getKeyValue()){ case MKEY_VALUE_ESC: learnNoticeReleaseDB(); noticeShowReady=false; uISetNextStatus(UIS_MENU_LOCATION_SEL); break; case MKEY_VALUE_DOWN:noticeInfoDetailShow(1);break; case MKEY_VALUE_UP:noticeInfoDetailShow(2);break; case MKEY_VALUE_MENU: uISetNextStatus(UIS_MENU_LOCATION_NOTICE_DETAIL); break; } } } void noticeBackToStandby(void){ if(noticeShowReady==false) return; noticeShowReady=false; learnNoticeReleaseDB(); learnClassReleaseDB(); sdUnmount(); uISetNextStatus(UIS_STANDBY); } bool noticeDetailReady=false; /*消息通知详情*/ void uiShowLearnNoticeDetailShow(char update){ int ret; if(update){ guiClearAll(guiGetBackColor()); guiShowCaption(0,notices.noticeResult[noticetIndex]->time,UI_STATUS_ITEM_Y+1,guiGetBackColor(),guiGetForeColor(),FONT_MODE_12X12); uiMenuShowBottomLine(); uiMenuShowBottomIndacitor(NULL, "返回"); if(sutApp.pocPpp==0){ guiShowMessageBox("无网络"); nwy_sleep(1500); uISetNextStatus(UIS_MENU_LOCATION_SEL); return; } showInfoBox("请稍候",3000); sdMount(); noticeDetailReady=false; learnUpdateStatus(LEARN_NOTICE_GET_DETAIL_SHOW); learnTaskUpdate(LEARN_NOTICE_GET_DETAIL_SHOW,(void *)¬ices.noticeResult[noticetIndex]->id, NULL,true); MSG_ERR(1, "update notice detail show"); } if(false==noticeDetailReady){ ret=getHttpLearnStatus(); if(uTimerExpired(&learnTick) || ret!=1){ MSG_INFO(1, "WAIT NOTICE SHOW:%d",ret); switch(ret){ case 0://功获取到了信息 //处理 noticeDetailReady=true; MSG_INFO(1, "notice info get ok"); noticeInfoDetailShowContent(0); return; case 2://获取失败 guiShowMessageBox("获取失败"); break; default://获取超时 hearnHttpOverTime(); guiShowMessageBox("获取超时"); break; } nwy_sleep(1500); noticeShowReady=false; getStackStruct()->ok_back=1; uISetNextStatus(UIS_MENU_LOCATION_SEL); } } } void LearnNoticeDetailResponse(void){ if(noticeDetailReady==true){ switch(getKeyValue()){ case MKEY_VALUE_ESC: noticeShowReady=false; uISetNextStatus(UIS_MENU_LOCATION_NOTICE); break; case MKEY_VALUE_DOWN:noticeInfoDetailShowContent(1);break; case MKEY_VALUE_UP:noticeInfoDetailShowContent(2);break; } } } void noticeDetailBackToStandby(void){ if(noticeDetailReady==false) return; noticeShowReady=false; noticeDetailReady=false; learnNoticeReleaseDB(); learnClassReleaseDB(); sdUnmount(); uISetNextStatus(UIS_STANDBY); } #define OBJECT_AVG_NAME "avg" #define OBJECT_SCORE_NAME "score" #define OBJECT_RANKING_NAME "ranking" #define OBJECT_NUM_NAME "num" /* msg:json buffer 数据,长度为len { "gid":555, "uid":12345, "list":[ {"week":29,"avg":518,"score":562,"ranking":5,"num":35}, {"week":28,"avg":518,"score":581,"ranking":8,"num":28}, {"week":27,"avg":518,"score":558,"ranking":10,"num":40}, {"week":26,"avg":518,"score":592,"ranking":2,"num":37}, ] } 或 { "gid":555, "uid":12345, "list":[ {"month":8,"avg":518,"score":562,"ranking":5,"num":35}, {"month":7,"avg":518,"score":581,"ranking":8,"num":28}, {"month":6,"avg":518,"score":558,"ranking":10,"num":40}, {"month":5,"avg":518,"score":592,"ranking":2,"num":37}, ] } 这里将list提取出到buffer并输出 */ static char *rankBuffer=NULL; cJSON* rankJson=NULL; static void learnRankReleaseDB(void){ int i; releaseBuf(&rankBuffer); if(NULL!=ranks.rankResult){ for(i=0;itype=ranktype; t=cJSON_GetObjectItem(element, info); if(NULL==t) rankPtr[i]->typeIndex=-1; else rankPtr[i]->typeIndex=atoi(t->valuestring); //avg t=cJSON_GetObjectItem(element, OBJECT_AVG_NAME); if(NULL==t) rankPtr[i]->avg=-1; else rankPtr[i]->avg=atoi(t->valuestring); //score t=cJSON_GetObjectItem(element, OBJECT_SCORE_NAME); if(NULL==t) rankPtr[i]->score=-1; else rankPtr[i]->score=atoi(t->valuestring); //ranking t=cJSON_GetObjectItem(element, OBJECT_RANKING_NAME); if(NULL==t) rankPtr[i]->ranking=-1; else rankPtr[i]->ranking=atoi(t->valuestring); //num t=cJSON_GetObjectItem(element, OBJECT_NUM_NAME); if(NULL==t) rankPtr[i]->num=-1; else rankPtr[i]->num=atoi(t->valuestring); i++; } ranks.item=i; ranks.rankResult=rankPtr; MSG_INFO(1, "rank valid num:%d",i); return; R_EXIT: releaseJson(&rankJson); releaseBuf(&rankBuffer); if(fd>0) nwy_sdk_fclose(fd); if(rankPtr != NULL){ for(i=0;iweek=-1; else classPtr[i]->week=atoi(t->valuestring); //time t=cJSON_GetObjectItem(element, OBJECT_TIME_NAME); if(NULL==t) classPtr[i]->time[0]='\0'; else snprintf(classPtr[i]->time, sizeof(classPtr[i]->time), "%s", t->valuestring); //subject t=cJSON_GetObjectItem(element, OBJECT_SUBJECT_NAME); if(NULL==t) classPtr[i]->subject[0]='\0'; else snprintf(classPtr[i]->subject, sizeof(classPtr[i]->subject), "%s", t->valuestring); i++; } classes.item=i; classes.classResult=classPtr; MSG_INFO(1, "class valid num:%d",i); return; R_EXIT: releaseJson(&classJson); releaseBuf(&classBuffer); if(fd>0) nwy_sdk_fclose(fd); if(classPtr != NULL){ for(i=0;iid=-1; else noticePtr[i]->id=atoi(t->valuestring); //time t=cJSON_GetObjectItem(element, OBJECT_TIME_NAME); if(NULL==t) noticePtr[i]->time[0]='\0'; else snprintf(noticePtr[i]->time, sizeof(noticePtr[i]->time), "%s", t->valuestring); //title t=cJSON_GetObjectItem(element, OBJECT_TITLE_NAME); if(NULL==t) noticePtr[i]->title[0]='\0'; else snprintf(noticePtr[i]->title, sizeof(noticePtr[i]->title), "%s", t->valuestring); i++; } notices.item=i; notices.noticeResult=noticePtr; MSG_INFO(1, "notice valid num:%d",i); return; R_EXIT: releaseJson(¬iceJson); releaseBuf(¬iceBuffer); if(fd>0) nwy_sdk_fclose(fd); if(noticePtr != NULL){ for(i=0;ivaluestring)+1; char *ptr=(char *)createBuf(len*sizeof(char)); if(ptr==NULL){ MSG_ERR(1, "notice detail show malloc err"); goto R_EXIT; } memcpy(ptr, item->valuestring, len); ptr[len]=0; noticeDetailContent=ptr; R_EXIT: releaseJson(&nJson); } void cJSONTakeParam(char *msg, int len){ //msg={"scoreSpeedParam": "1.0","scoreVolumeParam": "1.0"} bool sparamOk=false; bool vparamOk=false; cJSON* nJson=NULL; nJson = createJson(msg); if(NULL==nJson){ MSG_WARN(1, "param detail json null"); goto R_EXIT; } cJSON* item = cJSON_GetObjectItem(nJson, OBJECT_SPEED_PARAM); if(NULL==item) MSG_ERR(1, "param speed json failed"); else{ usr.scoreSpeedParam=atof(item->valuestring); sparamOk=true; } item = cJSON_GetObjectItem(nJson, OBJECT_VOLUME_PARAM); if(NULL==item) MSG_ERR(1, "param volume json failed"); else{ usr.scoreVolumeParam=atof(item->valuestring); vparamOk=true; } if(sparamOk==true && vparamOk==true){ MSG_INFO(1, "sparam:%f, vparam:%f", usr.scoreSpeedParam, usr.scoreVolumeParam); usr.paramReady=true; } R_EXIT: releaseJson(&nJson); } //没获取账户信息,则定时尝试获取 void LearnUsrInfoCheck(unsigned int interval){ static char step=0; static unsigned int waitTimer; unsigned char ret; if(sutPocStatus.logined==0) return; if(true==isUserInfoReady() && true==usr.paramReady){ if(step!=0) step=0; return; } switch(step){ case 0://发起获取账户信息请求 step=1; learnUpdateStatus(LEARN_DB_WAIT_INFO); learnTaskUpdate(LEARN_DB_GET_INFO,NULL, NULL,false); uTimerStart(&waitTimer, 5000); break; case 1://等待获取结果 ret=getHttpLearnStatus(); if(uTimerExpired(&waitTimer) || ret !=1){ MSG_INFO(1, "Wait user account:%d", ret); if(ret==0) step=2; else step=0;//重新获取 } break; case 2://发起参数获取请求 step=3; learnUpdateStatus(LEARN_GET_PARAM); learnTaskUpdate(LEARN_GET_PARAM,NULL, NULL,false); uTimerStart(&waitTimer, 5000); break; case 3://等待获取结果 ret=getHttpLearnStatus(); if(uTimerExpired(&waitTimer) || ret !=1){ MSG_INFO(1, "Wait param:%d", ret); if(ret==0) step=4;//停止 else step=2;//重新获取 } break; case 4://IDLE break; } } void uiShowLearnGroup(char type){ static unsigned int gid=0xffffffff; if(false==isUserInfoReady()) return; if(type) goto S_NOW; if(gid == getLearnGid()) return; gid=getLearnGid(); S_NOW: uiShowLearnGName(getLearnGName()); } void sdUnmount(void){ if(nwy_read_sdcart_status()==0) return; sdCardCtl(false); } void sdMount(void){ if(nwy_read_sdcart_status()!=0) return; sdCardCtl(true); } bool sdCardTest(void){ const char *table="sdTest.txt"; char file[50]; int fd=NULL; bool ret=false; sdMount(); snprintf(file, sizeof(file), "%s/%s",SD_TOKEN,table); fd = nwy_sdk_fopen(file, NWY_CREAT | NWY_RDWR|NWY_TRUNC);//清0式 if(fd<0){ MSG_WARN(1, "fopen to write failed:%s",table); goto SD_END; } nwy_sdk_fwrite(fd, table, strlen(table)); nwy_sdk_fclose(fd); fd = nwy_sdk_fopen(file, NWY_RDONLY); if(fd < 0){ MSG_WARN(1, "fopen to read failed:%s",table); goto SD_END; } memset(file, 0, sizeof(file)); nwy_sdk_fread(fd, file, strlen(table)); if(0==memcmp(file, table, strlen(file))) ret=true; SD_END: if(fd != NULL) nwy_sdk_fclose(fd); sdUnmount(); return ret; }