Thread
Print

Location-Based Services Using CellID in Windows Mobile

Location-Based Services Using CellID in Windows Mobile

Recently we have tried to get the cellID from mobile phones. and found some userful links about how to get CellID in Windows Mobile
get CellID in Windows Mobile and Poor man's GPS
the cell ID has following format

CellID ¨C Location Area Code ¨C Mobile Country Code

for example , 54464-39502-505

and actually google latitude use such information to get the latitude/longitude based on the cell ID.

here's code sample to get such information from a scecret google Map API written by "Neil Young" (neil.young@freenet.de)
Copy to clipboard
Code:
using System;
using System.IO;
using System.Net;

//---Based on code written by "Neil Young" (neil.young@freenet.de)
//---Source: http://maps.alphadex.de/datafiles/fct0e1b11782832f02.cs
namespace GoogleMaps
{
    class GMM
    {
        static byte[] PostData(int MCC, int MNC, int LAC, int CID,
                               bool shortCID)
        {
            /* The shortCID parameter follows heuristic experiences:
             * Sometimes UMTS CIDs are build up from the original GSM CID (lower 4 hex digits)
             * and the RNC-ID left shifted into the upper 4 digits.
             */
            byte[] pd = new byte[] {
                0x00, 0x0e,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00,
                0x00, 0x00,
                0x00, 0x00,

                0x1b,
                0x00, 0x00, 0x00, 0x00, // Offset 0x11
                0x00, 0x00, 0x00, 0x00, // Offset 0x15
                0x00, 0x00, 0x00, 0x00, // Offset 0x19
                0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, // Offset 0x1f
                0x00, 0x00, 0x00, 0x00, // Offset 0x23
                0x00, 0x00, 0x00, 0x00, // Offset 0x27
                0x00, 0x00, 0x00, 0x00, // Offset 0x2b
                0xff, 0xff, 0xff, 0xff,
                0x00, 0x00, 0x00, 0x00
            };

            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
                                    GSM CID part */

            if ((Int64)CID > 65536) /* GSM: 4 hex digits, UTMS: 6 hex
                                    digits */
                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;
        }

        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)
            {
                return string.Empty;
            }
        }
    }
}

TOP

RIL interface on windows mobile

On Windows mobile , call RIL interface to get the cell ID
Copy to clipboard
Code:
using System;
using System.Threading;
using System.Runtime.InteropServices;

namespace RIL
{
    public class RIL
    {
        // string used to store the CellID string
        private static string celltowerinfo = "";

        /*
         * Uses RIL to get CellID from the phone.
         */
        public static string GetCellTowerInfo()
        {
            // initialise handles
            IntPtr hRil = IntPtr.Zero;
            IntPtr hRes = IntPtr.Zero;

            // initialise result
            celltowerinfo = "";

            // initialise RIL
            hRes = RIL_Initialize(1,                                        // RIL port 1
                                  new RILRESULTCALLBACK(rilResultCallback), // function to call with result
                                  null,                                     // function to call with notify
                                  0,                                        // classes of notification to enable
                                  0,                                        // RIL parameters
                                  out hRil);                                // RIL handle returned

            if (hRes != IntPtr.Zero)
            {
                return "Failed to initialize RIL";
            }

            // initialised successfully

            // use RIL to get cell tower info with the RIL handle just created
            hRes = RIL_GetCellTowerInfo(hRil);

            // wait for cell tower info to be returned
            waithandle.WaitOne();

            // finished - release the RIL handle
            RIL_Deinitialize(hRil);

            // return the result from GetCellTowerInfo
            return celltowerinfo;
        }


        // event used to notify user function that a response has
        //  been received from RIL
        private static AutoResetEvent waithandle = new AutoResetEvent(false);


        public static void rilResultCallback(uint dwCode,
                                             IntPtr hrCmdID,
                                             IntPtr lpData,
                                             uint cbData,
                                             uint dwParam)
        {
            // create empty structure to store cell tower info in
            RILCELLTOWERINFO rilCellTowerInfo = new RILCELLTOWERINFO();

            // copy result returned from RIL into structure
            Marshal.PtrToStructure(lpData, rilCellTowerInfo);

            // get the bits out of the RIL cell tower response that we want
            celltowerinfo = rilCellTowerInfo.dwCellID + "-" +
                            rilCellTowerInfo.dwLocationAreaCode + "-" +
                            rilCellTowerInfo.dwMobileCountryCode;

            // notify caller function that we have a result
            waithandle.Set();
        }



