发 帖  
原厂入驻New

STM32开发GPRS传输的GPS定位器 C#编写服务器转发程序,客户端显示轨迹

2019-12-22 15:48:48  556 stm32 GPRS gps
分享
4
本帖最后由 gandonggandong 于 2019-12-24 08:21 编辑

GPS定位发展很快,随着物联网的推广,衍生出很多GPS相关的应用万变不离其宗,主要应用的技术是GPS信号的采集、解析、将GPS信号通过4G或GPRS等传至服务器,客户端与服务器通信,获取设备位置信息,实现定位轨迹跟踪等。大概都包含这三大部分,设备、服务器后台、客户端。
设备如下

C#编写服务器后台

C#客户端

下面逐个介绍
设备采用STM32串口接收GPS模块输出的位置信息,解析出经纬度,通过AT指令控制GPRS模块与服务器通信。硬件电路如下

单片机解析GPS模块的位置信息,一般解析GPRMC这一条就可以,解析的方法很多,可以用找字头,数逗号的方式例如下面的信息。
$GPRMC,092927.000,A,2235.9058,N,11400.0518,E,0.000,74.11,151216,,D*49
$GPVTG,74.11,T,,M,0.000,N,0.000,K,D*0B
$GPGGA,092927.000,2235.9058,N,11400.0518,E,2,9,1.03,53.1,M,-2.4,M,0.0,0*6B
$GPGSA,A,3,29,18,12,25,10,193,32,14,31,,,,1.34,1.03,0.85*31
$GPGSV,3,1,12,10,77,192,17,25,59,077,42,32,51,359,39,193,49,157,36*48
$GPGSV,3,2,12,31,47,274,25,50,46,122,37,18,45,158,37,14,36,326,18*70
$GPGSV,3,3,12,12,24,045,45,26,17,200,18,29,07,128,38,21,02,174,*79


  1. char *gpsdata;
  2.         int i,count;
  3.         IF(USART_GetiTStatus(USART2,USART_IT_IDLE) == SET)     
  4.         {                                                
  5.                 USART2->SR;        
  6.                 USART2->DR;
  7.                 USART_ClearITPendingBit(USART2,USART_IT_IDLE);
  8.                 DMA_Cmd(DMA1_Channel6,DISABLE);                      //??DMA        
  9.                 U2_Rx_Counter = 1024 - DMA_GetCurrDataCounter(DMA1_Channel6);  //??????????                          
  10.                 gpsdata = strstr(U2_RX_data,"$GNRMC");
  11.                 if(gpsdata)        
  12.                 {
  13.                         for(i=0;i<strlen(gpsdata);i++)
  14.                         {
  15.                                 if(gpsdata[i]==',')
  16.                                 {
  17.                                         count++;
  18.                                         if(count==2)
  19.                                         {
  20.                                                         
  21.                                                         if(gpsdata[i+1]=='A')
  22.                                                         {
  23.                                                                 gps_flag=1;
  24.                                                                
  25.                                                         }
  26.                                                         else
  27.                                                         {
  28.                                                                 gps_n=0;
  29.                                                                 gps_e=0;
  30.                                                                 break;
  31.                                                         }
  32.                                         }        
  33.                                         if(gps_flag==1)
  34.                                         {
  35.                                                 if((count==3)&&(gpsdata[i+1]!=','))
  36.                                                 {
  37.                                                         gps_n=((gpsdata[i+1]-0x30)*100000+(gpsdata[i+2]-0x30)*10000+((gpsdata[i+3]-0x30)*100000+(gpsdata[i+4]-0x30)*10000+(gpsdata[i+6]-0x30)*1000+(gpsdata[i+7]-0x30)*100+(gpsdata[i+8]-0x30)*10+(gpsdata[i+9]-0x30))/60);
  38.                                                 }
  39.                                                 if((count==5)&&(gpsdata[i+1]!=','))
  40.                                                 {
  41.                                                         gps_e=((gpsdata[i+1]-0x30)*1000000+(gpsdata[i+2]-0x30)*100000+(gpsdata[i+3]-0x30)*10000+((gpsdata[i+4]-0x30)*100000+(gpsdata[i+5]-0x30)*10000+(gpsdata[i+7]-0x30)*1000+(gpsdata[i+8]-0x30)*100+(gpsdata[i+9]-0x30)*10+(gpsdata[i+10]-0x30))/60);                        
  42.                                                 }               
  43.                                                 if(count>=13)
  44.                                                 {
  45.                                                         count=0;
  46.                                                         gps_flag=0;
  47.                                                         break;
  48.                                                 }
  49.                                         }        
  50.                                 }        
  51.                         }
  52.                 }
  53.                 memset(U2_RX_data,0, 1024);               
  54.                 DMA1_Channel6->CNDTR = 1024;                            //??????????           
  55.                 DMA_Cmd(DMA1_Channel6,ENABLE);                       //??DMA            
  56.         }
复制代码

