windows获取wifi的bssid(mac地址)进行wifi定位

wifi定位:顾名思义就是利用wifi来进行定位的功能。其原理是通过带有gps定位功能的设备接入wifi后,讲wifi的bssid信息连同gps定位结果同时上传到服务器,当有其他设备再次连接这个wifi时,就能大致的推断出他的位置。

在win8.1后已经提供接口可直接获取设备的经定位信息,当然xp、win7呢?显然不支持。由此我们就想到有没有办法让他们也能够定位呢?答案是肯定的!

一、首先你的计算机要支持wifi,不然就扯淡了。看看如何获取wifi的bssid吧。

#include 

typedef std::string AString;
typedef std::vector AStringVector;

// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib,"netapi32")

AStringVector GetBSSIDs()
{
	AStringVector vecBSSIDs;

	// Declare and initialize variables.

	HANDLE hClient = NULL;
	DWORD dwMaxClient = 2;      //    
	DWORD dwCurVersion = 0;
	DWORD dwResult = 0;
	DWORD dwRetVal = 0;
	int iRet = 0;

	WCHAR GuidString[39] = { 0 };

	unsigned int i, j, k;

	/* variables used for WlanEnumInterfaces  */

	PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
	PWLAN_INTERFACE_INFO pIfInfo = NULL;

	PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
	PWLAN_AVAILABLE_NETWORK pBssEntry = NULL;

	int iRSSI = 0;

	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
	if (dwResult == ERROR_SUCCESS)
	{
		dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
		if (dwResult != ERROR_SUCCESS) 
		{
			LOG("WlanEnumInterfaces failed with error: %u\n", dwResult);
			// You can use FormatMessage here to find out why the function failed
		}
		else 
		{
			for (i = 0; i < (int)pIfList->dwNumberOfItems; i++) {
				pIfInfo = (WLAN_INTERFACE_INFO *)&pIfList->InterfaceInfo[i];

				dwResult = WlanGetAvailableNetworkList(hClient,
					&pIfInfo->InterfaceGuid, 0, NULL, &pBssList);

				if (dwResult != ERROR_SUCCESS) {
					LOG("WlanGetAvailableNetworkList failed with error: %u\n", dwResult);
					dwRetVal = 1;
					// You can use FormatMessage to find out why the function failed
				}
				else 
				{
					for (j = 0; j < pBssList->dwNumberOfItems; j++)
					{
						pBssEntry = (WLAN_AVAILABLE_NETWORK *)& pBssList->Network[j];

						PWLAN_BSS_LIST ppWlanBssList;

						DWORD dwResult2 = WlanGetNetworkBssList(hClient, &pIfInfo->InterfaceGuid,
							&pBssEntry->dot11Ssid,
							pBssEntry->dot11BssType,
							pBssEntry->bSecurityEnabled,
							NULL,
							&ppWlanBssList);

						if (dwResult2 == ERROR_SUCCESS)
						{
							for (int z = 0; z < ppWlanBssList->dwNumberOfItems; z++)
							{
								WLAN_BSS_ENTRY bssEntry = ppWlanBssList->wlanBssEntries[z];

								AString bssid = Printf("%02X:%02X:%02X:%02X:%02X:%02X",
									bssEntry.dot11Bssid[0],
									bssEntry.dot11Bssid[1],
									bssEntry.dot11Bssid[2],
									bssEntry.dot11Bssid[3],
									bssEntry.dot11Bssid[4],
									bssEntry.dot11Bssid[5]);

								vecBSSIDs.push_back(bssid);
							}
						}
					}
				}
			}

		}
	}
	else
	{
		LOG("WlanOpenHandle failed with error: %u\n", dwResult);
		// You can use FormatMessage here to find out why the function failed
	}

	if (pBssList != NULL) {
		WlanFreeMemory(pBssList);
		pBssList = NULL;
	}

	if (pIfList != NULL) {
		WlanFreeMemory(pIfList);
		pIfList = NULL;
	}

	return vecBSSIDs;
}

二、看看如何使用这些bssid吧。

我们以百度的wifi定位接口为例,当然谷歌、新浪等等都有类似的接口,甚至还有收费的。

#include 
#include 

AString url = "http://apis.baidu.com/lbs_repository/wifi/query?coord=wgs84&mac=";


size_t write_data(void* buffer, size_t size, size_t nmemb, void *stream)
{
	AString *fptr = (AString*)stream;
	fptr->append((char*)buffer);

	return size*nmemb;
}

void getGeoInfo(const AString &url, const AString &bssid,const AString &appkey)
{
	AString postUrl = url + bssid;


	CURL *curl;
	CURLcode res;
	AString *strRet = new AString;

	struct curl_slist *headers = NULL; /* init to NULL is important */
	headers = curl_slist_append(headers, AString("apikey: "+ m_strAppKey).c_str());

	curl = curl_easy_init();
	curl_easy_setopt(curl, CURLOPT_URL, postUrl.c_str());
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, strRet);
	curl_easy_setopt(curl, CURLOPT_HEADER, 1);


	res = curl_easy_perform(curl);

	curl_easy_cleanup(curl);

	if (res != CURLE_OK)
	{
		switch (res)
		{
		case CURLE_UNSUPPORTED_PROTOCOL:
			fprintf(stderr, "不支持的协议,由URL的头部指定\n");
		case CURLE_COULDNT_CONNECT:
			fprintf(stderr, "不能连接到remote主机或者代理\n");
		case CURLE_HTTP_RETURNED_ERROR:
			fprintf(stderr, "http返回错误\n");
		case CURLE_READ_ERROR:
			fprintf(stderr, "读本地文件错误\n");
		default:
			fprintf(stderr, "返回值:%d\n", res);
		}
	}

	AString strResult = *strRet;

	delete strRet;

	size_t end_index = strResult.find("\r\n\r\n");	//所以也不需要计算偏移来提高搜索速度
	if (end_index != std::string::npos)
	{
		size_t length = strResult.length();
		AString strBody = strResult.substr(end_index + 4, length - end_index - 4);
		AString strHeader = strResult.substr(0, end_index + 4);


		//正常HTTP头中 第9-11位为HTTP状态码
		size_t lenght = strHeader.length();

		int _http_code = -1;
		if (lenght >= 12)
		{
			std::string http_code = strHeader.substr(9, 3);
			try
			{
				_http_code = atoi(http_code.c_str());
			}
			catch (...)
			{
				_http_code = -1;
			}
		}

		if (_http_code == 200)
		{
			Json::Reader reader;
			Json::Value root;
			if (reader.parse(strBody, root))  // reader将Json字符串解析到root,root将包含Json里所有子元素  
			{
				UInt32 errcode = root["errcode"].asUInt();
				UInt32 radius = atoi(root["radius"].asString().c_str());
				double lat = atof(root["lat"].asString().c_str());
				double lon = atof(root["lon"].asString().c_str());
				AString address = root["address"].asString();

				if (errcode == 0)
				{
					//定位成功
				}
			}
		}
	}
}

好了,到此为止基本上已经讲完了。wifi定位不能作为最终的结果,毕竟数据库可能不完整或者不实时,定位的结果存在偏差也是很正常的。我们一般还要采取其他方式进行混合定位,比如:基站+wifi+ip+gps等等。

再次希望对需要的人有帮助,谢谢。



你可能感兴趣的:(wifi定位,bssid)