在做手机定位应用软件,有两种方法可以实行定位:
1.利用基站定位,通过手机获取基站信息,再根据该信息获取经纬度;
2.利用GPS定位,直接获取经纬度信息。
利弊:
1.基站定位精确度低,误差范围估计500米以内(这种情况还是在大城市下的,如果是小城市,估计误差更大),但是基站定位可以实现处处定位,即不会因为建筑物等原因而无法获取基站信息。
2.GPS定位精确度高,误差范围估计10米以内,但是需要在空旷的地方,如果周围建筑物多,或者在室内,没法获取GPS信息。
通常用定位这两种方法都采用,也会增加第三种WIFI定位或者小区定位,这是后话。
在windows mobile下获得CELLID、LAC的途径有两条:利用串口发送AT指令或是利用RIL来获取。RIL(Radio Interface Layer)是微软自己开发的一个库,它的程序有固有的特点,在获取CELLID上,它其实是对第一种方法的封装,两者本质是一样的。但要注意是:串口一旦打开,就难以关闭,除非重启机器(可能涉及到底层的中断),另外并不是所有的设备都可以取到CELLID。
本文章是利用COM口来获取CELLID,并不保证所有的设备都支持。
测试平台:
VS2005 + WM 6.0
开发语言:
C++
正文:
定义基站信息结构体:
复制到剪贴板 C/C++代码
typedef struct
{
char CountryCode[12];
char AreaCode[4];
char NetworkCode[4];
char CellID[4];
} TCREG_DATA;
获取基站信息:
复制到剪贴板 C/C++代码
void Get_Cellid(void)
{
char m_sTemp[12] = {0};
strcat(m_sTemp,"COM");
for(int i = 9; i > 0; -- i)
{
char ch1;
_itoa(i,&ch1,10);
strcat(m_sTemp,&ch1);
strcat(m_sTemp,":");
TCREG_DATA* pData = (TCREG_DATA*)GetCREG(m_sTemp);
if(!pData)
continue;
char szNum1[8] = {0};
char szNum2[8] = {0};
strcpy(szNum1,pData->AreaCode);
strcpy(szNum2,pData->CellID); int iLac = (int)strtol(szNum1,NULL,16);
int iId = (int)strtol(szNum2,NULL,16);
if (iLac && iId)
{
sprintf(m_sCell.LAC,"%06d", iLac );
sprintf(m_sCell.ID,"%06d", iId );
break;
}
}
}
获取串口:
复制到剪贴板 C/C++代码
char* GetCREG( char * comPort )
{
HANDLE hCom;
int bufpos;
DCB dcb;
COMMTIMEOUTS to;
DWORD nWritten;
DWORD event;
DWORD nRead;
static char outbuf[20], buf[256];
BYTE comdevcmd[2]= {0x84, 0x00};
WCHAR m_sCom[12] = {0};
mbstowcs(m_sCom,comPort,strlen(comPort));
hCom= CreateFile( m_sCom ,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
if (hCom==NULL || hCom==INVALID_HANDLE_VALUE)
{
hCom= NULL;
return NULL;
}
if (!GetCommState(hCom, &dcb))
{
return "ERROR:GetCommState Failed";
}
dcb.BaudRate= CBR_115200;
dcb.ByteSize= 8;
dcb.fParity= false;
dcb.StopBits= ONESTOPBIT;
if (!SetCommState(hCom, &dcb))
{
return "ERROR:SetCommState Failed";
}
EscapeCommFunction(hCom, SETDTR);
EscapeCommFunction(hCom, SETRTS);
GetCommTimeouts(hCom, &to);
to.ReadIntervalTimeout= 0;
to.ReadTotalTimeoutConstant= 200;
to.ReadTotalTimeoutMultiplier= 0;
to.WriteTotalTimeoutConstant= 20000;
to.WriteTotalTimeoutMultiplier= 0;
SetCommTimeouts(hCom, &to);
if (!SetCommMask(hCom, EV_RXCHAR))
{
return "-8";
}
DWORD rildevresult=0,nReturned=0;
if (!DeviceIoControl (hCom,0xAAAA5679L, comdevcmd, sizeof(comdevcmd),0,0,0,0))
{
return "-9";
}
bufpos = 0;
strcpy(outbuf,"AT+creg=2 ");
if (!WriteFile(hCom, outbuf, 10, &nWritten, NULL))
{
return "-10";
}
if (nWritten != 10)
{
return "-11";
}
if (!WaitCommEvent(hCom, &event, NULL))
{
return "-12";
}
while(1)
{
if (!ReadFile(hCom, buf+bufpos, 256 - bufpos, &nRead, NULL))
{
return "-13";
}
if (nRead == 0)
break;
bufpos += nRead;
if (bufpos >= 256)
break;
}
strcpy(outbuf,"AT+creg? ");
if (!WriteFile(hCom, outbuf, 9, &nWritten, NULL))
{
return "-14";
}
if (nWritten != 9)
{
return "-15";
}
if (!WaitCommEvent(hCom, &event, NULL))
{
return "-16";
}
while(1)
{
if (!ReadFile(hCom, buf+bufpos, 256 - bufpos, &nRead, NULL))
{
return "-17";
}
if (nRead == 0)
break;
bufpos += nRead;
if (bufpos >= 256)
break;
}
puts(buf);
rildevresult = 0;
if (!EscapeCommFunction(hCom, CLRDTR))
{
return "-4";
}
if (hCom!=NULL)
{
CloseHandle(hCom);
hCom= NULL;
}
char* cregResponse = strpbrk( buf, "CREG" );
return cregResponse;
}
总结:
通过获取基站信息,手机可以实现定位,这对于没有GPS设备的手机来说是一个不错的想法。