您的位置:首页 > 编程语言 > Go语言

通过RIL和GOOGLE实现基站定位

2010-09-12 12:00 369 查看
本文实现的基本原是,在windows mobile带手机功能的手机通过RIL调用就可以获取到基站的编号、区域号、国家代码等信息,通过这些信息访问google提供的一个网址就可以返回该基站的经纬度。(本文参考了很多网上的资料)

在网上查看资料说是可以获取多个基站,但我一直不能实现,还有我在一款CDMA的手机也实现不了。

定义NativeMethods类,写入要调用的方法。

internal static class NativeMethods
{
//初始化RIL接口
[DllImport("ril.dll")]
public static extern IntPtr RIL_Initialize(uint dwIndex,
RILRESULTCALLBACK pfnResult,
RILNOTIFYCALLBACK pfnNotify,
uint dwNotificationClasses,
uint dwParam,
out IntPtr lphRil);

//获取基站信息
[DllImport("ril.dll")]
public static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);

//释放资源
[DllImport("ril.dll")]
public static extern IntPtr RIL_Deinitialize(IntPtr hRil);

//这个方法为最小化窗口时使用到的,非定位所需方法
[DllImport("coredll")]
public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
}


定义接收基站信息结构和委托

public class RILCELLTOWERINFO
{
public uint cbSize;     //字节。
public uint dwParams;   //合法的参量。 必须是其中一个或RILCELLTOWERINFO参量常数的组合。
public uint dwMobileCountryCode;    //国家或区域代码。中国的MCC为460
public uint dwMobileNetworkCode;    //流动网络的代码。
public uint dwLocationAreaCode;     //当前地点的区号。
public uint dwCellID;               //多孔的塔的ID。
public uint dwBaseStationID;        //基地的ID。
public uint dwBroadcastControlChannel;//广播控制通道(BCCH)。
public uint dwRxLevel;              //被接受的信号电平。
public uint dwRxLevelFull;          //在充分的网络的被接受的信号电平。
public uint dwRxLevelSub;           //在子系统的被接受的信号质量。
public uint dwRxQuality;            //被接受的信号质量。
public uint dwRxQualityFull;        //在充分的网络的被接受的信号质量。
public uint dwRxQualitySub;         //在子系统的被接受的信号质量。
public uint dwIdleTimeSlot;         //无所事事的时隙。
public uint dwTimingAdvance;        //时间前进。
public uint dwGPRSCellID;           //GPRS多孔的塔的ID。
public uint dwGPRSBaseStationID;    //GPRS基地的ID。
public uint dwNumBCCH;              //BCCH的数量。

}

public delegate void RILRESULTCALLBACK(uint dwCode,
IntPtr hrCmdID,
IntPtr lpData,
uint cbData,
uint dwParam);

public delegate void RILNOTIFYCALLBACK(uint dwCode,
IntPtr lpData,
uint cbData,
uint dwParam);


好现在就可以来实现获取基站信息了

System.IntPtr hRes;
System.IntPtr hRil;
private static AutoResetEvent waithandle = new AutoResetEvent(false);
private static RILCELLTOWERINFO rilCellTowerInfo;
private void GetCellInfo_Click(object sender, EventArgs e)
{
  //获取手机CellID
  hRes = NativeMethods.RIL_Initialize(1, new RILRESULTCALLBACK(rilResultCallback), null, 0, 0, out hRil);

  NativeMethods.RIL_GetCellTowerInfo(hRil);

  //等待回调函数返回
  waithandle.WaitOne();

  //释放RIL handle
  NativeMethods.RIL_Deinitialize(hRil);
}

public static void rilResultCallback(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam)
{
//构造一个RILCELLTOWERINFO类用于存放数据
rilCellTowerInfo = new RILCELLTOWERINFO();
Marshal.PtrToStructure(lpData, rilCellTowerInfo);

//回调通知
waithandle.Set();
}


获取时会卡一小会,建议把这部分放入单独的线程中。

获取到基站后就使用google来查询出经纬度了。

访问google进行查询的类