单片机与服务器通过AT指令控制GPRS模块与服务器通信,AT指令是比较难的,开发过的会有感受,AT指令返回的状态比较多,并不是返回一种或两种结果。不但要按照正常流程一步一步发送AT指令,还要有错误返回处理。AT指令挺复杂的,特别适合用状态机处理这些流程。
  1. switch (M26_info.state)            
  2.         {
  3.                 case GPRS_state_Poweroff :
  4.                                 if(AT_Delay_Timer>5)
  5.                                 {
  6.                                         GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);
  7.                                         GPIO_SetBits(GPIOA,GPIO_Pin_1);
  8.                                         GPIO_ResetBits(GPIOA, GPIO_Pin_7);
  9.                                         GPIO_ResetBits(GPIOA, GPIO_Pin_4);             // Sleep
  10.                                 }
  11.                                 if(AT_Delay_Timer>25)
  12.                                 {
  13.                                         GPIO_ResetBits(GPIOA,GPIO_Pin_1);
  14.                                         GPIO_SetBits(GPIOA, GPIO_Pin_7);
  15.                                 }                                
  16.                                 if(AT_Delay_Timer>45)
  17.                                 {
  18.                                         GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);
  19.                                         M26_info.state=GPRS_state_AT;
  20.                                         AT_Timeslimite=0;
  21.                                         AT_Delay_Timer=0;
  22.                                         AT_overtime=0;
  23.                                         ZC_DATA_flog=1;
  24.                                 }               
  25.                         break;
  26.                 case GPRS_state_AT :
  27.                                 M26_ATTR(5,30,50,"AT+IPR=115200&W\r\n","OK","","","","",GPRS_state_CREG,GPRS_state_AT);
  28.                         break;
  29.                 case GPRS_state_CREG :
  30.                                 M26_ATTR(5,30,100,"AT+CREG?\r\n","+CREG: 0,1","+CREG: 0,5","+CREG: 0,2","+CREG: 0,3","+CREG: 0,4",GPRS_state_CSQ,GPRS_state_CREG);
  31.                         break;
  32.                 case GPRS_state_CSQ :
  33.                                 M26_ATTR(2,30,20,"AT+CSQ\r\n","+CSQ:","","","","",GPRS_state_QIDNSIP,GPRS_state_CSQ);
  34.                 case GPRS_state_QIDNSIP:
  35.                                 M26_ATTR(2,30,5,"AT+QIFGCNT=0\r\n","OK","","","","",GPRS_state_QIDEACT,GPRS_state_Poweroff);
  36.                         break;
  37.                 case GPRS_state_QIDEACT:
  38.                                 M26_ATTR(2,2,50,"AT+QICSGP=1,\"CMMTM\"\r\n","OK","","ERROR","","",GPRS_state_QIREGAPP,GPRS_state_Poweroff);
  39.                                 break;
  40.                 case GPRS_state_QIREGAPP:
  41.                                 M26_ATTR(2,2,50,"AT+QIREGAPP\r\n","OK","","ERROR","","",GPRS_state_QIACT,GPRS_state_Poweroff);
  42.                         break;
  43.                 case GPRS_state_QIACT:
  44.                                 M26_ATTR(10,2,300,"AT+QIACT\r\n","OK","","ERROR","","",GPRS_state_QIOPEN,GPRS_state_Poweroff);
  45.                         break;
  46.                 case GPRS_state_QIOPEN:
  47.                                 M26_ATTR(20,10,50,"AT+QIOPEN=\"TCP\",\"122.51.33.246\",\"8888\"\r\n","CONNECT OK","ALREADY CONNECT","ERROR","CONNECT FAIL","",GPRS_state_QISEND,GPRS_state_QIACT);
  48.                         break;
  49.                 case GPRS_state_QISTAT:
  50.                                 M26_ATTR(10,10,500,"AT+QISTAT\r\n","STATE: CONNECT OK","","STATE: IP INITIAL","","",GPRS_state_QISEND,GPRS_state_QIOPEN);
  51.                         break;
  52.                 case GPRS_state_QISEND:
  53.                                 ////GPRS_DATA_flog=1;
  54.                                 M26_ATTR(50,20,100,"AT+QISEND=27\r\n",">",">","ERROR","ERROR","ERROR",GPRS_state_QISENDDATA,GPRS_state_QISENDDATA);
  55.                         break;
  56.                 case GPRS_state_QISENDDATA:
  57.                                 M26_senddata(10,10,100,"12345678","SEND OK","","ERROR","ERROR","ERROR",GPRS_state_QISEND,GPRS_state_Poweroff);
  58.                         break;
  59.                
  60.                 default:  ;
  61.         }
复制代码

