Following Microsoft's documentation on RIL I've been able to implement a code that retrieves Cell ID, LAC, MCC, MNC and Signal Strength. Using these data and http://www.opencellid.org/ I'm able to retrieve latitude and longitude of that cell tower. The problem is that I need to implement some kind of triangulation algorithm to get a more accurate position. But before even thinking in triangulation, I'm going to need more than one tower ID to work with. How can I get them? I tried to create an array of towerIDs and populate it in a loop, while a tower id does not exist in the array then add it, but if it exists then ignore it and keep looking for another one. Obviously it did not work, once it gets one it keeps it and if I delete the object and create a new one it gets the same tower. How can I get a different one?
Thanks in advance.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace GPS_Test
{
public class CellTower
{
public int CellID { get; set; }
// LAC (Local Area Code)
public int LAC { get; set; }
// MCC (Mobile Country Code)
public int MCC { get; set; }
// MNC (Mobile Network Code)
public int MNC { get; set; }
// Received signal strength
public int signalStrength { get; set; }
// Base Station ID
//public int baseStationID { get; set; }
}
public class RIL
{
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);
[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", EntryPoint = "RIL_GetCellTowerInfo")]
public static extern IntPtr RIL_GetCellTowerInfo(IntPtr hril);
[DllImport("ril.dll")]
public static extern IntPtr RIL_Deinitialize(IntPtr hril);
[DllImport("ril.dll", EntryPoint = "RIL_GetSignalQuality")]
public static extern IntPtr RIL_GetSignalQuality(IntPtr hRil);
[StructLayout(LayoutKind.Explicit)]
internal 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(28)]
public uint dwBaseStationID;
[FieldOffset(36)]
public uint dwRxLevel;
}
[StructLayout(LayoutKind.Explicit)]
internal class RILSIGNALQUALITY
{
[FieldOffset(0)]
uint dwSize;
[FieldOffset(4)]
uint dwParams;
[FieldOffset(8)]
public int nSignalStrength;
[FieldOffset(12)]
public uint nMinSignalStrength;
[FieldOffset(16)]
public uint nMaxSignalStrength;
[FieldOffset(20)]
public uint dwBitErrorRate;
[FieldOffset(24)]
public uint nLowSignalStrength;
[FieldOffset(28)]
public uint nHighSignalStrength;
}
}
public class CellTowerInfo
{
private static AutoResetEvent dataReceived = new AutoResetEvent(false);
private static AutoResetEvent whSignalQuality = new AutoResetEvent(false);
private static RIL.RILCELLTOWERINFO towerInfo;
private static RIL.RILSIGNALQUALITY signalQuality;
public static CellTower GetCellTowerInfo()
{
IntPtr hRil = IntPtr.Zero;
IntPtr hResult = IntPtr.Zero;
hResult = RIL.RIL_Initialize(1,
new RIL.RILRESULTCALLBACK(CellTowerData),
null, 0, 0, out hRil);
if (hResult != IntPtr.Zero)
return null;
hResult = RIL.RIL_GetCellTowerInfo(hRil);
dataReceived.WaitOne();
RIL.RIL_Deinitialize(hRil);
CellTower ct = new CellTower();
ct.LAC = (int)towerInfo.dwLocationAreaCode;
ct.MCC = (int)towerInfo.dwMobileCountryCode;
ct.MNC = (int)towerInfo.dwMobileNetworkCode;
ct.CellID = (int)towerInfo.dwCellID;
ct.signalStrength = GetSignalQuality();
return ct;
}
public static int GetSignalQuality()
{
IntPtr hRes = IntPtr.Zero;
IntPtr hSignalQ = IntPtr.Zero;
hRes = RIL.RIL_Initialize(1, new RIL.RILRESULTCALLBACK(SignalQualityCallback),
null, 0, 0, out hSignalQ);
hRes = RIL.RIL_GetSignalQuality(hSignalQ);
whSignalQuality.WaitOne();
RIL.RIL_Deinitialize(hSignalQ);
return signalQuality.nSignalStrength;
}
private static void CellTowerData(uint dwCode, IntPtr hrCmdID,
IntPtr lpData, uint cbData, uint dwPara)
{
towerInfo = new RIL.RILCELLTOWERINFO();
Marshal.PtrToStructure(lpData, (object)towerInfo);
dataReceived.Set();
}
private static void SignalQualityCallback(uint dwCode, IntPtr hrCmdID,
IntPtr lpData, uint cbData, uint dwPara)
{
signalQuality = new RIL.RILSIGNALQUALITY();
Marshal.PtrToStructure(lpData, (object)signalQuality);
whSignalQuality.Set();
}
}
}