zoukankan      html  css  js  c++  java
  • C# 使用Google API进行手机基站定位资料整理

     在网上收集了一部分关于使用Google API进行手机定位的资料和大家分享:

     关于基站定位方面的介绍:

    http://tech.c114.net/164/a140837.html

    开发方面的帮助:

    http://www.dotblogs.com.tw/kylin/archive/2009/08/09/9964.aspx

    http://code.google.com/intl/zh-CN/apis/maps/documentation/staticmaps/

    http://www.codeproject.com/KB/mobile/DeepCast.aspx

    http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!7866.entry?wa=wsignin1.0&sa=334916734

    以上方法的流程一般如下:

    通过RIL获取CellTowerInfo----->通过google api获取经纬度------->转换成54或是地方坐标后在地图上显示位置

    本人整理了代码进行了测试,效果不是很好,使用的多普达S700,windows mobile 专业版 6.1 ,地点在上海,

    定位结果如下

    CELLID=1346
    LAC=43060
    MCC=460
    MNC=0

    从google获取的坐标31.109,121.368,定位位置到了莘西路上

    经过计算与实际位置直线距离在8KM左右

     

    而通过Google Maps在手机上测试当前位置提示精度为18000m,呵呵,这个精度恐怕只能确定在那个城市了,个人认为:原因可能有以下几点:

    1.周围基站分布较少或是真的很远,上海的移动2G基站每年的数量都在减少,有时在公司的时候都会出现盲区,信号不是很好

    2.直接通过cellid,lac,mcc,mnc等信息在Google上获取的经纬度没有经过误差分析,没有太大的精度可言

    3.绕开中国移动运营商进行手机基站定位比较难,人家要靠这个赚钱的,当然也牵涉到国家安全,呵呵

    4.RIL相关函数严格来说在Windows Mobile 上面都不是必须被实现的

    下面是我的代码和注释,有些地方还是不能理解:

      1    public class RIL
      2     {
      3         //CellTower信息
      4         private static string celltowerinfo = "";
      5 
      6         //通过RIL获取CellID
      7         public static string GetCellTowerInfo()
      8         {
      9             //初始化句柄
     10             IntPtr hRil = IntPtr.Zero;
     11             IntPtr hRes = IntPtr.Zero;
     12 
     13             //初始化结果变量
     14             celltowerinfo = "";
     15 
     16             //为一个Client初始化RIL    
     17             hRes = RIL_Initialize(1,
     18                                new RILRESULTCALLBACK(rilResultCallBack),
     19                                null,
     20                                0,
     21                                0,
     22                                out hRil);
     23 
     24             if (hRes != IntPtr.Zero)
     25             {
     26                 return "不能初始化RIL";
     27             }
     28 
     29             //获取当前Phone使用的基站信息
     30             hRes = RIL_GetCellTowerInfo(hRil);
     31 
     32             waithandle.WaitOne();
     33 
     34             //解除RIL
     35             RIL_Deinitialize(hRil);
     36 
     37             return celltowerinfo;
     38 
     39 
     40         }
     41 
     42         private static AutoResetEvent waithandle = new AutoResetEvent(false);
     43 
     44         public static void rilResultCallBack(uint dwCode, 
     45                                              IntPtr hrCmdID, 
     46                                              IntPtr lpData, 
     47                                              uint cdData, 
     48                                              uint dwParam)
     49         {
     50             RILCELLTOWERINFO rilCellTowerInfo = new RILCELLTOWERINFO();
     51 
     52             //将数据lpData从非托管内存块封送到rilCellTowerInfo托管对象中
     53             Marshal.PtrToStructure(lpData, rilCellTowerInfo);
     54 
     55             celltowerinfo = rilCellTowerInfo.dwCellID + "-" + rilCellTowerInfo.dwLocationAreaCode + "-" +
     56                             rilCellTowerInfo.dwMobileCountryCode+"-"+rilCellTowerInfo.dwMobileNetworkCode;
     57                
     58             //将事件状态设置为终止状态,允许一个或多个等待线程继续
     59             waithandle.Set();
     60         }
     61         
     62         public delegate void RILRESULTCALLBACK(uint dwCode,IntPtr hrCmdID,IntPtr lpData,uint cbData,uint dwParam);
     63 
     64         public delegate void RILNOTIFYCALLBACK(uint dwCode,IntPtr lpData,uint cbData,uint dwParam);
     65 
     66         //RIL基站信息类
     67         public class RILCELLTOWERINFO
     68         {
     69                public uint cbSize;  
     70                public uint dwParams;  
     71                public uint dwMobileCountryCode;  
     72                public uint dwMobileNetworkCode;  
     73                public uint dwLocationAreaCode;  
     74                public uint dwCellID;  
     75                public uint dwBaseStationID;  
     76                public uint dwBroadcastControlChannel;  
     77                public uint dwRxLevel;  
     78                public uint dwRxLevelFull;  
     79                public uint dwRxLevelSub;  
     80                public uint dwRxQuality;  
     81                public uint dwRxQualityFull;  
     82                public uint dwRxQualitySub;  
     83                public uint dwIdleTimeSlot;  
     84                public uint dwTimingAdvance;  
     85                public uint dwGPRSCellID;  
     86                public uint dwGPRSBaseStationID;  
     87                public uint dwNumBCCH;  
     88 
     89 
     90         }
     91 
     92         /* 调用API    
     93          * 初始化RIL    
     94          * MSDN:   http://msdn.microsoft.com/zh-cn/library/aa919106(en-us).aspx */
     95         [DllImport("ril.dll")]
     96         private static extern IntPtr RIL_Initialize(uint dwIndex, RILRESULTCALLBACK pfnResult, RILNOTIFYCALLBACK pfnNotify, uint dwNotificationClasses, uint dwParam, out IntPtr lphRil);
     97         [DllImport("ril.dll")]
     98         private static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);
     99         [DllImport("ril.dll")]
    100         private static extern IntPtr RIL_Deinitialize(IntPtr hRil);
    101 
    102     }

    之后是有关通信方面的,通过基站信息获取经纬度(GOOGLE API)

    代码
      public class GMM
        {     
              
    static byte[] PostData(int MCC, int MNC, int LAC, int CID,  
                                   
    bool shortCID)  
          { 
               
                
    byte[] pd = new byte[]{  
                    
    0x000x0e,  
                    
    0x000x000x000x000x000x000x000x00,  
                    
    0x000x00,  
                    
    0x000x00,  
                    
    0x000x00,  
     
                    
    0x1b,  
                    
    0x000x000x000x00// Offset 0x11  
                    0x000x000x000x00// Offset 0x15  
                    0x000x000x000x00// Offset 0x19  
                    0x000x00,  
                    
    0x000x000x000x00// Offset 0x1f  
                    0x000x000x000x00// Offset 0x23  
                    0x000x000x000x00// Offset 0x27  
                    0x000x000x000x00// Offset 0x2b  
                    0xff0xff0xff0xff,  
                    
    0x000x000x000x00  
                };  
     
                
    bool isUMTSCell = ((Int64)CID > 65535);  
     
                
    if (isUMTSCell)  
                    Console.WriteLine(
    "UMTS CID.{0}", shortCID ?  
                     
    "Using short CID to resolve." : "");  
                
    else  
                    Console.WriteLine(
    "GSM CID given.");  
     
                
    if (shortCID)  
                    CID 
    &= 0xFFFF;      /* Attempt to resolve the cell using the    
     
                if ((Int64)CID > 65536) /* GSM: 4 hex digits, UTMS: 6 hex  
                                        digits 
    */
                
    if ((Int64)CID > 65536)
                    pd[
    0x1c= 5;  
                
    else  
                    pd[
    0x1c= 3;  
     
                pd[
    0x11= (byte)((MNC >> 24& 0xFF);  
                pd[
    0x12= (byte)((MNC >> 16& 0xFF);  
                pd[
    0x13= (byte)((MNC >> 8& 0xFF);  
                pd[
    0x14= (byte)((MNC >> 0& 0xFF);  
     
                pd[
    0x15= (byte)((MCC >> 24& 0xFF);  
                pd[
    0x16= (byte)((MCC >> 16& 0xFF);  
                pd[
    0x17= (byte)((MCC >> 8& 0xFF);  
                pd[
    0x18= (byte)((MCC >> 0& 0xFF);  
     
                pd[
    0x27= (byte)((MNC >> 24& 0xFF);  
                pd[
    0x28= (byte)((MNC >> 16& 0xFF);  
                pd[
    0x29= (byte)((MNC >> 8& 0xFF);  
                pd[
    0x2a= (byte)((MNC >> 0& 0xFF);  
     
                pd[
    0x2b= (byte)((MCC >> 24& 0xFF);  
                pd[
    0x2c= (byte)((MCC >> 16& 0xFF);  
                pd[
    0x2d= (byte)((MCC >> 8& 0xFF);  
                pd[
    0x2e= (byte)((MCC >> 0& 0xFF);  
     
                pd[
    0x1f= (byte)((CID >> 24& 0xFF);  
                pd[
    0x20= (byte)((CID >> 16& 0xFF);  
                pd[
    0x21= (byte)((CID >> 8& 0xFF);  
                pd[
    0x22= (byte)((CID >> 0& 0xFF);  
     
                pd[
    0x23= (byte)((LAC >> 24& 0xFF);  
                pd[
    0x24= (byte)((LAC >> 16& 0xFF);  
                pd[
    0x25= (byte)((LAC >> 8& 0xFF);  
                pd[
    0x26= (byte)((LAC >> 0& 0xFF);  
     
                
    return pd;  
            }
                                        
    //GSM CID part */  
     
           
    /// <summary>
           
    /// 通过基站信息获取经纬度
           
    /// </summary>
           
    /// <param name="args"></param>
           
    /// <returns></returns>
            static public string GetLatLng(string[] args)  
           {  
                
    if (args.Length < 4)  
                {  
                    
    return string.Empty;  
                }  
                
    string shortCID = "";   /* Default, no change at all */  
                
    if (args.Length == 5)  
                    shortCID 
    = args[4].ToLower();  
                
    try  
                {  
                    String url 
    = "http://www.google.com/glm/mmap";  
                    HttpWebRequest req 
    = (HttpWebRequest)WebRequest.Create(  
                        
    new Uri(url));  
                    req.Method 
    = "POST";  
     
                    
    int MCC = Convert.ToInt32(args[0]);  
                    
    int MNC = Convert.ToInt32(args[1]);  
                    
    int LAC = Convert.ToInt32(args[2]);  
                    
    int CID = Convert.ToInt32(args[3]);  
                    
    byte[] pd = PostData(MCC, MNC, LAC, CID,  
                        shortCID 
    == "shortcid");  
     
                    req.ContentLength 
    = pd.Length;  
                    req.ContentType 
    = "application/binary";  
                    Stream outputStream 
    = req.GetRequestStream();  
                    outputStream.Write(pd, 
    0, pd.Length);  
                    outputStream.Close();  
     
                    HttpWebResponse res 
    = (HttpWebResponse)req.GetResponse();  
                    
    byte[] ps = new byte[res.ContentLength];  
                    
    int totalBytesRead = 0;  
                    
    while (totalBytesRead < ps.Length)  
                    {  
                        totalBytesRead 
    += res.GetResponseStream().Read(  
                            ps, totalBytesRead, ps.Length 
    - totalBytesRead);  
                    }  
     
                    
    if (res.StatusCode == HttpStatusCode.OK)  
                   {  
                        
    short opcode1 = (short)(ps[0<< 8 | ps[1]);  
                        
    byte opcode2 = ps[2];  
                        
    int ret_code = (int)((ps[3<< 24| (ps[4<< 16|  
                                       (ps[
    5<< 8| (ps[6]));  
                        
    if (ret_code == 0)  
                      {  
                            
    double lat = ((double)((ps[7<< 24| (ps[8<< 16)  
                                         
    | (ps[9<< 8| (ps[10]))) / 1000000;  
                            
    double lon = ((double)((ps[11<< 24| (ps[12<<  
                                         
    16| (ps[13<< 8| (ps[14]))) /  
                                         
    1000000;  
                            
    return lat + "|" + lon;  
                        }  
                        
    else  
                            
    return string.Empty;  
                    }  
                    
    else  
                        
    return string.Empty;  
                }  
                
    catch (Exception ex)  
                {  
                    MessageBox.Show(ex.ToString());  
                    
    return string.Empty;  
                }  
            }  

        }

    下面在介绍一种只要知道cellid和lac两个参数就可以获取经纬度的方法:

     1  /// <summary>
     2         /// 判断是否正确获取经纬度信息
     3         /// </summary>
     4         /// <param name="cellid">cellid</param>
     5         /// <param name="lac">LocationAreaCode</param>
     6         /// <param name="Lat">latitude</param>
     7         /// <param name="Lng">longgitude</param>
     8         /// <returns></returns>
     9         public static bool LocateGooleMapApi(uint cellid, uint lac, out double Lat, out double Lng)
    10         {
    11             HttpWebRequest request =(HttpWebRequest)WebRequest.Create("http://www.google.com/glm/mmap");
    12             request.Method = "POST";
    13 
    14          
    15             byte[] byteArray = {0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02
    16                         0x650x6E// en
    17                         0x000x07
    18                         0x410x6E0x640x720x6F0x690x64
    19                         0x000x03
    20                         0x310x2E0x30// 1.0
    21                         0x000x03
    22                         0x570x650x62// web
    23                         0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    24                         0x00,0x00,0x00,0x00,0x03,0x00,0x00
    25                         0xFF0xFF0xFF0xFF// CellID
    26                         0xFF0xFF0xFF0xFF// LAC
    27                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    28                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
    29 
    30             // write CellID
    31             byte[] intByte = BitConverter.GetBytes(cellid);
    32             byteArray[48= intByte[3];
    33             byteArray[49= intByte[2];
    34             byteArray[50= intByte[1];
    35             byteArray[51= intByte[0];
    36 
    37             // write LAC
    38             intByte = BitConverter.GetBytes(lac);
    39             byteArray[52= intByte[3];
    40             byteArray[53= intByte[2];
    41             byteArray[54= intByte[1];
    42             byteArray[55= intByte[0];
    43 
    44             // set request
    45             request.ContentLength = byteArray.Length;
    46             Stream postStream = request.GetRequestStream();
    47             postStream.Write(byteArray, 0, byteArray.Length);
    48             postStream.Close();
    49 
    50             // Get the response.
    51             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    52             Console.WriteLine("[I] Request response: {0}", response.StatusDescription);
    53 
    54             // Read response
    55             Stream dataStream = response.GetResponseStream();
    56             BinaryReader BR = new BinaryReader(dataStream);
    57             // skip 3 byte
    58             BR.ReadByte();
    59             BR.ReadByte();
    60             BR.ReadByte();
    61 
    62             // check state
    63             if (0 == BR.ReadInt32())
    64             {
    65                 // read lat
    66                 byte[] tmpByte = new byte[4];
    67                 tmpByte[3= BR.ReadByte();
    68                 tmpByte[2= BR.ReadByte();
    69                 tmpByte[1= BR.ReadByte();
    70                 tmpByte[0= BR.ReadByte();
    71                 Lat = (double)(BitConverter.ToInt32(tmpByte, 0)) / 1000000D;
    72 
    73                 // read lng
    74                 tmpByte[3= BR.ReadByte();
    75                 tmpByte[2= BR.ReadByte();
    76                 tmpByte[1= BR.ReadByte();
    77                 tmpByte[0= BR.ReadByte();
    78                 Lng = (double)(BitConverter.ToInt32(tmpByte, 0)) / 1000000D;
    79 
    80                 BR.Close();
    81                 dataStream.Close();
    82                 response.Close();
    83                 return true;
    84             }
    85             else
    86             {
    87                 BR.Close();
    88                 dataStream.Close();
    89                 response.Close();
    90                 Lat = 0;
    91                 Lng = 0;
    92                 return false;
    93             }
    94 
    95 
    96         }

    最后只要用C#2008 建立一个新项目,添加webbrowser控件,添加一个按键代码如下:

     1       Cursor.Current = Cursors.WaitCursor;
     2             string [] cellidFields = RIL.GetCellTowerInfo().ToString().Split('-');
     3               
     4             string[] args ={
     5                                cellidFields[2],
     6                                "0",
     7                                cellidFields[1],
     8                                cellidFields[0]
     9                            };
    10             string[] latlng = GMM.GetLatLng(args).Split('|');
    11 
    12             Uri url = new Uri("http://maps.google.com/staticmap?&maptype=satellite&key=xxx&markers=" + latlng[0].ToString().Replace(',''.'+ "," + latlng[1].ToString().Replace(',''.'+ "&center=,&size=240x320&zoom=18");
    13             webBrowser1.Navigate(url);
    14             Cursor.Current = Cursors.Default;

     

    就只有这些了,如果谁有更好的利用GOOGLE 进行手机基站定位,精度较高的方法,请告诉我,本人不胜感激啊!

  • 相关阅读:
    Elasticsearch 检索
    Elasticsearch 基本操作
    Elasticsearch 集群
    Elasticsearch 插件head和kibana
    Elasticsearch 安装
    CentOS 安装JDK
    前端登录密码加密传输
    springboot2.0 快速集成kafka
    原来自定义模型绑定器还可以这么玩
    Value cannot be null or empty. 参数名: contentPath
  • 原文地址:https://www.cnblogs.com/MyLucifer/p/1673587.html
Copyright © 2011-2022 走看看