服务器后台
用C#编写服务器后台程序,他负责接收所有设备发来数据,把与客户端有关的设备数据转发给客户端。这样局域网里的客户端可以通过网关获取服务器的数据。服务器程序用到多线程技术,可以同时处理多个设备发来的数据。用到了Dictionary数据类型,实现设备ID与socket对应,关键代码如下
  1. private void ReceiveClient(object obj)
  2.         {
  3.             Socket _ClientSocket = (Socket)obj;
  4.             while (true)
  5.             {
  6.                 try
  7.                 {
  8.                     byte[] result = new byte[1024];
  9.                     int receiveLength = _ClientSocket.Receive(result);            
  10.                     string clientMessage = Encoding.UTF8.GetString(result, 0, receiveLength);
  11.                     string Destination_Address;
  12.                     string Data_Rcve;
  13.                     if (receiveLength == 0)
  14.                     {
  15.                         ClientSocketDictionary.Remove(_ClientSocket);
  16.                         _ClientSocket.Shutdown(SocketShutdown.Both);
  17.                         _ClientSocket.Close();
  18.                         SetText2box();
  19.                         break;
  20.                     }
  21.                     else
  22.                     {
  23.                         if ((result[0] == '
  24. 客户端
  25. C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下
  26. [code]private void button1_Click(object sender, EventArgs e)
  27.         {
  28.             try
  29.             {
  30.                 clientScoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  31.                 clientScoket.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text.ToString()), 8888));
  32.                 t = new Thread(ReceiveMessage);//开启线程执行循环接收消息
  33.                 t.IsBackground=true;
  34.                 t.Start();
  35.                 button1.Text = "已连接服务器";
  36.                 button1.EnabLED = false;
  37.             }
  38.             catch (Exception ex)
  39.             {
  40.                 SetText3box(ex);
  41.                 button1.Text = "无法连接服务器";
  42.                 button1.Enabled = true;
  43.             }
  44.                   
  45.         }
  46.       
  47.         public delegate void CallSetTextbox(string ms);
  48.         void ReceiveMessage()//接收消息
  49.         {
  50.             
  51.             string Destination_Address;
  52.             string Data_Rcve;
  53.             send_flog = 1;
  54.             while (true)
  55.             {
  56.                 if (clientScoket.Connected == true)
  57.                 {
  58.                     
  59.                     
  60.                         if (send_flog == 1)
  61.                         {
  62.                             send_flog = 0;
  63.                             message = "$1" + textBox4.Text;
  64.                             SendMessage(message);
  65.                         }
  66.                         int length = 0;

  67.                         try
  68.                         {
  69.                             length = clientScoket.Receive(data);
  70.                          }
  71.                         catch (Exception e)
  72.                         {
  73.                             SetText3box(e);
  74.                        
  75.                         break;

  76.                         }

  77.                         if (length != 0)
  78.                         {
  79.                             message = Encoding.UTF8.GetString(data, 0, length);
  80.                             if ((data[0] == '

  81. ) && (result[1] == '2'))//发送数据 目的地址
  82.                         {
  83.                             Destination_Address = clientMessage.Substring(2, 10);
  84.                             Data_Rcve = clientMessage.Substring(12, clientMessage.Length-12);
  85.                             temp = DateTime.Now.ToString()+ " Dest is : " + Destination_Address + "  Data is : " + Data_Rcve;
  86.                             SetTextbox();
  87.                             SendMessage(clientMessage);
  88.                         }
  89.                         if ((result[0] == '
  90. 客户端
  91. C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下
  92. [        DISCUZ_CODE_52        ]

  93. ) && (result[1] == '1'))//注册ID  源地址
  94.                         {
  95.                             if (!ClientSocketDictionary.ContainsKey(_ClientSocket))
  96.                             {
  97.                                 ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10));
  98.                                 SetText2box();
  99.                             }
  100.                             else
  101.                             {
  102.                                 ClientSocketDictionary.Remove(_ClientSocket);
  103.                                 ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10));
  104.                                 SetText2box();
  105.                             }                                       
  106.                         }
  107.                     }
  108.                                                       
  109.                 }
  110.                 catch (Exception e)
  111.                 {
  112.                     ClientSocketDictionary.Remove(_ClientSocket);
  113.                     _ClientSocket.Shutdown(SocketShutdown.Both);
  114.                     _ClientSocket.Close();
  115.                     SetText2box();
  116.                     SetText3box(e);

  117.                     break;
  118.                 }
  119.             }
  120.         }
  121. public void SendMessage(string msg)
  122.         {
  123.             if (msg == string.Empty || this.ClientSocketDictionary.Count <= 0) return;
  124.             string Destination_Address = msg.Substring(2, 10);
  125.             string Data_Rcve = msg.Substring(12, msg.Length-12);
  126.             msg = "$3" + Destination_Address + Data_Rcve;

  127.             
  128.             try
  129.             {
  130.                 foreach (KeyValuePair<Socket, string> kvp in ClientSocketDictionary)
  131.                 {
  132.                    if(kvp.Value.Substring(0,10)== Destination_Address)
  133.                    {
  134.                        kvp.Key.Send(Encoding.UTF8.GetBytes(msg));
  135.                    }              
  136.                 }
  137.             }
  138.             catch (Exception e)
  139.             {
  140.                 SetText3box(e);
  141.             }
  142.         }      
复制代码