/// <summary>
/// LocationService 的摘要说明
/// </summary>
public class LocationService
{
public static string ErrorMessage;

public LocationService(string postData)
{
GetLocationInfomation(postData);
}

/// <summary>
/// 返回经纬度信息
/// 格式如下:
/// 22.506421,113.918245|22.497636,113.912647|22.496063,113.91121
/// </summary>
/// <param name="postData"></param>
/// <returns></returns>
public string GetLocationInfomation(string postData)
{
List<CellInfo> list = GetCellInfos(postData);
StringBuilder sb = new StringBuilder();

for (int i = 0; i < list.Count; i++)
{
CellInfo info = list[i];
//基本步骤
//1. 生成发往google的json串
//2. 接收google返回的json串
//3. 解析json串,只取得经纬度
//4. 拼接经纬度
string json = GenerateRequestJson(info);
string content = GetResponseJson(json);
string latLon = ParseResponseJson(content);

sb.Append(latLon);
sb.Append("|");
}

return sb.ToString().Substring(0, sb.Length - 1);
//return sb.ToString();
}

/// <summary>
/// 接收从手机端发送过来的数据
/// '|'分割对象,','分割属性
/// </summary>
/// <param name="postData"></param>
/// <returns></returns>
private List<CellInfo> GetCellInfos(string postData)
{
string[] strInfos = postData.Split('|');
List<CellInfo> list = new List<CellInfo>();
for (int i = 0; i < strInfos.Length; i++)
{
string[] properties = strInfos[i].Split(',');
CellInfo info = new CellInfo();

info.CID = properties[0];
info.LAC = properties[1];
info.MCC = properties[2];
info.MNC = properties[3];

list.Add(info);
}
return list;
}

/// <summary>
/// 发送一个基站信息,并返回一个位置信息
/// 位置信息是以json串的形式存在
/// 需要对json串进行解析
/// </summary>
/// <param name="requestJson"></param>
private string GetResponseJson(string requestJson)
{
string responseJson = string.Empty;
try
{
ServicePointManager.Expect100Continue = false;
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] data = encoding.GetBytes(requestJson);

HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(@"http://www.google.com/loc/json");

// myRequest.Timeout = 5000;
// myRequest.Proxy = null;
myRequest.Method = "POST";
myRequest.ContentType = "application/requestJson";
myRequest.ContentLength = data.Length;

Stream newStream = myRequest.GetRequestStream();

// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();

// Get response JSON string
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();

StreamReader reader = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.Default);
responseJson = reader.ReadToEnd();
myResponse.Close();

}
catch(Exception ex)
{
string pp = ex.Message;
}

return responseJson;
}

/// <summary>
/// 解析从google Response的JSON串,获取经纬度
/// </summary>
/// <param name="responseJson"></param>
/// <returns></returns>
private string ParseResponseJson(string responseJson)
{
StringBuilder latLon = new StringBuilder();
JObject obj = JObject.Parse(responseJson);

string lat = obj["location"]["latitude"].ToString();
string lon = obj["location"]["longitude"].ToString();

latLon.Append(lat);
latLon.Append(",");
latLon.Append(lon);

return latLon.ToString();

//return responseJson;
}

/// <summary>
/// 生成发往http://www.google.com/loc/json的json串
/// 仅仅只有一个基站
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
private string GenerateRequestJson(CellInfo info)
{

string json = "";
json += "{";
json += "/"version/":/"1.1.0/"" + ",";
json += "/"host/":/"maps.google.com/"" + ",";
json += "/"cell_towers/":[";

json += "{";
json += "/"cell_id/":" + info.CID + ",";
json += "/"location_area_code/":" + info.LAC + ",";
json += "/"mobile_country_code/":" + info.MCC + ",";
json += "/"mobile_network_code/":" + info.MNC;
json += "}";

json += "],";
json += "/"wifi_towers/": [{}]";
json += "}";

return json;
}
}


里面我引用了,using Newtonsoft.Json.Linq;

这个程序集是用于json的解析,可以在网上下载得到,稍后也会在csdn的下载添加一个下载连接。

写好后使用它就非常简单了

string postData=rilCellTowerInfo.dwCellID.ToString() + "," +
rilCellTowerInfo.dwLocationAreaCode.ToString() + "," +
rilCellTowerInfo.dwMobileCountryCode.ToString() + "," +
"1";

LocationService service = new LocationService(postData);
string _location = service.GetLocationInfomation(postData);

这个_location就是转换出来的经纬度。

再次建议写在线程里。因为转换需要1-几秒钟的时间。

由于项目有其它功能,就不把源文件上传上来了。但其它有关的代码都已经在文章中了。

如何有人知道多基站定位的,也请您指导一下。谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: