location.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. #include "includes.h"
  2. #include "location.h"
  3. #include "lsapi_gps.h"
  4. #include "nmea.h"
  5. #define max_neighbor_cellbun 6//定义LSB能存的最大组数
  6. //#define NEED_NEAR_CELLS //使用邻近小区
  7. //最小星数个数条件
  8. #define GPS_MIN_NUM 2
  9. //开启GPS后,定位基本条件达到后最多等待时间
  10. //星数达到一定数目,最多等待GPS_WAIT_MAX_TIME,否则关闭GPS
  11. #define GPS_WAIT_MAX_TIME 10
  12. //开启GPS后,定位基本条件未达到最多等待时间
  13. //星数未达到一定数目,最多等待GPS_WAIT_TIME,否则关闭GPS
  14. #define GPS_WAIT_TIME 20
  15. //GPS定位后,延时一定时间等待稳定后取值
  16. #define GPS_STABLE_TIME 14 //因为GPS回调为5秒,故取14秒吧
  17. //第一次GPS定位所给予最大时间
  18. #define GPS_FIRST_VALID_TIME 180
  19. //每次重启GPS后,如果定位了,直接更新定位标记,否则超过此时间还未定位,则复位定位标志
  20. #define GPS_RESET_TIME 12
  21. //在非作业期间,如果采样间隔小于等此值,GPS采用常开工作模式
  22. #define KEEP_GPS_ON_UN_WORKTIME 15
  23. #if(GPS_RESET_TIME>=GPS_STABLE_TIME) //如果不加这个限制,当GPS异常不再回调后,每次打开GPS都会认为是已定位并取值,但实际都是以前的定位点
  24. #error "GPS时间不允许"
  25. #endif
  26. #ifdef NOT_USE_SERVER_INTERVAL
  27. #define GPS_SAMPLE_TIME 20 //采样间隔,测试
  28. #define GPS_LOCATED_MAX (60*5)
  29. #endif
  30. typedef enum{
  31. GS_IDLE, //GPS空闲,为关闭状态
  32. GS_START, //开始启动GPS
  33. GS_WAIT, //GPS已启动,等待定位
  34. GS_VALID, //GPS已定位
  35. GS_STABLE, //GPS定位延时稳定后取值
  36. GS_STOP, //停止GPS
  37. }GS_ENUM;
  38. typedef struct{
  39. T_UINT8 status; //GS_ENUM GPS业务状态
  40. T_UINT16 waitMaxCnt; //最大等待时间计数
  41. T_UINT16 waitCnt; //最小等待时间计数
  42. T_UINT8 resetCnt; //超时未定位复位定位标记计数
  43. T_UINT8 stableCnt; //等待稳定延时计数
  44. T_UINT8 gpsValid:1; //GPS定位标志 GPS_LOCATION_ENUM
  45. T_UINT8 gpsFirstValid:1; //第一次登陆过的标志
  46. T_UINT8 gpsLstValid:1;
  47. T_UINT8 gpsOnUse; //在用卫星个数
  48. T_UINT8 gpsOnView; //在范围卫星个数
  49. T_UINT8 gpsInterval; //定时起来定位
  50. T_UINT8 gpsDlyCnt; //用于常开模式下延时取值
  51. }GPS_DEF;
  52. GPS_DEF gps={
  53. .status=GS_START,//开机自动开启GPS任务
  54. .gpsInterval=0,
  55. .gpsFirstValid=0,
  56. .gpsOnUse=0,
  57. .gpsOnView=0,
  58. };
  59. T_UINT16 gpsRealSample;
  60. void gpsIntervalMaxInit(void){
  61. #ifdef NOT_USE_SERVER_INTERVAL
  62. gpsRealSample=GPS_SAMPLE_TIME;
  63. #else
  64. gpsRealSample=app.gnssSampleTime;
  65. #endif
  66. if(gpsRealSample<ALL_MIN_SAMPLE_TIME) gpsRealSample=ALL_MIN_SAMPLE_TIME;
  67. }
  68. T_BOOL isGpsLocated(void){
  69. if(gps.gpsValid==GPS_ACTIVE) return TRUE;
  70. else return FALSE;
  71. }
  72. /*
  73. 仅用于打印定位与/未定位的跳变
  74. */
  75. void gpsValidInfo(unsigned char status){
  76. static unsigned char lastStatus=0;
  77. if(lastStatus==status) return;
  78. if(status==0) wlog_info("GPS Unlocated");
  79. else wlog_info("GPS Located");
  80. lastStatus=status;
  81. }
  82. void showNmeaInfo(char *nmea,int len){
  83. int i;
  84. char ch,*nextPtr=nmea;
  85. for(i=0;i<len;i++){
  86. if(ch=='\r' && nmea[i]=='\n'){
  87. ch=nmea[i+1];
  88. nmea[i+1]=0;
  89. msgToOutter(nextPtr);
  90. nextPtr=&nmea[i+1];
  91. nmea[i+1]=ch;
  92. }
  93. ch=nmea[i];
  94. }
  95. }
  96. #define AGPS_GET_INTERVAL (60*60*2) //获取AGPS星表时间间隔
  97. LSAPI_OSI_Thread_t* agpsThread=NULL;
  98. static int64_t agpsNextTime=0;
  99. static unsigned char agpsFailNum=0;
  100. /*
  101. 尝试打开APGS
  102. 打开成功后,如果获取成功,会自动关闭,下次需要时再打开
  103. */
  104. static void agpsEntry(void *param){
  105. wlog_info("agpsEntry start ok");
  106. LSAPI_OSI_Event_t event = {};
  107. for(;;){
  108. LSAPI_OSI_EventWait(LSAPI_OSI_ThreadCurrent(), &event);
  109. if(event.id==USER_ENENT_AGPS){
  110. if(true==LSAPI_GPS_Check_Eph_Valid()){
  111. wlog_info("agps is already valid");
  112. agpsNextTime += AGPS_GET_INTERVAL;
  113. }else{
  114. wlog_info("exe agps api");
  115. if(0==LSAPI_GPS_Write_EPH()){
  116. agpsNextTime += AGPS_GET_INTERVAL;
  117. wlog_info("agps set valid ok");
  118. agpsFailNum=0;
  119. }else{
  120. wlog_warn("agps set valid failed");
  121. agpsNextTime += AGPS_GET_INTERVAL;
  122. agpsFailNum++;
  123. }
  124. }
  125. }
  126. }
  127. agpsThread=NULL;
  128. LSAPI_OSI_ThreadExit();
  129. }
  130. void tryToEnableAgps(void){
  131. if(agpsThread==NULL){
  132. agpsThread=LSAPI_OSI_ThreadCreate("agpsEntry", agpsEntry, NULL, LSAPI_OSI_PRIORITY_NORMAL, AGPS_THRAD_THREAD_STACK, 4);
  133. if(agpsThread==NULL){
  134. wlog_warn("agpsThread create error");
  135. agpsNextTime += 30;
  136. return;
  137. }
  138. }
  139. threadPostEvent(agpsThread,USER_ENENT_AGPS ,NULL);
  140. }
  141. /*AGPS控制
  142. 当打开了GPS时,尝试打开AGPS
  143. AGPS为一次性,打开成功后会自动关闭
  144. 下次一次成,最少能使用2个小时
  145. */
  146. void agpsCtl(void){
  147. int64_t tmp;
  148. static unsigned char cnt=0;
  149. if(agpsFailNum>=5){
  150. if(++cnt>=5){
  151. cnt=0;
  152. wlog_warn("Agps Open faild in %d time, stop use agps", agpsFailNum);
  153. }
  154. return;
  155. }
  156. if(app.netWork.netReayd!=0){//尝试打开AGPS
  157. if(cnt==0){//5秒读一次时间比较
  158. tmp=LSAPI_OSI_UpTime()/1000;
  159. if(tmp>agpsNextTime){
  160. agpsNextTime=tmp;
  161. tryToEnableAgps();
  162. }else wlog_info("agps:%d",agpsNextTime-tmp);
  163. }
  164. if(++cnt>=5) cnt=0;
  165. }else cnt=0;
  166. }
  167. #ifdef ENABLE_SET_GPS_INTERVAL
  168. //如果设定GPS回调为5秒,则GPS无响应超时值设置为5*10=50秒
  169. #define MAX_CNT_FOR_GPS_TIMEOUT 50
  170. #else
  171. //如果设定GPS回调为1秒,则GPS无响应超时值设置为1*10=10秒
  172. #define MAX_CNT_FOR_GPS_TIMEOUT 10
  173. #endif
  174. /*
  175. $GNXXX
  176. 我们需要
  177. $GNRMC
  178. $GNGSA
  179. */
  180. static T_UINT8 cntAfterNoCb=0;
  181. void gpsCntChecker(void){
  182. static char rstgps=0;
  183. #if 0
  184. if(app.gpsPwrStatus==FALSE){
  185. app.gpsCallBackCnt=0;
  186. return;
  187. }
  188. if(++app.gpsCallBackCnt>=MAX_CNT_FOR_GPS_TIMEOUT){
  189. app.gpsCallBackCnt=0;
  190. wlog_error("gpsCallBackCnt over,reboot sys!!!");
  191. #if 0//for test only
  192. outterInfo("gpsCntChecker to TG mode\r\n",26);
  193. app.tgMode=TRUE;
  194. return;
  195. #endif
  196. #ifdef TAKE_NOTE_FOR_REBOOT
  197. saveRebootReason("gpsCntChecker\r\n");
  198. #endif
  199. LSAPI_OSI_ThreadSleep(500);
  200. LSAPI_SYS_reboot();
  201. }
  202. #else
  203. if(rstgps==1){
  204. wlog_error("gpsCallBackCnt stop gps!!");
  205. gpsStop();
  206. rstgps=2;
  207. return;
  208. }else if(rstgps==2){
  209. wlog_info("gpsCallBackCnt start gps!!");
  210. gpsStart();
  211. app.gpsCallBackCnt=0;
  212. rstgps=0;
  213. }
  214. if(app.gpsPwrStatus==FALSE){
  215. app.gpsCallBackCnt=0;
  216. return;
  217. }
  218. if(++app.gpsCallBackCnt>=MAX_CNT_FOR_GPS_TIMEOUT){
  219. app.gpsCallBackCnt=0;
  220. if(++cntAfterNoCb>=3){
  221. cntAfterNoCb=0;
  222. if(app.vcharge<30){
  223. wlog_error("gpsCallBackCnt reboot!!");
  224. #ifdef TAKE_NOTE_FOR_REBOOT
  225. saveRebootReason("gpsCntChecker\r\n");
  226. #endif
  227. LSAPI_OSI_ThreadSleep(500);
  228. LSAPI_SYS_reboot();
  229. }else wlog_warn("dev is charging, skip reboot");
  230. }else{
  231. wlog_error("gpsCallBackCnt reset gps!!");
  232. rstgps=1;
  233. }
  234. }
  235. #endif
  236. }
  237. char gpsTmp[1024+512];
  238. int gpsLen;
  239. void get_location_callback(void *location,int len){
  240. int i,index;
  241. char *rmc,*gsa,*src,ch,*nextPtr;
  242. unsigned char done=0;
  243. unsigned char onUseGps=0,onViewGps=0,onViewBd=0;
  244. char *ptr=(char *)location;
  245. cntAfterNoCb=0;
  246. app.gpsCallBackCnt=0;
  247. if(len>=sizeof(gpsTmp)){
  248. wlog_warn("gpstmp over, return");
  249. return;
  250. }
  251. gpsLen=0;
  252. for(i=0;i<len;i++) gpsTmp[gpsLen++]=ptr[i];
  253. gpsTmp[gpsLen]=0;
  254. if(app.tgMode==TRUE){
  255. showNmeaInfo(gpsTmp,gpsLen);
  256. return;
  257. }
  258. #if defined ENABLE_QUE_TASK_LOCK
  259. uint32_t osFlag;
  260. osFlag=osiSchedulerSuspend();
  261. #endif
  262. //处理并更新定位标志gps.gpsValid以及相关位置变量
  263. src=gpsTmp;
  264. nextPtr=src;
  265. for(i=0;i<len;i++){
  266. if(ch=='\r' && src[i]=='\n'){
  267. src[i-1]=0;
  268. if(0==memcmp(nextPtr, "$GNGGA",6)){//获取在使用卫星数
  269. //$GNGGA,080420.00,2237.25706,N,11402.10753,E,1,07,6.20,85.3,M,-2.2,M,,*68
  270. //wlog_info(nextPtr);
  271. index=findByteFromStr(nextPtr, strlen(nextPtr),',',7);
  272. if(index>=0){
  273. index=atoi(nextPtr+index);
  274. onUseGps=index;
  275. }
  276. done |= 1<<0;
  277. }else if(0==memcmp(nextPtr, "$GPGSV",6)){//获取在范围GPS卫星数
  278. //$GPGSV,3,2,12,12,33,272,,13,21,180,34,15,02,205,,17,29,136,36,0*61
  279. //wlog_info(nextPtr);
  280. index=findByteFromStr(nextPtr, strlen(nextPtr),',',3);
  281. if(index>=0){
  282. index=atoi(nextPtr+index);
  283. onViewGps=index;
  284. }
  285. done |= 1<<1;
  286. }else if(0==memcmp(nextPtr, "$BDGSV",6)){//获取在范围GPS卫星数
  287. //$BDGSV,4,1,13,01,46,124,28,02,48,238,,03,65,189,29,04,33,110,36,0*70
  288. //wlog_info(nextPtr);
  289. index=findByteFromStr(nextPtr, strlen(nextPtr),',',3);
  290. if(index>=0){
  291. index=atoi(nextPtr+index);
  292. onViewBd=index;
  293. }
  294. done |= 1<<2;
  295. }else if(0==memcmp(nextPtr, "$GNRMC",6)){//获取定位信息
  296. //$GNRMC,080410.00,A,2237.25264,N,11402.10765,E,0.018,,030720,,,A,V*16
  297. //wlog_info(nextPtr);
  298. nmeaRmc(nextPtr+7);
  299. done |= 1<<3;
  300. }
  301. nextPtr=&src[i+1];
  302. }
  303. ch=src[i];
  304. if(done==0x0F) break;
  305. }
  306. //更新参数
  307. gps.gpsOnUse=onUseGps;
  308. gps.gpsOnView=onViewGps+onViewBd;
  309. gpsValidInfo(nmeaInfo.isGpsValid);
  310. gps.gpsValid=nmeaInfo.isGpsValid;
  311. if(gps.gpsValid==GPS_INVALID){
  312. gps.gpsDlyCnt=0;
  313. #if defined ENABLE_QUE_TASK_LOCK
  314. osiSchedulerResume(osFlag);
  315. #endif
  316. return;
  317. }
  318. gps.gpsFirstValid=gps.gpsValid;
  319. #if defined ENABLE_QUE_TASK_LOCK
  320. osiSchedulerResume(osFlag);
  321. #endif
  322. //如果已休眠,定位成功时,可以唤醒一下
  323. WakeupNow("gps call_cb located");
  324. }
  325. #ifdef ENABLE_SET_GPS_INTERVAL
  326. #define GPS_INTERVAL "$CCINV,5000*78"
  327. void setGpsInterval(void){
  328. LSAPI_OSI_ThreadSleep(1000);
  329. if(false==LSAPI_SendData_To_GPS(GPS_INTERVAL,strlen(GPS_INTERVAL))) wlog_warn("!!!GPS INTERVAL SET FAILSE");
  330. else wlog_warn("!!!GPS INTERVAL SET OK");
  331. }
  332. #else
  333. void setGpsInterval(void){
  334. return;
  335. }
  336. #endif
  337. LSAPI_OSI_Thread_t *threadid_gps = NULL;
  338. void gpsEntry(void *param){
  339. LSAPI_OSI_Event_t event = {};
  340. wlog_info("gpsEntry thread start");
  341. for(;;){
  342. LSAPI_OSI_EventWait(threadid_gps, &event);
  343. wlog_info("gpsEntry get event:%d",event.param1);
  344. if(event.param1==1){//打开GPS
  345. if(app.gpsPwrStatus==FALSE){
  346. LSAPI_GPS_Init();
  347. LSAPI_GPS_Set_StartMode(GPS_START_MODE_HOT);
  348. LSAPI_GPS_Set_ANTMode(1);//0 无源 1 有源
  349. LSAPI_GPS_Open(NULL);
  350. setGpsInterval();
  351. LSAPI_GPS_Get_ALLData(get_location_callback);
  352. app.gpsPwrStatus=TRUE;
  353. wlog_info("gps start done");
  354. }else wlog_info("gps already on");
  355. }else if(event.param1==0){//关闭GPS
  356. LSAPI_GPS_Close();
  357. nmeaInfo.isGpsValid=GPS_INVALID;
  358. app.gpsPwrStatus=FALSE;
  359. wlog_info("gps stop done");
  360. }
  361. }
  362. threadid_gps=NULL;
  363. LSAPI_OSI_ThreadExit();
  364. }
  365. void gpsStart(void){
  366. wlog_info("try to start gps");
  367. if(NULL==threadid_gps){
  368. threadid_gps=LSAPI_OSI_ThreadCreate("gps",gpsEntry,NULL,LSAPI_OSI_PRIORITY_NORMAL,GPS_THREAD_STACK,4);
  369. if(NULL==threadid_gps){
  370. wlog_error("gps thread create failed!");
  371. return;
  372. }
  373. }
  374. wlog_info("gps send start event");
  375. threadPostEvent(threadid_gps,USER_EVENT_GPS,1);//start gps
  376. }
  377. void gpsStop(void){
  378. wlog_info("try to stop gps");
  379. gps.status=GS_IDLE;
  380. if(NULL==threadid_gps){
  381. wlog_warn("gps thread off, quit gpsStop");
  382. return;
  383. }
  384. wlog_info("gps send stop event");
  385. threadPostEvent(threadid_gps,USER_EVENT_GPS,0);//stop gps
  386. wlog_info("GPS Stop,restart after %ds",gpsRealSample);
  387. }
  388. void ActiveTgMode(void){
  389. app.tgMode=TRUE;
  390. gpsStart();
  391. }
  392. /*
  393. ptLocationTask任务投票处理
  394. */
  395. void isLocationTaskIdle(void){
  396. if(GS_IDLE==gps.status || GS_WAIT==gps.status) ticketVote(TICKET_PT_LOCATION);//开关模式下的等待定位时也可以休眠
  397. else ticketDeVote(TICKET_PT_LOCATION);
  398. }
  399. /*
  400. 控制GPS任务运行与停止
  401. 默认情况GPS任务一直运行
  402. 此功能API只提供mcuiap使用
  403. */
  404. void locationWorkCtl(T_BOOL status){
  405. #ifdef KEEP_GPS_ON_FOEVER
  406. if(TRUE==status) gpsStart();
  407. else gpsStop();
  408. #else
  409. if(TRUE==status){
  410. gps.status=GS_START;
  411. }else gpsStop();
  412. #endif
  413. }
  414. /*非作业期间,根据采样间隔,判定GPS是否执行常开业务或开关业务*/
  415. T_BOOL isGpsKeepOnByTime(void){
  416. if(gpsRealSample<=KEEP_GPS_ON_UN_WORKTIME) return TRUE;
  417. else return FALSE;
  418. }
  419. /*作业期间GPS业务逻辑:常开工作
  420. 非作业期间GPS采样时间小于设定限值:常开工作*/
  421. void gpsKeepOnToWork(void){
  422. static T_BOOL isGpsStart=FALSE;
  423. if(FALSE==isGpsStart){//打开GPS
  424. gpsStart();
  425. isGpsStart=TRUE;
  426. }
  427. ticketVote(TICKET_PT_LOCATION);
  428. if(gps.gpsValid != gps.gpsLstValid){
  429. if(gps.gpsValid==GPS_ACTIVE) gps.gpsInterval=gpsRealSample;//从未定位到定位,直接可以取值,当然,第一次时会延时
  430. gps.gpsLstValid=gps.gpsValid;
  431. }
  432. if(gps.gpsValid==GPS_ACTIVE){//已定位
  433. if(++gps.gpsInterval>=gpsRealSample){
  434. if(++gps.gpsDlyCnt>GPS_STABLE_TIME){
  435. //保存一个记录点
  436. gps.gpsInterval=0;
  437. gnssInfoSave();
  438. gps.gpsDlyCnt=GPS_STABLE_TIME;
  439. }else{
  440. wlog_info("Delay cnt:%d<%d",gps.gpsDlyCnt,GPS_STABLE_TIME);
  441. ticketDeVote(TICKET_PT_LOCATION);//不让休眠,否则gps.gpsDlyCnt不准
  442. }
  443. }
  444. }else gps.gpsInterval=0;//未定位时可以休眠最大时间
  445. }
  446. /*非作业期间GPS采样时间大于设定限值:开关工作*/
  447. void gpsOnOffToWork(void){
  448. static T_UINT16 lastWaitCnt=0;
  449. T_BOOL needsave=FALSE;
  450. switch(gps.status){
  451. case GS_IDLE:
  452. if(++gps.gpsInterval >= gpsRealSample){
  453. gps.gpsInterval=0;
  454. gps.status=GS_START;
  455. }
  456. break;
  457. case GS_START://启动GPS
  458. gps.status=GS_WAIT;
  459. gps.waitCnt=0;
  460. gps.waitMaxCnt=0;
  461. gps.resetCnt=0;
  462. gps.gpsOnUse=0;
  463. gps.gpsOnView=0;
  464. //gps.gpsValid=GPS_INVALID;//不主动关闭
  465. gps.gpsInterval=0;
  466. gpsStart();
  467. break;
  468. case GS_WAIT:
  469. //定位过程中,打印下计数值吧
  470. if(gps.waitCnt>lastWaitCnt+5){
  471. wlog_info("gps onTime:%d",gps.waitCnt);
  472. lastWaitCnt=gps.waitCnt;
  473. }
  474. //检测GPS定位标志,定位则切换状态
  475. if(gps.gpsValid==GPS_ACTIVE){
  476. gps.status=GS_VALID;
  477. break;
  478. }
  479. #ifdef NOT_USE_SERVER_INTERVAL
  480. if(++gps.waitCnt>=GPS_LOCATED_MAX){
  481. wlog_warn("gps timeout");
  482. needsave=TRUE;
  483. gps.status=GS_STOP;
  484. }
  485. #else
  486. //定位时间超时检测
  487. if(gps.gpsFirstValid==1){//已定位过了
  488. if(gps.gpsOnUse<GPS_MIN_NUM){
  489. if(++gps.waitCnt>=GPS_WAIT_TIME){
  490. //星数条件差但超时未定位,退出
  491. wlog_warn("gps weak timeout");
  492. needsave=TRUE;
  493. gps.status=GS_STOP;
  494. }
  495. }else{
  496. if(++gps.waitMaxCnt>=GPS_WAIT_MAX_TIME){
  497. //星数条件好但超时未定位,退出
  498. wlog_warn("gps strong timeout");
  499. needsave=TRUE;
  500. gps.status=GS_STOP;
  501. }
  502. }
  503. }else{
  504. if(++gps.waitCnt>=GPS_FIRST_VALID_TIME){
  505. wlog_warn("gps first valid timeout");
  506. needsave=TRUE;
  507. gps.status=GS_STOP;
  508. }
  509. }
  510. #endif
  511. //定位标志超时复位检测
  512. if(++gps.resetCnt>=GPS_RESET_TIME){
  513. gps.gpsValid=GPS_INVALID;
  514. gps.resetCnt=0;
  515. }
  516. break;
  517. case GS_VALID:
  518. gps.stableCnt=0;
  519. gps.status=GS_STABLE;
  520. break;
  521. case GS_STABLE:
  522. if(gps.gpsValid==GPS_INVALID){
  523. //在等待稳定期间突然定位不了了,继续回到GS_WAIT状态,计数值不清0,按原来时间顺延
  524. gps.status=GS_WAIT;
  525. break;
  526. }
  527. if(++gps.stableCnt>=GPS_STABLE_TIME){
  528. //稳定后得到了定位数据,这里是要保存定位数据等待上传时刻到来执行上传
  529. wlog_info("Get valid gps data:%lu,%lu",nmeaInfo.Latitude,nmeaInfo.Longitude);
  530. needsave=TRUE;
  531. gps.status=GS_STOP;
  532. }
  533. break;
  534. case GS_STOP:
  535. gpsStop();
  536. gps.gpsInterval=0;
  537. break;
  538. }
  539. if(needsave==TRUE) gnssInfoSave();
  540. isLocationTaskIdle();
  541. }
  542. /*
  543. GPS定位及逻辑控制pt任务
  544. */
  545. PT_THREAD (ptLocationTask(pt_timer_t *ptPool, struct pt *pt)){
  546. static pt_timer_t ptTimer;
  547. static unsigned char lastWorkZone=0xff;
  548. static unsigned char forceGpsOnOffMode=35;
  549. PT_BEGIN(pt);
  550. while(1){
  551. //检测作业状态变化
  552. if(sut_para.forceGpsOnOffMode != forceGpsOnOffMode){
  553. forceGpsOnOffMode=sut_para.forceGpsOnOffMode;
  554. wlog_warn("gpsForce:%s", (forceGpsOnOffMode!=0)?"keep on":"onOff");
  555. }
  556. if(forceGpsOnOffMode==0) gpsOnOffToWork();
  557. else{
  558. if(lastWorkZone != app.onWorkZone){
  559. lastWorkZone=app.onWorkZone;
  560. //工作状态发变化,检查GPS状态
  561. if(lastWorkZone==0){//从作业状态变为非作业状态
  562. wlog_warn("work-->non_work");
  563. if(isGpsKeepOnByTime()==TRUE){//采样小于设定值,GPS继续常开工作模式
  564. wlog_warn("gps keep on mode");
  565. }else{//GPS开关工作模式
  566. wlog_warn("gps onOff mode");
  567. gps.status=GS_WAIT;
  568. gps.waitCnt=0;
  569. }
  570. }else{//从非作业状态变为作业状态
  571. wlog_warn("non_work-->work");
  572. gps.gpsValid=GPS_INVALID;//消除定位标记
  573. }
  574. gps.gpsInterval=0;
  575. if(app.gpsPwrStatus==FALSE) gpsStart();
  576. }
  577. //定向工作模式
  578. if(lastWorkZone==0) gpsOnOffToWork();
  579. else gpsKeepOnToWork();
  580. }
  581. //apgs工作
  582. agpsCtl();
  583. PTTimerStart(ptPool, &ptTimer,100);
  584. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  585. }
  586. PT_END(pt);
  587. }
  588. /*
  589. 获取GPS可休眠时间,投票ticket调用
  590. */
  591. T_INT32 getLocationCnt(void){
  592. T_INT32 value;
  593. if(app.onWorkZone==0 && FALSE==isGpsKeepOnByTime()){//开关模式下
  594. return 5;//开关模式下可以睡长一些,只要定位上,会唤醒的
  595. }else{//常开模式下
  596. value=gpsRealSample-gps.gpsInterval;
  597. if(value<=0) return 0;
  598. else return value;
  599. }
  600. }
  601. /*
  602. 每次休眠唤醒后更新GPS逻辑计数值
  603. */
  604. void locationCntUpdate(T_INT32 value){
  605. if(gps.gpsInterval+value > gpsRealSample) gps.gpsInterval=gpsRealSample;
  606. else gps.gpsInterval += value;
  607. gps.waitCnt += value;
  608. }
  609. /*将定位信息更新到记录结构体中*/
  610. void gnssInfoSave(void){
  611. char ret;
  612. #if defined ENABLE_QUE_TASK_LOCK
  613. uint32_t osFlag;
  614. osFlag=osiSchedulerSuspend();
  615. #endif
  616. memset((unsigned char *)gGnssInfo, 0, sizeof(GNSSINFO_DEF));
  617. memcpy(gGnssInfo->BCDTime, getBCDDateTime(), sizeof(gGnssInfo->BCDTime));
  618. if(gps.gpsValid==GPS_ACTIVE) gGnssInfo->located=1;
  619. else gGnssInfo->located=0;
  620. gGnssInfo->onUseGps=gps.gpsOnUse;
  621. gGnssInfo->onViewGps=gps.gpsOnView;
  622. gps.gpsOnUse=0;gps.gpsOnView=0;
  623. if(gps.gpsValid==GPS_ACTIVE){
  624. gGnssInfo->latitude=nmeaInfo.Latitude;
  625. gGnssInfo->longitude=nmeaInfo.Longitude;
  626. gGnssInfo->height=nmeaInfo.Altitude;
  627. gGnssInfo->speed=nmeaInfo.Speed;
  628. gGnssInfo->direction=nmeaInfo.Aspect;
  629. }
  630. #if defined ENABLE_QUE_TASK_LOCK
  631. osiSchedulerResume(osFlag);
  632. #endif
  633. if(gps.gpsValid!=GPS_ACTIVE) return;
  634. //保存
  635. ret=recordSave(REC_GNSSINFO,(void *)&sut_saveRecGnss);
  636. wlog_info("gnss save ret:%d",ret);
  637. GnssRecShow();
  638. }
  639. ///////////////////////////////////////LSB///////////////////////////////////////////////////
  640. int getGnssCnt(void){
  641. int leftTime;
  642. leftTime=getBaseSeconds()%app.gnssSampleTime;
  643. if(leftTime==0) return NO_SLEEP_TIME;
  644. else return (app.gnssSampleTime-leftTime);
  645. }
  646. static unsigned char lbsStatus=0; //0未开启获取 1正在获取 2获取超时 3获取成功 4获取失败
  647. static unsigned char motionStatus=0;//0未开启获取 1正在获取 2获取超时 3获取成功 4获取失败
  648. static unsigned char lm_cnt=0;
  649. LSAPI_OSI_Thread_t *lbsThread=NULL;
  650. void motionGetOk(void){motionStatus=3;}
  651. #ifdef NEED_NEAR_CELLS
  652. /*
  653. 根据LBS值得到经纬度值的回调
  654. */
  655. void lbs_callback(void *lac,void *lng){
  656. wlog_info("lbs_callback:lac=%s,lng=%s",lac,lng);//lac=22.6182549,lng=114.0404818
  657. }
  658. #endif
  659. void lbsStart(void){
  660. LSAPI_CellLocation_t nCellInfo[max_neighbor_cellbun];
  661. //SUTDS ds;
  662. int num,count;
  663. if(app.netWork.netReayd==0) return;
  664. //先获取主小区信息
  665. memset(nCellInfo,0x00,sizeof(nCellInfo));
  666. LSAPI_NET_CellInfo(nCellInfo,LSAPI_pCurrCellInfo,0);
  667. if(nCellInfo[0].sCellID != 0){
  668. lbsStatus=3;
  669. //mcc
  670. gDevInfo->mcc=nCellInfo[0].sMcc[0]*100+nCellInfo[0].sMcc[1]*10+nCellInfo[0].sMcc[2];
  671. //lac
  672. gDevInfo->lac=nCellInfo[0].sLac;
  673. //cellid
  674. gDevInfo->cellid=nCellInfo[0].sCellID;
  675. //mnc
  676. if(nCellInfo[0].sMnc[2]==0x0f) gDevInfo->mnc=nCellInfo[0].sMnc[0]*10+nCellInfo[0].sMnc[1];
  677. else gDevInfo->mnc=nCellInfo[0].sMnc[0]*100+nCellInfo[0].sMnc[1]*10+nCellInfo[0].sMnc[2];
  678. wlog_info("mcc:%d,mnc:%d,lac:%x,cellid:%x",gDevInfo->mcc,gDevInfo->mnc,gDevInfo->lac,gDevInfo->cellid);
  679. }else lbsStatus=4;
  680. #ifdef NEED_NEAR_CELLS
  681. //再获取邻近小区信息
  682. memset(nCellInfo,0x00,sizeof(nCellInfo));
  683. LSAPI_NET_CellInfo(nCellInfo,LSAPI_NeighborCellInfo,0);
  684. num=nCellInfo[0].neighbor_cellnum;
  685. wlog_info("neighbor num:%d",num);
  686. if(num>=3) LSAPI_LBS_Location(nCellInfo,lbs_callback,0);//有3个邻近以上则获取经纬度
  687. #endif
  688. }
  689. /*
  690. LBS获取线程
  691. */
  692. void CEllEntry(void *param)
  693. {
  694. wlog_info("CellEntry init");
  695. LSAPI_OSI_Event_t event = {};
  696. for(;;){
  697. LSAPI_OSI_EventWait(LSAPI_OSI_ThreadCurrent(), &event);
  698. if(event.id==USER_EVENT_LSB) lbsStart();
  699. }
  700. lbsThread=NULL;
  701. LSAPI_OSI_ThreadExit();
  702. }
  703. /*
  704. LBS初始化操作
  705. pt任务会调用
  706. */
  707. void CellInit(void){
  708. static T_BOOL cellActive=FALSE;
  709. if(app.netWork.netReayd==0) return;
  710. if(cellActive==TRUE) return;
  711. //创建LBS线程获取LBS
  712. lbsThread=LSAPI_OSI_ThreadCreate("cellid", CEllEntry,NULL,LSAPI_OSI_PRIORITY_NORMAL,LBS_THREAD_STACK,4);
  713. cellActive=TRUE;
  714. }
  715. /*
  716. 获取LBS接口
  717. */
  718. void getLbsMotionNow(void){
  719. threadPostEvent(lbsThread,USER_EVENT_LSB,NULL);
  720. }
  721. void isLbsMotionIdle(void){
  722. int csq;
  723. char ret;
  724. lm_cnt++;
  725. if(lbsStatus==1 && lm_cnt>=5){
  726. lbsStatus=2;
  727. wlog_warn("get lbs timeout");
  728. }
  729. if(motionStatus==1 && lm_cnt>=5){
  730. motionStatus=2;
  731. wlog_warn("get motion timeout");
  732. }
  733. if(lm_cnt>=5 || ((lbsStatus==3 || lbsStatus==4) && (motionStatus==3 || motionStatus==4))){
  734. //结束(成功/失败/超时)
  735. ticketVote(TICKET_PT_LBSMOTION);
  736. //检测是否需要保存消息
  737. if(lbsStatus==3 || motionStatus==3){
  738. //保存记录
  739. //获取CSQ
  740. #if 1
  741. if(0==LSAPI_NET_GetCsq(&csq)) gDevInfo->csq=(unsigned char)csq;
  742. else gDevInfo->csq=99;//获取失败,认为异常
  743. gDevInfo->bat=app.vBatPersent;
  744. gDevInfo->hardWareStatus=app.hardWareSta;
  745. gDevInfo->warnStatus=app.warnStatus;
  746. //保存获取到的时间
  747. memcpy(gDevInfo->BCDTime, getBCDDateTime(), sizeof(gDevInfo->BCDTime));
  748. //保存
  749. ret=recordSave(REC_DEVINFO,(void *)&sut_saveRecDev);
  750. DevRecShow();
  751. #endif
  752. wlog_warn("recordSave:lsb=%d,mot=%d,ret=%d",lbsStatus,motionStatus,ret);
  753. lbsStatus=0;motionStatus=0;
  754. }
  755. }
  756. if((getBaseSeconds()%app.devSampleTime)==0){
  757. wlog_info("start get lsb/motion");
  758. lm_cnt=0;
  759. clearLbsMotionOfDevinfo();
  760. if(motionStatus != 1){
  761. motionStatus=1;
  762. getMotionInfo();
  763. }
  764. if(lbsStatus != 1){
  765. lbsStatus=1;
  766. getLbsMotionNow();
  767. }
  768. ticketDeVote(TICKET_PT_LBSMOTION);
  769. }
  770. }
  771. static T_UINT16 lbsCnt=0;
  772. /*
  773. 获取LBS与MOTION逻辑控制pt任务
  774. */
  775. PT_THREAD (ptLbsMotionTask(pt_timer_t *ptPool, struct pt *pt)){
  776. static pt_timer_t ptTimer;
  777. CellInit();
  778. PT_BEGIN(pt);
  779. while(1){
  780. isLbsMotionIdle();
  781. PTTimerStart(ptPool, &ptTimer,100);
  782. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  783. }
  784. PT_END(pt);
  785. }
  786. #define COMPARE_BY_MINUTE
  787. /*判定当前时间是在工作期间与否*/
  788. T_BOOL isOnWorkZoneNow(void){
  789. unsigned char *curTime;
  790. ARRANGE_SEG_DEF *arrange;
  791. int i;
  792. #ifdef FORCE_ONWORK_STATUS
  793. return TRUE;
  794. #endif
  795. #ifdef COMPARE_BY_MINUTE
  796. unsigned int curT,startT,endT;
  797. #endif
  798. curTime=getBCDDateTime();
  799. if(0!=memcmp(curTime, sut_para.arrange.bcdDate,sizeof(sut_para.arrange.bcdDate))) return FALSE;
  800. if(sut_para.arrange.num==0) return FALSE;
  801. for(i=0;i<sut_para.arrange.num;i++){
  802. arrange=&sut_para.arrange.arrangeList[i];
  803. #ifdef COMPARE_BY_MINUTE
  804. //转换成分钟来比较
  805. curT=bcdToDec(curTime[3])*60+bcdToDec(curTime[4]);
  806. startT=bcdToDec(arrange->startH)*60+bcdToDec(arrange->startM);
  807. endT=bcdToDec(arrange->endH)*60+bcdToDec(arrange->endM);
  808. if(curT>=startT && curT<endT) return TRUE;
  809. #else
  810. if(curTime[3]==arrange->startH && curTime[3]==arrange->endH){
  811. if(curTime[4]>=arrange->startM && curTime[4]<=arrange->endM) return TRUE;
  812. }else if(curTime[3]>=arrange->startH && curTime[3]<arrange->endH) return TRUE;
  813. #endif
  814. }
  815. return FALSE;
  816. }
  817. /*实际使用GPS采样间隔限制*/
  818. void forceGnssInterval(void){
  819. T_UINT16 maxInterval;
  820. if(app.onWorkZone==0) maxInterval=60;
  821. else maxInterval=20;
  822. if(app.gnssSampleTime<maxInterval){
  823. app.gnssSampleTime=maxInterval;
  824. wlog_warn("gnss interval too small, force to %d",maxInterval);
  825. }
  826. }
  827. /*定期检测当前是否发生工作期与非工作期间的切换
  828. 通过创建定时器实现每分钟检测
  829. */
  830. void onWorkChecking(T_BOOL right_now){
  831. unsigned char status=TRUE,nowStatus;
  832. if(app.onWorkZone==0) status=FALSE;
  833. nowStatus=isOnWorkZoneNow();
  834. if(status==nowStatus && FALSE==right_now) goto SHOW_INFO;
  835. //工作状态发生变化
  836. if(nowStatus==TRUE){
  837. app.onWorkZone=1;
  838. app.devSampleTime=sut_para.devSampleInterval;
  839. app.gnssSampleTime=sut_para.gnssSampleInterval;
  840. app.nearSampleTime=sut_para.nearSampleInterval;
  841. app.dataUploadTime=sut_para.dataUploadInterval;
  842. //是否需要更新当前每项的计数值
  843. }else{
  844. app.onWorkZone=0;
  845. app.devSampleTime=sut_para.devSampleInterval_N;
  846. app.gnssSampleTime=sut_para.gnssSampleInterval_N;
  847. app.nearSampleTime=sut_para.nearSampleInterval_N;
  848. app.dataUploadTime=sut_para.dataUploadInterval_N;
  849. }
  850. SHOW_INFO:
  851. if(nowStatus==TRUE) wlog_info("onWorkNow");
  852. else wlog_info("non_onWorkNow");
  853. forceGnssInterval();
  854. wlog_info("[para]devInt:%d,gnssInt:%d,nearInt:%d,dataInt:%d",sut_para.devSampleInterval,sut_para.gnssSampleInterval,sut_para.nearSampleInterval,sut_para.dataUploadInterval);
  855. wlog_info("[para]devIntN:%d,gnssIntN:%d,nearIntN:%d,dataIntN:%d",sut_para.devSampleInterval_N,sut_para.gnssSampleInterval_N,sut_para.nearSampleInterval_N,sut_para.dataUploadInterval_N);
  856. wlog_info("[app]devInt:%d,gnssInt:%d,nearInt:%d,dataInt:%d",app.devSampleTime,app.gnssSampleTime,app.nearSampleTime,app.dataUploadTime);
  857. gpsIntervalMaxInit();
  858. }
  859. LSAPI_OSI_Timer_t *pOnWorktimer_t = NULL;
  860. LSAPI_OSI_Thread_t *threadid_onworktimer = NULL;
  861. void onWorkTimeout_cb(void *param){
  862. WakeupNow("onWorkTimeout_cb");
  863. LSAPI_OSI_TimerStop(pOnWorktimer_t);
  864. onWorkChecking(FALSE);
  865. if(pOnWorktimer_t != NULL){
  866. LSAPI_OSI_TimerStart(pOnWorktimer_t, 60*1000);
  867. wlog_info("onWorkTimer restart ok");
  868. }
  869. }
  870. void onWorkTimerEntry(void *param){
  871. LSAPI_OSI_Event_t event = {};
  872. wlog_info("onWorkTimerEntry start");
  873. if(NULL==pOnWorktimer_t){
  874. pOnWorktimer_t = LSAPI_OSI_TimerCreate(LSAPI_OSI_ThreadCurrent(), onWorkTimeout_cb, NULL);
  875. if(pOnWorktimer_t==NULL) wlog_error("pOnWorktimer_t create error");
  876. else{
  877. LSAPI_OSI_TimerStart(pOnWorktimer_t, 60*1000);
  878. wlog_info("onWorkTimerInit done");
  879. }
  880. }
  881. for(;;){
  882. LSAPI_OSI_EventWait(LSAPI_OSI_ThreadCurrent(), &event);
  883. }
  884. }
  885. void onWorkTimerInit(void){
  886. if(NULL!=threadid_onworktimer) return;
  887. threadid_onworktimer = LSAPI_OSI_ThreadCreate("onWorkTimer", onWorkTimerEntry,NULL,LSAPI_OSI_PRIORITY_NORMAL,ONWORKTIMER_THREAD_STACK,4);
  888. if(NULL==threadid_onworktimer) wlog_error("onWorkTimer create failed");
  889. }
  890. /////////////////////////////////////////////以下为NEAR信息收集pt任务
  891. static unsigned char nearStatus=0; //0未开启获取 1正在获取 2获取超时 3获取成功 4获取失败
  892. static unsigned char near_cnt=0;
  893. void getNearOk(void){nearStatus=3;}
  894. void isNearIdle(void){
  895. char ret;
  896. near_cnt++;
  897. if(nearStatus==1 && near_cnt>=5){
  898. nearStatus=2;
  899. wlog_warn("get near timeout");
  900. }
  901. if(near_cnt>=5 || (nearStatus==3 || nearStatus==4)){
  902. //结束(成功/失败/超时)
  903. ticketVote(TICKET_PT_NEAR);
  904. //检测是否需要保存消息
  905. if(nearStatus==3){
  906. //保存记录
  907. if(gNearInfo->num>0){
  908. //保存获取到的时间
  909. //时间已在前面保存了
  910. //保存
  911. ret=recordSave(REC_NEARINFO,(void *)&sut_saveRecNear);
  912. NearRecShow();
  913. wlog_warn("recordSave:nearNum=%d,ret=%d",gNearInfo->num,ret);
  914. }else wlog_warn("no near num");
  915. nearStatus=0;
  916. }
  917. }
  918. if((getBaseSeconds()%app.nearSampleTime)==0){
  919. wlog_info("start get near info");
  920. near_cnt=0;
  921. gNearInfo->num=0;//每次获取near前,清掉个数即可
  922. if(nearStatus != 1){
  923. nearStatus=1;
  924. getNearInfo();
  925. }
  926. ticketDeVote(TICKET_PT_NEAR);
  927. }
  928. }
  929. PT_THREAD (ptNearTask(pt_timer_t *ptPool, struct pt *pt)){
  930. static pt_timer_t ptTimer;
  931. PT_BEGIN(pt);
  932. while(1){
  933. isNearIdle();
  934. PTTimerStart(ptPool, &ptTimer,100);
  935. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  936. }
  937. PT_END(pt);
  938. }
  939. /*获取near下次采样时间
  940. 用于投票使用
  941. */
  942. int getNearCnt(void){
  943. int leftTime;
  944. leftTime=getBaseSeconds()%app.nearSampleTime;
  945. if(leftTime==0) return NO_SLEEP_TIME;
  946. else return (app.nearSampleTime-leftTime);
  947. }