客户端
C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下
  1. private void button1_Click(object sender, EventArgs e)
  2.         {
  3.             try
  4.             {
  5.                 clientScoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  6.                 clientScoket.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text.ToString()), 8888));
  7.                 t = new Thread(ReceiveMessage);//开启线程执行循环接收消息
  8.                 t.IsBackground=true;
  9.                 t.Start();
  10.                 button1.Text = "已连接服务器";
  11.                 button1.Enabled = false;
  12.             }
  13.             catch (Exception ex)
  14.             {
  15.                 SetText3box(ex);
  16.                 button1.Text = "无法连接服务器";
  17.                 button1.Enabled = true;
  18.             }
  19.                   
  20.         }
  21.       
  22.         public delegate void CallSetTextbox(string ms);
  23.         void ReceiveMessage()//接收消息
  24.         {
  25.             
  26.             string Destination_Address;
  27.             string Data_Rcve;
  28.             send_flog = 1;
  29.             while (true)
  30.             {
  31.                 if (clientScoket.Connected == true)
  32.                 {
  33.                     
  34.                     
  35.                         if (send_flog == 1)
  36.                         {
  37.                             send_flog = 0;
  38.                             message = "$1" + textBox4.Text;
  39.                             SendMessage(message);
  40.                         }
  41.                         int length = 0;

  42.                         try
  43.                         {
  44.                             length = clientScoket.Receive(data);
  45.                          }
  46.                         catch (Exception e)
  47.                         {
  48.                             SetText3box(e);
  49.                        
  50.                         break;

  51.                         }

  52.                         if (length != 0)
  53.                         {
  54.                             message = Encoding.UTF8.GetString(data, 0, length);
  55.                             if ((data[0] == '

  56. ) && (data[1] == '3'))//配置ID
  57.                             {
  58.                                 Destination_Address = message.Substring(2, 10);
  59.                                 Data_Rcve = message.Substring(12, message.Length - 12);

  60.                                 Longitude = Data_Rcve.Substring(0, 8);
  61.                                 Latitude = Data_Rcve.Substring(8, 7);
  62.                                 if ((Longitude != "000.0000") && (Latitude != "00.0000"))
  63.                                 {
  64.                                     SetTextbox(DateTime.Now.ToString() + " Dest is : " + Destination_Address + "  Data is : " + Data_Rcve);
  65.                                 }
  66.                                 SetText2box(DateTime.Now.ToString() + " Dest is : " + Destination_Address + "  Data is : " + Data_Rcve);

  67.                         }
  68.                         }
  69.                  
  70.                     
  71.                 }
  72.                 else
  73.                 {
  74.                     break;
  75.                 }
  76.             }
复制代码

相关经验

gandonggandong 2020-1-11 21:40:05
前面文章介绍如何开发定位器硬件,单片机软件,服务器软件,上位机客户端软件,下面介绍如何使用android studio开发客户端APP显示轨迹。

能自己做的事从来不求人,前面用C#实现了PC端显示定位数据轨迹,用android studio开发客户端APP显示轨迹的流程也是大同小异的,只是开发语言的不同,安卓应用程序是使用Java开发的,但是C#和Java很相似。

用android studio开发客户端APP显示轨迹大概分这么几个步骤,1,编写xml文件,2,TCP服务器通信部分,3,调用百度地图API实现轨迹绘制。
1,XML布局文件加入百度地图mapview,和两个文本框,代码及UI界面如下
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     xmlns:app="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools"
  6.     android:layout_width="match_parent"
  7.     android:layout_height="match_parent"
  8.     android:paddingBottom="@dimen/activity_vertical_margin"
  9.     android:paddingLeft="@dimen/activity_horizontal_margin"
  10.     android:paddingRight="@dimen/activity_horizontal_margin"
  11.     android:paddingTop="@dimen/activity_vertical_margin"

  12.     tools:context="com.example.myapplication.MainActivity">

  13.     <com.baidu.mapapi.map.MapView
  14.         android:id="@+id/bmapview"
  15.         android:layout_width="match_parent"
  16.         android:layout_height="400dp"
  17.         android:clickable="true" />
  18.     <TextView
  19.     android:id="@+id/Text2view"
  20.     android:layout_width="match_parent"
  21.     android:layout_height="20dp"
  22.     android:text="---"
  23.     android:layout_below="@id/bmapview"/>
  24.     <TextView
  25.         android:id="@+id/Textview"
  26.         android:layout_width="match_parent"
  27.         android:layout_height="90dp"
  28.         android:text="---"
  29.         android:layout_below="@id/Text2view"/>
  30. </RelativeLayout>
复制代码
​​
2,编写TCP与服务器通信程序
这部分主要有三个线程组成,一个用于连接服务器,一个向服务器发送数据,一个接收服务器的数据。
连接服务器线程,这里要实时检查安卓客户端与服务器的连接是否有效,做断线重连,并且开启发送数据线程和接收数据线程,程序如下


  1. private class connectToServer extends Thread{
  2.         @Override
  3.         public void run() {
  4.             while(true)
  5.             {
  6.                 try
  7.                 {
  8.                     //客户端向服务器发送连接请求
  9.                     //c_Socket = new Socket("---.---.---.---",8888);
  10.                     if (c_Socket==null)
  11.                     {
  12.                         c_Socket = new Socket("---.---.---.---",8888);
  13.                         if (c_Socket.isConnected())
  14.                         {
  15.                             TCP_R_Count=0;
  16.                             int port = c_Socket.getLocalPort();
  17.                             Message msg = new Message();
  18.                             msg.what = 5;
  19.                             msg.obj = String.valueOf(port);
  20.                             mHandler.sendMessage(msg);
  21.                             c_readflag = true;
  22.                             new c_ReadThread().start();
  23.                             new SenfToServer().start();
  24.                             connect=true;
  25.                         }

  26.                     }
  27.                     if(connect==false)
  28.                     {
  29.                         if(c_Socket!=null){
  30.                             c_Socket.close();
  31.                             c_Socket=null;
  32.                         }

  33.                     }

  34.                     //c_Socket = new Socket("192.168.5.32",8888);
  35.                     //c_Socket.connect(IPAddress.Parse(c_ip.getText().toString()), Int32.Parse(c_port.Text));
  36.                 }catch(Exception ee)
  37.                 {
  38.                     ee.printStackTrace();
  39.                 }
  40.             }
  41.             //super.run();
  42.         }

  43.     }
复制代码
发送线程 目前这部分比较简单,随着功能的增加会逐步丰富。
  1. //客户端向服务器发送数据
  2.     private class SenfToServer extends Thread{
  3.         @Override
  4.         public void run() {
  5.             while(true)
  6.             {
  7.                 if(c_Socket!=null){
  8.                     if (c_Socket.isConnected())
  9.                     {
  10.                         try{
  11.                             out = c_Socket.getOutputStream();
  12.                             out.write("----------------".getBytes());
  13.                             out.flush();
  14.                             SenfToServer.sleep(60000);
  15.                         }
  16.                         catch(Exception e){
  17. //                        connect=false;
  18.                         }
  19.                     }
  20.                 }
  21.             }
  22.             //super.run();
  23.         }
  24.     }
复制代码


接收线程
接收线程接收服务器发来的GPS定位数据,通过Handler向主线程传递消息。这里要检测TCP连接的有效性,如果断开连接要重连服务器。

  1. //客户端接收服务器发来的信息
  2.     private class c_ReadThread extends Thread
  3.     {
  4.         @Override
  5.         public void run() {
  6.             // TODO 自动生成的方法存根
  7.             try {
  8.                 InputStream input = c_Socket.getInputStream();
  9.                 while (c_readflag)
  10.                 {
  11.                     byte[] buff = new byte[100];

  12.                     int size = input.read(buff);
  13.                     if((size>12)){
  14.                         if((buff[0]=='3,调用百度地图API实现轨迹绘制
  15. 首先获取xml中加入的地图组件,mMapView = (MapView) findViewById(R.id.bmapview);   
  16. mBaiduMap = mMapView.getMap();设置地图缩放级别mBaiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(new MapStatus.Builder().zoom(21).build()));之后,使用Overlay mPolyline = mBaiduMap.addOverlay(mOverlayOptions);逐段加入两点连线,最终形成上图中的轨迹。更新坐标位置,让最后发来的位置坐标作为地图的中心mBaiduMap.animateMapStatus(u);这里还要注意从GPS卫星接收到的经纬度和百度地图经纬度有偏差,要使用下面方法做纠偏。CoordinateConverter converter1  = new CoordinateConverter().from(CoordinateConverter.CoordType.GPS).coord(p1); LatLng desLatLng1 = converter1.convert();

  17. 关键代码如下
  18. [code]mHandler = new Handler(){
  19.             @Override
  20.             public void handleMessage(Message msg) {
  21.                 if(msg.what ==4){
  22.                     if((latitude_n!=null) &&(longitude_n!=null)&&(latitude_o!=null) &&(longitude_o!=null)){

  23.                         List<LatLng> points = new ArrayList<LatLng>();
  24.                         LatLng p1,p2 ;
  25.                         p1=new LatLng( Double.parseDouble(latitude_n),Double.parseDouble(longitude_n));
  26.                         // sourceLatLng待转换坐标

  27.                         CoordinateConverter converter1  = new CoordinateConverter()
  28.                                 .from(CoordinateConverter.CoordType.GPS)
  29.                                 .coord(p1);
  30.                         LatLng desLatLng1 = converter1.convert();
  31.                         points.add(desLatLng1);

  32.                         Log.i("P1","纬度:"+desLatLng1.latitude+" | 经度:"+desLatLng1.longitude);

  33.                         p2=new LatLng( Double.parseDouble(latitude_o),Double.parseDouble(longitude_o));
  34.                         // sourceLatLng待转换坐标

  35.                         CoordinateConverter converter2  = new CoordinateConverter()
  36.                                 .from(CoordinateConverter.CoordType.GPS)
  37.                                 .coord(p2);
  38.                         LatLng desLatLng2 = converter2.convert();
  39.                         points.add(desLatLng2);

  40.                         Log.i("P2","纬度:"+desLatLng2.latitude+" | 经度:"+desLatLng2.longitude);

  41.                         //设置折线的属性
  42.                         OverlayOptions mOverlayOptions = new PolylineOptions()
  43.                                 .width(10)
  44.                                 .color(0xAAFF0000)
  45.                                 .points(points);
  46.                         Overlay mPolyline = mBaiduMap.addOverlay(mOverlayOptions);
  47.                         //if(((latitude_n.equals(latitude_o))&&(longitude_n.equals(longitude_o))))
  48.                         {

  49.                             //定义Maker坐标点
  50.                             LatLng p3;
  51.                             p3=new LatLng( Double.parseDouble(latitude_n),Double.parseDouble(longitude_n));

  52.                             // sourceLatLng待转换坐标

  53.                             CoordinateConverter converter3  = new CoordinateConverter()
  54.                                     .from(CoordinateConverter.CoordType.GPS)
  55.                                     .coord(p3);
  56.                             LatLng desLatLng3 = converter3.convert();
  57.                             /*
  58.                             //构建Marker图标
  59.                             BitmapDescriptor bitmap = BitmapDescriptorFactory
  60.                                     .fromResource(R.drawable.icon_w);
  61.                             //构建MarkerOption,用于在地图上添加Marker
  62.                             OverlayOptions option = new MarkerOptions()
  63.                                     .position(desLatLng3)
  64.                                     .icon(bitmap);
  65.                             //在地图上添加Marker,并显示
  66.                             mBaiduMap.addOverlay(option);
  67.                             */
  68.                             // 构造定位数据
  69.                             MyLocationData locData = new MyLocationData.Builder()
  70.                                     .accuracy(0)    //设置精度
  71.                                     .direction(0)                 // 此处设置开发者获取到的方向信息,顺时针0-360
  72.                                     .latitude(desLatLng3.latitude)                   // 设置纬度坐标
  73.                                     .longitude(desLatLng3.longitude)    //设置经度坐标
  74.                                     .build();
  75.                             // 设置定位数据
  76.                             mBaiduMap.setMyLocationData(locData);
  77.                             //设置自定义定位图标
  78.                             BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
  79.                                     .fromResource(R.drawable.icon_w);
  80.                             mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;  //设置定位模式
  81.                             //位置构造方式,将定位模式,定义图标添加其中
  82.                             MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
  83.                             mBaiduMap.setMyLocationConfigeration(config);  //地图显示定位图标

  84.                             MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(desLatLng3);  //更新坐标位置
  85.                             mBaiduMap.animateMapStatus(u);                            //设置地图位置
  86.                         }



  87.                         //获取显示LocationProvider名称的TextView组件
  88.                         TextView textView = (TextView) findViewById(R.id.Textview);
  89.                        // StringBuilder stringBuilder = new StringBuilder();  //使用StringBuilder保存数据
  90.                         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
  91.                         Date date = new Date(System.currentTimeMillis());
  92.                         String str=simpleDateFormat.format(date);

  93.                         textView.setText("");
  94.                         textView.append(str + "\n");
  95.                         textView.append(("N纬度:"+desLatLng1.latitude).toString() + "\n");
  96.                         textView.append(("N纬度:"+desLatLng2.latitude).toString() + "\n");
  97.                         textView.append(("O经度:"+desLatLng1.longitude).toString() + "\n");
  98.                         textView.append(("O经度:"+desLatLng2.longitude).toString() + "\n");
  99.                     }
  100.                 }
  101.                 if(msg.what ==5){
  102.                     TextView textView = (TextView) findViewById(R.id.Text2view);
  103.                     textView.setText("receive is  "+Integer.toString(TCP_R_Count));
  104.                 }
  105.                 super.handleMessage(msg);
  106.             }

  107.         };
复制代码



)&&(buff[1]=='3')&&(buff[12]!=0)){
                            Message msg = new Message();
                            msg.what =4;
                            msg.obj = new String(buff,0,size);
                            latitude_o=latitude_n;
                            longitude_o=longitude_n;
                            latitude_n=new String(buff,20,7);
                            longitude_n=new String(buff,12,8);

                            Log.i("n","纬度:"+latitude_n+" | 经度:"+longitude_n);

                            if((latitude_n!="00.0000")&&(longitude_n!="000.0000")){
                                mHandler.sendMessage(msg);
                            }else{
                                latitude_n=null;
                                longitude_n=null;
                            }
                        }
                    }
                    if(size>0)
                    {
                        TCP_R_Count=TCP_R_Count+size;
                        Message msg = new Message();
                        msg.what =5;
                        mHandler.sendMessage(msg);
                    }
                }
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
                connect=false;
            }
            super.run();
        }
    }[/code]3,调用百度地图API实现轨迹绘制
首先获取xml中加入的地图组件,mMapView = (MapView) findViewById(R.id.bmapview);   
mBaiduMap = mMapView.getMap();设置地图缩放级别mBaiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(new MapStatus.Builder().zoom(21).build()));之后,使用Overlay mPolyline = mBaiduMap.addOverlay(mOverlayOptions);逐段加入两点连线,最终形成上图中的轨迹。更新坐标位置,让最后发来的位置坐标作为地图的中心mBaiduMap.animateMapStatus(u);这里还要注意从GPS卫星接收到的经纬度和百度地图经纬度有偏差,要使用下面方法做纠偏。CoordinateConverter converter1  = new CoordinateConverter().from(CoordinateConverter.CoordType.GPS).coord(p1); LatLng desLatLng1 = converter1.convert();

关键代码如下
  1. mHandler = new Handler(){
  2.             @Override
  3.             public void handleMessage(Message msg) {
  4.                 if(msg.what ==4){
  5.                     if((latitude_n!=null) &amp;&amp;(longitude_n!=null)&amp;&amp;(latitude_o!=null) &amp;&amp;(longitude_o!=null)){

  6.                         List&lt;LatLng&gt; points = new ArrayList&lt;LatLng&gt;();
  7.                         LatLng p1,p2 ;
  8.                         p1=new LatLng( Double.parseDouble(latitude_n),Double.parseDouble(longitude_n));
  9.                         // sourceLatLng待转换坐标

  10.                         CoordinateConverter converter1  = new CoordinateConverter()
  11.                                 .from(CoordinateConverter.CoordType.GPS)
  12.                                 .coord(p1);
  13.                         LatLng desLatLng1 = converter1.convert();
  14.                         points.add(desLatLng1);

  15.                         Log.i("P1","纬度:"+desLatLng1.latitude+" | 经度:"+desLatLng1.longitude);

  16.                         p2=new LatLng( Double.parseDouble(latitude_o),Double.parseDouble(longitude_o));
  17.                         // sourceLatLng待转换坐标

  18.                         CoordinateConverter converter2  = new CoordinateConverter()
  19.                                 .from(CoordinateConverter.CoordType.GPS)
  20.                                 .coord(p2);
  21.                         LatLng desLatLng2 = converter2.convert();
  22.                         points.add(desLatLng2);

  23.                         Log.i("P2","纬度:"+desLatLng2.latitude+" | 经度:"+desLatLng2.longitude);

  24.                         //设置折线的属性
  25.                         OverlayOptions mOverlayOptions = new PolylineOptions()
  26.                                 .width(10)
  27.                                 .color(0xAAFF0000)
  28.                                 .points(points);
  29.                         Overlay mPolyline = mBaiduMap.addOverlay(mOverlayOptions);
  30.                         //if(((latitude_n.equals(latitude_o))&amp;&amp;(longitude_n.equals(longitude_o))))
  31.                         {

  32.                             //定义Maker坐标点
  33.                             LatLng p3;
  34.                             p3=new LatLng( Double.parseDouble(latitude_n),Double.parseDouble(longitude_n));

  35.                             // sourceLatLng待转换坐标

  36.                             CoordinateConverter converter3  = new CoordinateConverter()
  37.                                     .from(CoordinateConverter.CoordType.GPS)
  38.                                     .coord(p3);
  39.                             LatLng desLatLng3 = converter3.convert();
  40.                             /*
  41.                             //构建Marker图标
  42.                             BitmapDescriptor bitmap = BitmapDescriptorFactory
  43.                                     .fromResource(R.drawable.icon_w);
  44.                             //构建MarkerOption,用于在地图上添加Marker
  45.                             OverlayOptions option = new MarkerOptions()
  46.                                     .position(desLatLng3)
  47.                                     .icon(bitmap);
  48.                             //在地图上添加Marker,并显示
  49.                             mBaiduMap.addOverlay(option);
  50.                             */
  51.                             // 构造定位数据
  52.                             MyLocationData locData = new MyLocationData.Builder()
  53.                                     .accuracy(0)    //设置精度
  54.                                     .direction(0)                 // 此处设置开发者获取到的方向信息,顺时针0-360
  55.                                     .latitude(desLatLng3.latitude)                   // 设置纬度坐标
  56.                                     .longitude(desLatLng3.longitude)    //设置经度坐标
  57.                                     .build();
  58.                             // 设置定位数据
  59.                             mBaiduMap.setMyLocationData(locData);
  60.                             //设置自定义定位图标
  61.                             BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
  62.                                     .fromResource(R.drawable.icon_w);
  63.                             mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;  //设置定位模式
  64.                             //位置构造方式,将定位模式,定义图标添加其中
  65.                             MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
  66.                             mBaiduMap.setMyLocationConfigeration(config);  //地图显示定位图标

  67.                             MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(desLatLng3);  //更新坐标位置
  68.                             mBaiduMap.animateMapStatus(u);                            //设置地图位置
  69.                         }



  70.                         //获取显示LocationProvider名称的TextView组件
  71.                         TextView textView = (TextView) findViewById(R.id.Textview);
  72.                        // StringBuilder stringBuilder = new StringBuilder();  //使用StringBuilder保存数据
  73.                         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
  74.                         Date date = new Date(System.currentTimeMillis());
  75.                         String str=simpleDateFormat.format(date);

  76.                         textView.setText("");
  77.                         textView.append(str + "\n");
  78.                         textView.append(("N纬度:"+desLatLng1.latitude).toString() + "\n");
  79.                         textView.append(("N纬度:"+desLatLng2.latitude).toString() + "\n");
  80.                         textView.append(("O经度:"+desLatLng1.longitude).toString() + "\n");
  81.                         textView.append(("O经度:"+desLatLng2.longitude).toString() + "\n");
  82.                     }
  83.                 }
  84.                 if(msg.what ==5){
  85.                     TextView textView = (TextView) findViewById(R.id.Text2view);
  86.                     textView.setText("receive is  "+Integer.toString(TCP_R_Count));
  87.                 }
  88.                 super.handleMessage(msg);
  89.             }

  90.         };
