打印

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

[复制链接]
1377|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
感动|  楼主 | 2019-12-22 15:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 感动 于 2019-12-27 13:32 编辑
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

[hide=d1000]char *gpsdata;
        int i,count;
        if(USART_GetITStatus(USART2,USART_IT_IDLE) == SET)     
        {                                                
                USART2->SR;        
                USART2->DR;
                USART_ClearITPendingBit(USART2,USART_IT_IDLE);
                DMA_Cmd(DMA1_Channel6,DISABLE);                      //??DMA        
                U2_Rx_Counter = 1024 - DMA_GetCurrDataCounter(DMA1_Channel6);  //??????????                          
                gpsdata = strstr(U2_RX_data,"$GNRMC");
                if(gpsdata)        
                {
                        for(i=0;i<strlen(gpsdata);i++)
                        {
                                if(gpsdata[i]==',')
                                {
                                        count++;
                                        if(count==2)
                                        {
                                                        
                                                        if(gpsdata[i+1]=='A')
                                                        {
                                                                gps_flag=1;
                                                               
                                                        }
                                                        else
                                                        {
                                                                gps_n=0;
                                                                gps_e=0;
                                                                break;
                                                        }
                                        }        
                                        if(gps_flag==1)
                                        {
                                                if((count==3)&&(gpsdata[i+1]!=','))
                                                {
                                                        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);
                                                }
                                                if((count==5)&&(gpsdata[i+1]!=','))
                                                {
                                                        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);                        
                                                }               
                                                if(count>=13)
                                                {
                                                        count=0;
                                                        gps_flag=0;
                                                        break;
                                                }
                                        }        
                                }        
                        }
                }
                memset(U2_RX_data,0, 1024);               
                DMA1_Channel6->CNDTR = 1024;                            //??????????           
                DMA_Cmd(DMA1_Channel6,ENABLE);                       //??DMA            
        }[/hide]
单片机与服务器通过AT指令控制GPRS模块与服务器通信,AT指令是比较难的,开发过的会有感受,AT指令返回的状态比较多,并不是返回一种或两种结果。不但要按照正常流程一步一步发送AT指令,还要有错误返回处理。AT指令挺复杂的,特别适合用状态机处理这些流程。
[hide=d1000]switch (M26_info.state)             
        {
                case GPRS_state_Poweroff :
                                if(AT_Delay_Timer>5)
                                {
                                        GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);
                                        GPIO_SetBits(GPIOA,GPIO_Pin_1);
                                        GPIO_ResetBits(GPIOA, GPIO_Pin_7);
                                        GPIO_ResetBits(GPIOA, GPIO_Pin_4);             // Sleep
                                }
                                if(AT_Delay_Timer>25)
                                {
                                        GPIO_ResetBits(GPIOA,GPIO_Pin_1);
                                        GPIO_SetBits(GPIOA, GPIO_Pin_7);
                                }                                
                                if(AT_Delay_Timer>45)
                                {
                                        GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);
                                        M26_info.state=GPRS_state_AT;
                                        AT_Timeslimite=0;
                                        AT_Delay_Timer=0;
                                        AT_overtime=0;
                                        ZC_DATA_flog=1;
                                }               
                        break;
                case GPRS_state_AT :
                                M26_ATTR(5,30,50,"AT+IPR=115200&W\r\n","OK","","","","",GPRS_state_CREG,GPRS_state_AT);
                        break;
                case GPRS_state_CREG :
                                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);
                        break;
                case GPRS_state_CSQ :
                                M26_ATTR(2,30,20,"AT+CSQ\r\n","+CSQ:","","","","",GPRS_state_QIDNSIP,GPRS_state_CSQ);
                case GPRS_state_QIDNSIP:
                                M26_ATTR(2,30,5,"AT+QIFGCNT=0\r\n","OK","","","","",GPRS_state_QIDEACT,GPRS_state_Poweroff);
                        break;
                case GPRS_state_QIDEACT:
                                M26_ATTR(2,2,50,"AT+QICSGP=1,\"CMMTM\"\r\n","OK","","ERROR","","",GPRS_state_QIREGAPP,GPRS_state_Poweroff);
                                break;
                case GPRS_state_QIREGAPP:
                                M26_ATTR(2,2,50,"AT+QIREGAPP\r\n","OK","","ERROR","","",GPRS_state_QIACT,GPRS_state_Poweroff);
                        break;
                case GPRS_state_QIACT:
                                M26_ATTR(10,2,300,"AT+QIACT\r\n","OK","","ERROR","","",GPRS_state_QIOPEN,GPRS_state_Poweroff);
                        break;
                case GPRS_state_QIOPEN:
                                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);
                        break;
                case GPRS_state_QISTAT:
                                M26_ATTR(10,10,500,"AT+QISTAT\r\n","STATE: CONNECT OK","","STATE: IP INITIAL","","",GPRS_state_QISEND,GPRS_state_QIOPEN);
                        break;
                case GPRS_state_QISEND:
                                ////GPRS_DATA_flog=1;
                                M26_ATTR(50,20,100,"AT+QISEND=27\r\n",">",">","ERROR","ERROR","ERROR",GPRS_state_QISENDDATA,GPRS_state_QISENDDATA);
                        break;
                case GPRS_state_QISENDDATA:
                                M26_senddata(10,10,100,"12345678","SEND OK","","ERROR","ERROR","ERROR",GPRS_state_QISEND,GPRS_state_Poweroff);
                        break;
               
                default:  ;
        }[/hide]

