|
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using DeepCast.Services;
using PhoneVoyage.Services;
namespace DeepCast.Location
{
/// <summary>
/// Location provider to get cell tower details from the Windows Mobile Radio Interface layer
/// </summary>
internal class CellTowerLocationProvider : ILocationProvider
{
#region pInvoke
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);
public static IntPtr hRil;
[StructLayout(LayoutKind.Explicit)]
class RILCELLTOWERINFO
{
[FieldOffset(0)]
uint dwSize;
[FieldOffset(4)]
uint dwParams;
[FieldOffset(8)]
public uint dwMobileCountryCode;
[FieldOffset(12)]
public uint dwMobileNetworkCode;
[FieldOffset(16)]
public uint dwLocationAreaCode;
[FieldOffset(20)]
public uint dwCellID;
[FieldOffset(24)]
uint dwBaseStationID;
[FieldOffset(28)]
uint dwBroadcastControlChannel;
[FieldOffset(32)]
uint dwRxLevel;
[FieldOffset(36)]
uint dwRxLevelFull;
[FieldOffset(40)]
uint dwRxLevelSub;
[FieldOffset(44)]
uint dwRxQuality;
[FieldOffset(48)]
uint dwRxQualityFull;
[FieldOffset(52)]
uint dwRxQualitySub;
/* More minor interesting fields below */
}
[DllImport("ril.dll")]
private static extern IntPtr RIL_Initialize(uint dwIndex, RILRESULTCALLBACK pfnResult, RILNOTIFYCALLBACK pfnNotify, uint dwNotificationClasses, uint dwParam, out IntPtr lphRil);
[DllImport("ril.dll", EntryPoint = "RIL_GetCellTowerInfo")]
private static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);
[DllImport("ril.dll", EntryPoint = "RIL_Hangup")]
private static extern IntPtr RIL_Hangup(IntPtr hRil);
[DllImport("ril.dll")]
private static extern IntPtr RIL_Deinitialize(IntPtr hRil);
#endregion
private static RILCELLTOWERINFO _towerDetails;
private static AutoResetEvent waithandle = new AutoResetEvent(false);
private System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
private CellTower _currentTower;
/// <summary>
/// Initializes a new instance of the <see cref="CellTowerLocationProvider"/> class.
/// </summary>
public CellTowerLocationProvider()
{
_timer.Interval = 5000; // 5 seconds
_timer.Tick += new EventHandler(_timer_Tick);
}
#region ILocationProvider Members
/// <summary>
/// Starts the timer.
/// </summary>
public void Start()
{
_timer.Enabled = true;
}
/// <summary>
/// Stops the timer.
/// </summary>
public void Stop()
{
_timer.Enabled = false;
}
/// <summary>
/// Gets the current location.
/// </summary>
/// <value>The current location.</value>
public GeoLocation CurrentLocation
{
get
{
try
{
// If google didn't resolve location, try OpenCellID.org
OpenCellIdService cellService = new OpenCellIdService();
GeoLocation location = cellService.GetCellTowerLocation(_currentTower);
if (location == GeoLocation.Empty)
{
// Try google first; their dataase seems to be the most comprehensive
location = GoogleMapsCellService.GetLocation(_currentTower);
}
return location;
}
catch // Not much else can be done
{
return GeoLocation.Empty;
}
}
}
#endregion
/// <summary>
/// Handles the Tick event of the _timer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void _timer_Tick(object sender, EventArgs e)
{
// Get the current cell tower every time the timer ticks
_currentTower = GetCellTowerInfo();
}
/// <summary>
/// Gets the cell tower info from the.
/// </summary>
/// <returns></returns>
public static CellTower GetCellTowerInfo()
{
IntPtr radioInterfaceLayerHandle = IntPtr.Zero;
IntPtr radioResponseHandle = IntPtr.Zero;
// Initialize the radio layer with a result callback parameter.
radioResponseHandle = RIL_Initialize(1, new RILRESULTCALLBACK(CellDataCallback), null, 0, 0, out radioInterfaceLayerHandle);
// The initialize API call will always return 0 if initialization is successful.
if (radioResponseHandle != IntPtr.Zero)
{
return null;
}
// Qusery for the current tower data.
radioResponseHandle = RIL_GetCellTowerInfo(radioInterfaceLayerHandle);
// Wait for cell tower info to be returned since RIL_GetCellTowerInfo invokes the
// callback method asynchronously.
waithandle.WaitOne();
// Release the RIL handle
RIL_Deinitialize(radioInterfaceLayerHandle);
// Convert the raw tower data structre data into a CellTower object
return new CellTower()
{
TowerId = Convert.ToInt32(_towerDetails.dwCellID),
LocationAreaCode = Convert.ToInt32(_towerDetails.dwLocationAreaCode),
MobileCountryCode = Convert.ToInt32(_towerDetails.dwMobileCountryCode),
MobileNetworkCode = Convert.ToInt32(_towerDetails.dwMobileNetworkCode),
};
}
/// <summary>
/// Responds to the RIL GetCellTowerInfo callback when data is available.
/// </summary>
public static void CellDataCallback(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam)
{
// Refresh the current tower details
_towerDetails = new RILCELLTOWERINFO();
// Copy result returned from RIL into structure
Marshal.PtrToStructure(lpData, _towerDetails);
// notify caller function that we have a result
waithandle.Set();
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I'm the founder of PageLabs, a web-based performance and SEO optimization site.
Give your site a boost in performance, even take a free speed test!
http://www.pagelabs.com