复制代码



回复

举报

gandonggandong 2020-1-17 08:25:34
坐标知识介绍
.国内主流坐标系类型

主要有以下三种

1. WGS84:一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。

2. GCJ02:由中国国家测绘局制订的地理信息系统的坐标系统,是由WGS84坐标系经过加密后的坐标系。

3. BD09:百度坐标系,在GCJ02坐标系基础上再次加密。其中BD09LL表示百度经纬度坐标,BD09MC表示百度墨卡托米制坐标。

注意:百度地图SDK在国内(包括港澳台)使用的是BD09LL坐标(定位SDK默认使用GCJ02坐标);在海外地区,统一使用WGS84坐标。开发者在使用百度地图相关服务时,请注意选择。

.百度地图SDK是用什么坐标类型?

1. 国内(包括港澳台),输入、输出默认使用BD09LL坐标。支持全局声明为GCJ02坐标类型,全应用支持输入GCJ02坐标,返回GCJ02坐标。

2. 海外地区,输出为WGS84坐标。

.为什么需要坐标转换?

国内(包括港澳台):默认使用BD09LL坐标,国外使用WGS84坐标。若使用非BD09LL坐标直接叠加在百度地图上,因坐标值不同,展示位置会有偏移。

因此:

1)在国内(包括港澳台)通过其他坐标系(WGS84、GCJ02)调用百度地图服务时需要首先将其他坐标转换为BD09LL,再访问百度地图数据。