服务器后台
用C#编写服务器后台程序,他负责接收所有设备发来数据,把与客户端有关的设备数据转发给客户端。这样局域网里的客户端可以通过网关获取服务器的数据。服务器程序用到多线程技术,可以同时处理多个设备发来的数据。用到了Dictionary数据类型,实现设备ID与socket对应,关键代码如下
[hide=d1000]private void ReceiveClient(object obj)
        {
            Socket _ClientSocket = (Socket)obj;
            while (true)
            {
                try
                {
                    byte[] result = new byte[1024];
                    int receiveLength = _ClientSocket.Receive(result);            
                    string clientMessage = Encoding.UTF8.GetString(result, 0, receiveLength);
                    string Destination_Address;
                    string Data_Rcve;
                    if (receiveLength == 0)
                    {
                        ClientSocketDictionary.Remove(_ClientSocket);
                        _ClientSocket.Shutdown(SocketShutdown.Both);
                        _ClientSocket.Close();
                        SetText2box();
                        break;
                    }
                    else
                    {
                        if ((result[0] == '
[align=left][color=#333333][font=微软雅黑][size=18px]客户端[/size][/font][/color][/align][align=left][color=#333333][font=微软雅黑][size=18px]C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下[/size][/font][/color][/align][code]private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                clientScoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientScoket.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text.ToString()), 8888));
                t = new Thread(ReceiveMessage);//开启线程执行循环接收消息
                t.IsBackground=true;
                t.Start();
                button1.Text = "已连接服务器";
                button1.Enabled = false;
            }
            catch (Exception ex)
            {
                SetText3box(ex);
                button1.Text = "无法连接服务器";
                button1.Enabled = true;
            }
                  
        }
      
        public delegate void CallSetTextbox(string ms);
        void ReceiveMessage()//接收消息
        {
            
            string Destination_Address;
            string Data_Rcve;
            send_flog = 1;
            while (true)
            {
                if (clientScoket.Connected == true)
                {
                    
                    
                        if (send_flog == 1)
                        {
                            send_flog = 0;
                            message = "$1" + textBox4.Text;
                            SendMessage(message);
                        }
                        int length = 0;

                        try
                        {
                            length = clientScoket.Receive(data);
                         }
                        catch (Exception e)
                        {
                            SetText3box(e);
                       
                        break;

                        }

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

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

) && (result[1] == '1'))//注册ID  源地址
                        {
                            if (!ClientSocketDictionary.ContainsKey(_ClientSocket))
                            {
                                ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10));
                                SetText2box();
                            }
                            else
                            {
                                ClientSocketDictionary.Remove(_ClientSocket);
                                ClientSocketDictionary.Add(_ClientSocket, clientMessage.Substring(2, 10));
                                SetText2box();
                            }                                       
                        }
                    }
                                                      
                }
                catch (Exception e)
                {
                    ClientSocketDictionary.Remove(_ClientSocket);
                    _ClientSocket.Shutdown(SocketShutdown.Both);
                    _ClientSocket.Close();
                    SetText2box();
                    SetText3box(e);

                    break;
                }
            }
        }
