GPS.cpp
上传用户:zhqmouse
上传日期:2022-05-26
资源大小:47k
文件大小:11k
源码类别:

GPS编程

开发平台:

Visual C++

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