2)在国外,POI使用WGS84坐标数值,则无需转换、百度地图国外即使用WGS84坐标。

.非百度坐标系,如何转换成百度坐标系?

1. 通用坐标转换方法: 手动调用百度地图SDK坐标转换接口,将输入的WGS84或GCJ02坐标转换为BD09LL坐标。适用于所有百度地图开发者,是转换为百度BD09LL坐标的官方基础算法。

2. 自动坐标转换算法:支持全局声明为GCJ02坐标类型,全应用内自动执行从GCJ02到BD09LL的坐标转换,即直接输入GCJ02坐标,返回GCJ02坐标。

通用坐标转换方法(坐标之间互相转换)
开发者可以手动调用百度地图SDK坐标转换接口,将输入的WGS84或GCJ02坐标转换为BD09LL坐标。如未对坐标参数进行设置,默认使用BD09LL坐标系。

注意:请勿使用其他非百度地图SDK提供的坐标转换方法!!!

.其他坐标转换百度经纬度坐标BD09LL

将google地图、高德地图、腾讯地图、搜狗地图所用坐标转换成百度地图坐标

//初始化左边转换工具类,指定源坐标类型和坐标数据
//sourceLatLng 待转换坐标
CoordinateConverter converter  = new CoordinateConverter()
        .from(COMMON)
        .coord(sourceLatLng);