        // -------------------------------------------------------------------
        //  RIL function definitions
        // -------------------------------------------------------------------

        /*
         * Function definition converted from the definition
         *  RILRESULTCALLBACK from MSDN:
         *
         * http://msdn2.microsoft.com/en-us/library/aa920069.aspx
         */
        public delegate void RILRESULTCALLBACK(uint dwCode,
                                               IntPtr hrCmdID,
                                               IntPtr lpData,
                                               uint cbData,
                                               uint dwParam);


        /*
         * Function definition converted from the definition
         *  RILNOTIFYCALLBACK from MSDN:
         *
         * http://msdn2.microsoft.com/en-us/library/aa922465.aspx
         */
        public delegate void RILNOTIFYCALLBACK(uint dwCode,
                                               IntPtr lpData,
                                               uint cbData,
                                               uint dwParam);

        /*
         * Class definition converted from the struct definition
         *  RILCELLTOWERINFO from MSDN:
         *
         * http://msdn2.microsoft.com/en-us/library/aa921533.aspx
         */
        public class RILCELLTOWERINFO
        {
            public uint cbSize;
            public uint dwParams;
            public uint dwMobileCountryCode;
            public uint dwMobileNetworkCode;
            public uint dwLocationAreaCode;
            public uint dwCellID;
            public uint dwBaseStationID;
            public uint dwBroadcastControlChannel;
            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;
            public uint dwGPRSBaseStationID;
            public uint dwNumBCCH;
        }

        // -------------------------------------------------------------------
        //  RIL DLL functions
        // -------------------------------------------------------------------

        /* Definition from: http://msdn2.microsoft.com/en-us/library/aa919106.aspx */
        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Initialize(uint dwIndex,
                                                    RILRESULTCALLBACK pfnResult,
                                                    RILNOTIFYCALLBACK pfnNotify,
                                                    uint dwNotificationClasses,
                                                    uint dwParam,
                                                    out IntPtr lphRil);

        /* Definition from: http://msdn2.microsoft.com/en-us/library/aa923065.aspx */
        [DllImport("ril.dll")]
        private static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);

        /* Definition from: http://msdn2.microsoft.com/en-us/library/aa919624.aspx */
        [DllImport("ril.dll")]
        private static extern IntPtr RIL_Deinitialize(IntPtr hRil);
    }
}

TOP

On Nokia N95

form = new Form("Getting Cell ID");
S40_cell_id = System.getProperty("Cell-ID");
S60_cell_id = System.getProperty("com.nokia.mid.cellid");
s60_new=System.getProperty("com.nokia.mid.networkid");

form.append("Series 40 devices: " S40_cell_id "\n");
form.append("S60 devices: " S60_cell_id"\n");
form.append("Network id "+s60_new);

TOP

some sample Cell ID

MMCMNCLACCID LatitudeLongitude
50516030161652 -31.985307115.93802
50516030162234 -31.97968115.950289
50516030161631 -31.99400212115.955555
5051308002143 -31.989281115.947165
505130800351 -31.993085115.929197
5051308163653 -31.986078115.942871
AustraliaTelstraLocation Area CodeCell ID

Attachment

Welshpool_WA.PNG (741.21 KB)

22-5-2009 16:13

Welshpool_WA.PNG

TOP

Motorola A780

String cellID = System.getProperty("phone.cid");

TOP

Cell ID By reneheuven

Cell ID By reneheuven
There is different ways to retrieve the location of a mobile phone. We are currently evaluating some options. Each of the options seems to have quite a lot of drawbacks. To support a large number of mobile phones it would be required to write a J2ME application.

The Cell ID can be retrieved if the phone has no GPS, but supports the JSR-179 location API.  This new J2ME optional package, however, is only implemented on the most recent mobile phones.

As an alternative we could read a system property on the mobile phone using a J2ME application. On Nokia Series 40 phones this requires operator signing which will be difficult to achieve.

In our quest to read the Cell ID we also ran into an interesting option by getting the Cell ID through the SIM card. For J2ME applications this seems to be possible through JSR-177. This allows you to send APDU commands to the SIM card. Also in this case there only a few phones which support JSR-177.

Interestingly we also discovered Turbo SIM and Rebel SIM. Turbo SIM is an additional SIM card which you can insert in your phone. It is possible to write applications which are stored on the Turbo SIM card and to interact with both the phone and the operator SIM card. We purchased an evaluation package from Bladox. So you expect some more findings from Inmote about this technology in the next months.

TOP

Thread