public void SendMessage(string msg)
        {
            if (msg == string.Empty || this.ClientSocketDictionary.Count <= 0) return;
            string Destination_Address = msg.Substring(2, 10);
            string Data_Rcve = msg.Substring(12, msg.Length-12);
            msg = "$3" + Destination_Address + Data_Rcve;

            
            try
            {
                foreach (KeyValuePair<Socket, string> kvp in ClientSocketDictionary)
                {
                   if(kvp.Value.Substring(0,10)== Destination_Address)
                   {
                       kvp.Key.Send(Encoding.UTF8.GetBytes(msg));
                   }              
                }
            }
            catch (Exception e)
            {
                SetText3box(e);
            }
        }      
[/hide]
客户端
C#编写客户端程序,调用百度地图API,实现地图打标,绘制轨迹。客户端工作流程是这样的,首先向服务器发送注册自身ID,然后向服务器获取相关设备ID的数据,解析数据,调用百度地图API实现打标定位等。关键代码如下
[hide=d1000]private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                clientScoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientScoket.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text.ToString()), 8888));
                t = new Thread(ReceiveMessage);//开启线程执行循环接收消息
                t.IsBackground=true;
                t.Start();
                button1.Text = "已连接服务器";
                button1.Enabled = false;
            }
            catch (Exception ex)
            {
                SetText3box(ex);
                button1.Text = "无法连接服务器";
                button1.Enabled = true;
            }
                  
        }
      
        public delegate void CallSetTextbox(string ms);
        void ReceiveMessage()//接收消息
        {
            
            string Destination_Address;
            string Data_Rcve;
            send_flog = 1;
            while (true)
            {
                if (clientScoket.Connected == true)
                {
                    
                    
                        if (send_flog == 1)
                        {
                            send_flog = 0;
                            message = "$1" + textBox4.Text;
                            SendMessage(message);
                        }
                        int length = 0;

                        try
                        {
                            length = clientScoket.Receive(data);
                         }
                        catch (Exception e)
                        {
                            SetText3box(e);
                       
                        break;

                        }

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

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

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

                        }
                        }
                 
                    
                }
                else
                {
                    break;
                }
            }[/hide]

使用特权

评论回复

相关帖子

沙发
感动|  楼主 | 2020-1-11 21:33 | 只看该作者
STM32开发GPRS传输的GPS定位器-android studio开发客户端APP显示轨迹
前面**介绍如何开发定位器硬件,单片机软件,服务器软件,上位机客户端软件,下面介绍如何使用android studio开发客户端APP显示轨迹。

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

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

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

    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapview"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:clickable="true" />
    <TextView
    android:id="@+id/Text2view"
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:text="---"
    android:layout_below="@id/bmapview"/>
    <TextView
        android:id="@+id/Textview"
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:text="---"
        android:layout_below="@id/Text2view"/>
</RelativeLayout>
​​
2,编写TCP与服务器通信程序
这部分主要有三个线程组成,一个用于连接服务器,一个向服务器发送数据,一个接收服务器的数据。

连接服务器线程,这里要实时检查安卓客户端与服务器的连接是否有效,做断线重连,并且开启发送数据线程和接收数据线程,程序如下
private class connectToServer extends Thread{
        @Override
        public void run() {
            while(true)
            {
                try
                {
                    //客户端向服务器发送连接请求
                    //c_Socket = new Socket("---.---.---.---",8888);
                    if (c_Socket==null)
                    {
                        c_Socket = new Socket("---.---.---.---",8888);
                        if (c_Socket.isConnected())
                        {
                            TCP_R_Count=0;
                            int port = c_Socket.getLocalPort();
                            Message msg = new Message();
                            msg.what = 5;
                            msg.obj = String.valueOf(port);
                            mHandler.sendMessage(msg);
                            c_readflag = true;
                            new c_ReadThread().start();
                            new SenfToServer().start();
                            connect=true;
                        }

                    }
                    if(connect==false)
                    {
                        if(c_Socket!=null){
                            c_Socket.close();
                            c_Socket=null;
                        }

                    }

                    //c_Socket = new Socket("192.168.5.32",8888);
                    //c_Socket.connect(IPAddress.Parse(c_ip.getText().toString()), Int32.Parse(c_port.Text));
                }catch(Exception ee)
                {
                    ee.printStackTrace();
                }
            }
            //super.run();
        }

    }
