GPS.cpp
上传用户:wty58716
上传日期:2022-06-16
资源大小:3084k
文件大小:11k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*-----------------------------------------
  2. * Copyright (c) 2008 Eric Wong
  3. * 本版紧供读者参考,不得用于任何商业行为
  4. *
  5. * 文件名称: GPS.h
  6. * 文件标识: 
  7. * 摘要:用于封装GPS通讯协议
  8. *
  9. * 当前版本: 1.0
  10. * 作者: 汪兵 Eric Wong
  11. * 完成日期: 2008年1月29日
  12. *
  13. * 取代版本:
  14. * 原作者: 
  15. * 完成日期: 
  16. ----------------------------------------*/
  17. #include "StdAfx.h"
  18. #include "GPS.h"
  19. //构造函数
  20. CGPS::CGPS()
  21. {
  22. m_gpsDev_State = GPS_DEV_NOTOPENED; //GPS状态
  23. m_hGpsThread = NULL; //GPS检测线程句柄
  24. ZeroMemory(&m_gpsCurData,sizeof(m_gpsCurData));  //GPS当前数据
  25.   ZeroMemory(&m_gpsLastData,sizeof(m_gpsLastData)); //GPS上一次数据
  26. }
  27. //析构函数
  28. CGPS::~CGPS(void)
  29. {
  30. }
  31. /*
  32. *函数介绍:打开GPS设备
  33. *入口参数:pWnd :使用此GPS类的窗体句柄
  34.    portNo :串口号
  35.    baud :波特率
  36.    parity :奇偶校验
  37.    databits :数据位
  38.    stopbits :停止位
  39. *出口参数:(无)
  40. *返回值:TRUE:成功打开GPS设备;FALSE:打开GPS设备失败
  41. */
  42. BOOL CGPS::Open(CWnd *pWnd , /*拥有者窗口句柄*/
  43. UINT portNo, /*串口号*/
  44. UINT baud, /*波特率*/
  45. UINT parity, /*奇偶校验*/
  46. UINT databits, /*数据位*/
  47. UINT stopbits    /*停止位*/
  48. )
  49. {
  50. m_pWnd = pWnd;  //储存窗口句柄
  51. //创建GPS检测线程退出事件
  52. m_hThreadQuitEvent = CreateEvent(NULL,false,false,L"EVENT_GPS_THREAD");
  53. //指定串口读回调函数
  54. m_ceSeries.m_OnSeriesRead = GpsOnSeriesRead;
  55. //打开GPS设备串口
  56. BOOL bResult = m_ceSeries.OpenPort(this,portNo,baud,parity,databits,stopbits);
  57. if (bResult)
  58. {
  59. //设置当前GPS状态
  60. m_gpsDev_State = GPS_DEV_OPENED;
  61. //发送GPS状态变化消息
  62. ::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_OPENED),1);
  63. //创建GPS状态检测线程
  64. m_hGpsThread = CreateThread(NULL,0,GpsCheckThreadFunc,this,0,&m_dwGpsThreadID);
  65. }
  66. else
  67. {
  68. //设置当前GPS状态
  69. m_gpsDev_State = GPS_DEV_NOTOPENED;
  70. //发送GPS状态变化消息
  71. ::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_NOTOPENED),1);
  72. }
  73. return bResult;
  74. }
  75. /*
  76. *函数介绍:关闭GPS设备
  77. *入口参数:(无)
  78. *出口参数:(无)
  79. *返回值:TRUE:成功关闭GPS设备;FALSE:关闭GPS设备失败
  80. */
  81. void CGPS::Close()
  82. {
  83. //先退出GPS检测线程
  84. if (m_hGpsThread != NULL)
  85. {
  86. //发送线程退出信号
  87. SetEvent(m_hThreadQuitEvent);
  88. //等待线程退出
  89. if (WaitForSingleObject(m_hGpsThread,1000) == WAIT_TIMEOUT)
  90. {
  91. TerminateThread(m_hGpsThread,0);
  92. }
  93. }
  94. m_hGpsThread = NULL;
  95. CloseHandle(m_hThreadQuitEvent);
  96. //将接收数据回掉函数置空
  97. m_ceSeries.m_OnSeriesRead = NULL;
  98. //关闭GPS串口
  99. m_ceSeries.ClosePort();
  100. //设置GPS状态
  101. m_gpsDev_State = GPS_DEV_NOTOPENED;
  102. //发送GPS状态变化消息
  103. ::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_DEV_NOTOPENED),1);
  104. }
  105. /*
  106. *函数介绍:获取GPS设备状态
  107. *入口参数:(无)
  108. *出口参数:(无)
  109. *返回值:返回GPS设备状态
  110. */
  111. GPSDEV_STATE CGPS::GetGpsState()
  112. {
  113. return m_gpsDev_State;
  114. }
  115. /*
  116. *函数介绍:得到当前GPS数据
  117. *入口参数:(无)
  118. *出口参数:(无)
  119. *返回值:返回GPS设备当前GPS数据
  120. */
  121. GPSData CGPS::GetCurGpsData()
  122. {
  123. return m_gpsCurData;
  124. }
  125. /*--------------------------------------------------------------------
  126. 【函数介绍】: 在pArray缓冲区,查找subString字符串,如存在,返回当前位置,否则返回-1
  127. 【入口参数】: pArray:指定接收到的缓冲区队列
  128. 【出口参数】: pArray:指定接收到的缓冲区队列,解析后需要进行适当修改
  129. 【返回  值】: -1表示没有找到指定的子串,>=0表示发现第1个子串的位置
  130. ---------------------------------------------------------------------*/
  131. int CGPS::Pos(LPCSTR subString , CByteArray * pArray,int iPos)
  132. {
  133. //得到子串长度
  134. int subLen = strlen(subString);
  135. //得到缓冲区的长度
  136. int bufLen = pArray->GetUpperBound()+1;
  137. bool aResult = TRUE;
  138. //
  139. for ( int i=iPos;i<bufLen-subLen+1;i++)
  140. {
  141. aResult = TRUE;
  142. for (int j=0;j<subLen;j++)
  143. {
  144. if (pArray->GetAt(i+j) != *(subString + j))
  145. {
  146. aResult = FALSE;
  147. break;
  148. }
  149. int k = 0;
  150. }
  151. if (aResult)
  152. {
  153. return i;
  154. }
  155. }
  156. return -1;
  157. }
  158. /*
  159. *函数介绍:判断是否存在有效GPS数据
  160. *入口参数:aRecvStr :缓冲数据
  161. *出口参数:aRecvStr : 缓冲数据,outStr:得到的一个完整的GPS数据
  162. *返回值:TRUE : 成功初始化 , FALSE : 初始化失败
  163. */
  164. BOOL CGPS::HaveValidGPSData(CByteArray * pArray,CString &outStr)
  165. {
  166. int tmpPos1,tmpPos2;
  167. tmpPos1 = Pos("$GPRMC",pArray,0);
  168. tmpPos2 = Pos("$GPRMC",pArray,tmpPos1+6);
  169. if (tmpPos2 >= 0)  //代表已包含两个$GPRMC
  170. {   
  171. if (tmpPos1 >= 0 )
  172. {
  173. BYTE *pBuf = pArray->GetData();
  174. char *sBuf = new char[tmpPos2-tmpPos1+1];
  175. ZeroMemory(sBuf,tmpPos2-tmpPos1+1);
  176. CopyMemory(sBuf,pBuf+tmpPos1,tmpPos2-tmpPos1+1);
  177. outStr = CString(sBuf);
  178. //释放内存
  179. delete[] sBuf;
  180. sBuf = NULL;
  181. pArray->RemoveAt(0,tmpPos2);
  182. return TRUE;
  183. }
  184. }
  185. return FALSE;
  186. }
  187. /*
  188. *函数介绍:解析GPS数据
  189. *入口参数:aRecvStr :指待解析的GPS缓冲数据
  190. *出口参数:(无)
  191. *返回值:指CGPSData结构体的指针,如果无效即为:NULL;
  192. */
  193. PGPSData CGPS::AnalyseGpsData(CString &aRecvStr)
  194. {
  195. CString tmpTime;
  196. CString tmpState;
  197. CString tmpDate;
  198. CString tmpLONG;
  199. CString tmpLONGType;
  200. CString tmpLAT;
  201. CString tmpLATType;
  202. CString tmpSpeed;
  203. LPSTR pStrDate = NULL;
  204. LPSTR pStrTime = NULL;
  205. LPSTR pStrLong = NULL;
  206. LPSTR pStrLongType = NULL;
  207. LPSTR pStrLat = NULL;
  208. LPSTR pStrLatType = NULL;
  209. LPSTR pStrSpeed = NULL;
  210. PGPSData pGpsData = NULL;
  211. int tmpPos,tmpPos1;
  212. int len;
  213. tmpPos = aRecvStr.Find(',',0); //第1个值
  214. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  215. //得到时间
  216. tmpTime = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  217. tmpTime = tmpTime.Mid(0,2)+L":"+tmpTime.Mid(2,2)+L":"+tmpTime.Mid(4,2);
  218. len = tmpTime.GetLength();
  219. pStrTime = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  220. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpTime.GetBuffer(len),len
  221. ,pStrTime,len ,NULL,NULL);
  222. //数据状态,是否有效
  223. tmpPos = aRecvStr.Find(',',tmpPos+1);  //第2个值
  224. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  225. tmpState = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  226. if (tmpState != 'A')//代表数据无效,返回
  227. {
  228. if (m_gpsDev_State != GPS_INVALID_DATA)
  229. {
  230. //设置GPS状态
  231. m_gpsDev_State = GPS_INVALID_DATA;
  232. //发送GPS状态变化消息
  233. ::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_INVALID_DATA),1);
  234. }
  235. LocalFree(pStrTime);
  236. return NULL;
  237. }
  238. else  //代表数据有效
  239. {
  240. if (m_gpsDev_State != GPS_VALID_DATA)
  241. {
  242. //设置GPS状态
  243. m_gpsDev_State = GPS_VALID_DATA;
  244. //发送GPS状态变化消息
  245. ::PostMessage(m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_VALID_DATA),1);
  246. }
  247. }
  248. //得到纬度值
  249. tmpPos = aRecvStr.Find(',',tmpPos+1);//第3个值
  250. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  251. tmpLAT = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  252. len = tmpLAT.GetLength();
  253. pStrLat = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  254. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLAT.GetBuffer(len),len
  255. ,pStrLat,len ,NULL,NULL);
  256. tmpPos = aRecvStr.Find(',',tmpPos+1);//第4个值
  257. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  258. tmpLATType = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  259. len = tmpLATType.GetLength();
  260. pStrLatType = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  261. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLATType.GetBuffer(len),len
  262. ,pStrLatType,len ,NULL,NULL);
  263. //得到经度值
  264. tmpPos = aRecvStr.Find(',',tmpPos+1);//第5个值
  265. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  266. tmpLONG = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  267. len = tmpLONG.GetLength();
  268. pStrLong = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  269. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLONG.GetBuffer(len),len
  270. ,pStrLong,len ,NULL,NULL);
  271. tmpPos = aRecvStr.Find(',',tmpPos+1);//第6个值
  272. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  273. tmpLONGType = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  274. len = tmpLONGType.GetLength();
  275. pStrLongType = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  276. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpLONGType.GetBuffer(len),len
  277. ,pStrLongType,len ,NULL,NULL);
  278. //得到车速
  279. tmpPos = aRecvStr.Find(',',tmpPos+1);////第7个值
  280. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  281. tmpSpeed = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  282. len = tmpSpeed.GetLength();
  283. pStrSpeed = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  284. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpSpeed.GetBuffer(len),len
  285. ,pStrSpeed,len ,NULL,NULL);
  286. tmpPos = aRecvStr.Find(',',tmpPos+1);////第8个值
  287. //得到日期
  288. tmpPos = aRecvStr.Find(',',tmpPos+1);////第9个值
  289. tmpPos1 = aRecvStr.Find(',',tmpPos+1);
  290. //格式化一下
  291. tmpDate = aRecvStr.Mid(tmpPos+1,tmpPos1-tmpPos-1);
  292. tmpDate = L"20"+tmpDate.Mid(4,2)+L"-"+tmpDate.Mid(2,2)+L"-"+tmpDate.Mid(0,2);
  293. len = tmpDate.GetLength();
  294. pStrDate = LPSTR(LocalAlloc(LMEM_ZEROINIT,len));
  295. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,tmpDate.GetBuffer(len),len
  296. ,pStrDate,len ,NULL,NULL); 
  297. pGpsData = new GPSData();
  298. ZeroMemory(pGpsData,sizeof(GPSData));
  299. //得到GPS数据指针
  300. CopyMemory(pGpsData->date,pStrDate,10);
  301. CopyMemory(pGpsData->time,pStrTime,8);
  302. CopyMemory(pGpsData->latitude_type,pStrLatType,1);
  303. CopyMemory(pGpsData->latitude,pStrLat,9);
  304. CopyMemory(pGpsData->longitude_type,pStrLongType,1);
  305. CopyMemory(pGpsData->longitude,pStrLong,10);
  306. //先置默认速度0
  307. FillMemory(pGpsData->speed,5,'0');
  308. CopyMemory(pGpsData->speed,pStrSpeed,5);
  309. //释放内存
  310. LocalFree(pStrTime);
  311. LocalFree(pStrDate);
  312. LocalFree(pStrLatType);
  313. LocalFree(pStrLat);
  314. LocalFree(pStrLongType);
  315. LocalFree(pStrLong);
  316. LocalFree(pStrSpeed);
  317. return pGpsData;
  318. }
  319. //GPS接收数据事件
  320. void CALLBACK CGPS::GpsOnSeriesRead(void * powner,BYTE* buf,DWORD  dwBufLen)
  321. {
  322. CGPS * pGps = (CGPS*)powner;
  323. //得到本类指针
  324. CByteArray * pArray = &(pGps->m_aRecvBuf);
  325. //得到缓冲区大小
  326. int iMaxSize = pArray->GetSize();
  327. //得到缓冲区所使用的大小
  328. int iUpperBound = pArray->GetUpperBound();
  329. for (int i=0;i<dwBufLen;i++)
  330. {
  331. pArray->Add(*(buf+i));
  332. }
  333. //将收到的数据发给主程序显示出来
  334. char* pRecvBuf = new char[dwBufLen+1];
  335. ZeroMemory(pRecvBuf,dwBufLen+1);
  336. CopyMemory(pRecvBuf,buf,dwBufLen);
  337. //发送接收串口原始数据WINDOWS消息通知
  338. //消息处理完毕后,应释放内存
  339. ::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_RECV_BUF,WPARAM(pRecvBuf),dwBufLen+1);
  340. CString strGps;
  341. //检查是否已经存在有效的GPS数据
  342. if (pGps->HaveValidGPSData(pArray,strGps))
  343. {
  344. PGPSData pGpsData = NULL;
  345. pGpsData = pGps->AnalyseGpsData(strGps);
  346. if (pGpsData != NULL) 
  347. {
  348. //将接收到的GPS数据填充到最新当前数据
  349. pGps->m_gpsCurData = (*pGpsData);
  350. //发送接收有效GPS位置信息WINDOWS消息通知
  351. //由消息处理函数释放内存
  352. ::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_RECV_VALID_LONGLAT,WPARAM(pGpsData),0);
  353. }
  354. }
  355. }
  356. //检测GPS当前数据
  357. DWORD WINAPI CGPS::GpsCheckThreadFunc(LPVOID lparam)
  358. {
  359. //得到当前GPS指针
  360. CGPS *pGps = (CGPS*)lparam;
  361. int iRecCount = 0;
  362. //然后开始做循环检测,间隔为1秒
  363. while (TRUE)
  364. {
  365. //判断两次收到的时间是否相同
  366. if (strcmp(pGps->m_gpsCurData.time,pGps->m_gpsLastData.time) == 0)
  367. {
  368. //计数加1
  369. iRecCount++;
  370. }
  371. else
  372. {
  373. //将当前的GPS数据赋给历史值
  374. pGps->m_gpsLastData = pGps->m_gpsCurData;
  375. iRecCount = 0 ;
  376. }
  377. //代表连续三次没有收到数据
  378. if (iRecCount == 3)
  379. {
  380. if (pGps->m_gpsDev_State != GPS_NODATA)
  381. {
  382. //将GPS状态置为“无数据”
  383. pGps->m_gpsDev_State = GPS_NODATA;
  384. //发送GPS状态改变消息
  385. ::PostMessage(pGps->m_pWnd->m_hWnd,WM_GPS_STATE_CHANGE_MESSAGE,WPARAM(GPS_NODATA),1);
  386. }
  387. }
  388. //延时1秒
  389. for (int i =0; i<10;i++)
  390. {
  391. //线程退出
  392. if (WaitForSingleObject(pGps->m_hThreadQuitEvent,100) == WAIT_OBJECT_0)
  393. {
  394. goto finish;
  395. }
  396. }
  397. }
  398. finish:
  399. TRACE(L"GPS 检测线程退出n");
  400. return 0;
  401. }