//转换坐标
LatLng desLatLng = converter.convert();

将GPS设备采集的原始GPS坐标转换成百度坐标

//初始化坐标转换工具类,指定源坐标类型和坐标数据
// sourceLatLng待转换坐标
CoordinateConverter converter  = new CoordinateConverter()
        .from(CoordinateConverter.CoordType.GPS)
        .coord(sourceLatLng);

//desLatLng 转换后的坐标
LatLng desLatLng = converter.convert();
..百度墨卡托坐标转百度经纬度坐标(BD09MC转BD09LL)

//初始化坐标转换工具类,设置源坐标类型和原坐标数据
CoordinateConverter converter  = new CoordinateConverter()
        .from(BD09MC)
        .coord(sourceLatLng);

//转换坐标
LatLng desLatLng = converter.convert();
自动坐标转换(GCJ02坐标输入输出)
支持全局声明为GCJ02坐标类型,全应用内自动执行从GCJ02到BD09LL的坐标转换,即直接输入GCJ02坐标,返回GCJ02坐标。

.声明全局声明坐标类型

//自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
//包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
SDKInitializer.setCoordType(CoordType.GCJ02);
.获取当前使用的坐标类型

SDKInitializer.getCoordType();//BD09LL或者GCJ02坐标
注意事项
.自动坐标转换方法仅适用于国内(包括港澳台)输入坐标为GCJ02坐标的情况。

.百度地图国外即使用WGS84坐标,如需要支持海外地图,直接使用WGS84坐标访问即可,无需转换。如需要同时访问国内和国外数据,自动坐标转换方法不适用。

.百度地图SDK在国内(包括港澳台)使用的是BD09LL坐标(定位SDK默认使用GCJ02坐标);在海外地区,统一使用WGS84坐标,开发者在使用百度地图相关服务时,请注意选择。
回复

举报

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发经验
关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表