发送线程 目前这部分比较简单,随着功能的增加会逐步丰富。
 //客户端向服务器发送数据
    private class SenfToServer extends Thread{
        @Override
        public void run() {
            while(true)
            {
                if(c_Socket!=null){
                    if (c_Socket.isConnected())
                    {
                        try{
                            out = c_Socket.getOutputStream();
                            out.write("----------------".getBytes());
                            out.flush();
                            SenfToServer.sleep(60000);
                        }
                        catch(Exception e){
//                        connect=false;
                        }
                    }
                }
            }
            //super.run();
        }
    }

接收线程
接收线程接收服务器发来的GPS定位数据,通过Handler向主线程传递消息。这里要检测TCP连接的有效性,如果断开连接要重连服务器。
//客户端接收服务器发来的信息
    private class c_ReadThread extends Thread
    {
        @Override
        public void run() {
            // TODO 自动生成的方法存根
            try {
                InputStream input = c_Socket.getInputStream();
                while (c_readflag)
                {
                    byte[] buff = new byte[100];

                    int size = input.read(buff);
                    if((size>12)){
                        if((buff[0]=='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();关键代码如下
[code]mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                if(msg.what ==4){
                    if((latitude_n!=null) &&(longitude_n!=null)&&(latitude_o!=null) &&(longitude_o!=null)){

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

                        CoordinateConverter converter1  = new CoordinateConverter()
                                .from(CoordinateConverter.CoordType.GPS)
                                .coord(p1);
                        LatLng desLatLng1 = converter1.convert();
                        points.add(desLatLng1);

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

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

                        CoordinateConverter converter2  = new CoordinateConverter()
                                .from(CoordinateConverter.CoordType.GPS)
                                .coord(p2);
                        LatLng desLatLng2 = converter2.convert();
                        points.add(desLatLng2);

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

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

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

                            // sourceLatLng待转换坐标

                            CoordinateConverter converter3  = new CoordinateConverter()
                                    .from(CoordinateConverter.CoordType.GPS)
                                    .coord(p3);
                            LatLng desLatLng3 = converter3.convert();
                            /*
                            //构建Marker图标
                            BitmapDescriptor bitmap = BitmapDescriptorFactory
                                    .fromResource(R.drawable.icon_w);
                            //构建MarkerOption,用于在地图上添加Marker
                            OverlayOptions option = new MarkerOptions()
                                    .position(desLatLng3)
                                    .icon(bitmap);
                            //在地图上添加Marker,并显示
                            mBaiduMap.addOverlay(option);
                            */
                            // 构造定位数据
                            MyLocationData locData = new MyLocationData.Builder()
                                    .accuracy(0)    //设置精度
                                    .direction(0)                 // 此处设置开发者获取到的方向信息,顺时针0-360
                                    .latitude(desLatLng3.latitude)                   // 设置纬度坐标
                                    .longitude(desLatLng3.longitude)    //设置经度坐标
                                    .build();
                            // 设置定位数据
                            mBaiduMap.setMyLocationData(locData);
                            //设置自定义定位图标
                            BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
                                    .fromResource(R.drawable.icon_w);
                            mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;  //设置定位模式
                            //位置构造方式,将定位模式,定义图标添加其中
                            MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
                            mBaiduMap.setMyLocationConfigeration(config);  //地图显示定位图标

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



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

                        textView.setText("");
                        textView.append(str + "\n");
                        textView.append(("N纬度:"+desLatLng1.latitude).toString() + "\n");
                        textView.append(("N纬度:"+desLatLng2.latitude).toString() + "\n");
                        textView.append(("O经度:"+desLatLng1.longitude).toString() + "\n");
                        textView.append(("O经度:"+desLatLng2.longitude).toString() + "\n");
                    }
                }
                if(msg.what ==5){
                    TextView textView = (TextView) findViewById(R.id.Text2view);
                    textView.setText("receive is  "+Integer.toString(TCP_R_Count));
                }
                super.handleMessage(msg);
            }

        };


)&&(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();关键代码如下
mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                if(msg.what ==4){
                    if((latitude_n!=null) &amp;&amp;(longitude_n!=null)&amp;&amp;(latitude_o!=null) &amp;&amp;(longitude_o!=null)){

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

                        CoordinateConverter converter1  = new CoordinateConverter()
                                .from(CoordinateConverter.CoordType.GPS)
                                .coord(p1);
                        LatLng desLatLng1 = converter1.convert();
                        points.add(desLatLng1);

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

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

                        CoordinateConverter converter2  = new CoordinateConverter()
                                .from(CoordinateConverter.CoordType.GPS)
                                .coord(p2);
                        LatLng desLatLng2 = converter2.convert();
                        points.add(desLatLng2);

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

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

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

                            // sourceLatLng待转换坐标

                            CoordinateConverter converter3  = new CoordinateConverter()
                                    .from(CoordinateConverter.CoordType.GPS)
                                    .coord(p3);
                            LatLng desLatLng3 = converter3.convert();
                            /*
                            //构建Marker图标
                            BitmapDescriptor bitmap = BitmapDescriptorFactory
                                    .fromResource(R.drawable.icon_w);
                            //构建MarkerOption,用于在地图上添加Marker
                            OverlayOptions option = new MarkerOptions()
                                    .position(desLatLng3)
                                    .icon(bitmap);
                            //在地图上添加Marker,并显示
                            mBaiduMap.addOverlay(option);
                            */
                            // 构造定位数据
                            MyLocationData locData = new MyLocationData.Builder()
                                    .accuracy(0)    //设置精度
                                    .direction(0)                 // 此处设置开发者获取到的方向信息,顺时针0-360
                                    .latitude(desLatLng3.latitude)                   // 设置纬度坐标
                                    .longitude(desLatLng3.longitude)    //设置经度坐标
                                    .build();
                            // 设置定位数据
                            mBaiduMap.setMyLocationData(locData);
                            //设置自定义定位图标
                            BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
                                    .fromResource(R.drawable.icon_w);
                            mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;  //设置定位模式
                            //位置构造方式,将定位模式,定义图标添加其中
                            MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
                            mBaiduMap.setMyLocationConfigeration(config);  //地图显示定位图标

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



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

                        textView.setText("");
                        textView.append(str + "\n");
                        textView.append(("N纬度:"+desLatLng1.latitude).toString() + "\n");
                        textView.append(("N纬度:"+desLatLng2.latitude).toString() + "\n");
                        textView.append(("O经度:"+desLatLng1.longitude).toString() + "\n");
                        textView.append(("O经度:"+desLatLng2.longitude).toString() + "\n");
                    }
                }
                if(msg.what ==5){
                    TextView textView = (TextView) findViewById(R.id.Text2view);
                    textView.setText("receive is  "+Integer.toString(TCP_R_Count));
                }
                super.handleMessage(msg);
            }

        };


使用特权

评论回复
板凳
liubo0702| | 2020-1-15 11:54 | 只看该作者
感谢分享,有一个问题请教一下:这里还要注意从GPS卫星接收到的经纬度和百度地图经纬度有偏差,要使用下面方法做纠偏。CoordinateConverter converter1  = new CoordinateConverter().from(CoordinateConverter.CoordType.GPS).coord(p1); LatLng desLatLng1 = converter1.convert(),这里能否用文字方式介绍一下,遇到这个问题没有太解决好!谢谢!

使用特权

评论回复
地板
感动|  楼主 | 2020-1-17 08:25 | 只看该作者
坐标知识介绍
.国内主流坐标系类型

主要有以下三种

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坐标,开发者在使用百度地图相关服务时,请注意选择。

使用特权

评论回复
5
西瓜九毛八| | 2020-9-8 19:29 | 只看该作者
你能帮我开发一款车载定位器吗, 我出费用, 如有兴趣 ,回复我,我联系您,私信我

使用特权

评论回复
6
感动|  楼主 | 2020-9-19 11:17 | 只看该作者
西瓜九毛八 发表于 2020-9-8 19:29
你能帮我开发一款车载定位器吗, 我出费用, 如有兴趣 ,回复我,我联系您,私信我 ...

加微信 18622454561

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:关注我的博客https://blog.csdn.net/gd1984812 淘宝店 https://shop570248211.taobao.

35

主题

57

帖子

4

粉丝