WIFI定位
本文档介绍了wifi定位的使用方法,并通过demo_wifilocate.c举例演示
工作原理
设备扫描周围 WiFi 热点,获取它们的唯一标识BSSID和信号强度;将这些信息发给定位服务器,服务器通过结合信号强弱(强信号对应热点更近),算出设备位置。
工作流程
获取网络状态
在启动定位前,需确保设备已成功注册到网络(本地网络或漫游状态),否则无法进行后续的 WiFi 扫描和数据上传。
示例:
do{
yopen_nw_get_reg_status(0, &nw_status);
yopen_rtos_task_sleep_ms(1000);
DEMO_LBS_TRACE("==========nw_status old %d==========", nw_status.data_reg.state);
if(nw_status.data_reg.state == YOPEN_NW_REG_STATE_DENIED)
{
DEMO_LBS_TRACE("network reg denied !!!!");
}
}while(!(nw_status.data_reg.state == YOPEN_NW_REG_STATE_HOME_NETWORK || nw_status.data_reg.state == YOPEN_NW_REG_STATE_ROAMING));//当网络状态既不是本地网络也不是漫游状态时,继续循环检查
扫描热点信息
调用接口扫描周边 WiFi 热点,获取 BSSID(MAC 地址)和信号强度等关键信息,用于后续定位计算。
tick = yopen_rtos_get_system_tick();
// 调用WiFi扫描接口(wifi_config为配置参数,wifi_info用于存储扫描结果)
yopen_errcode_wifi_e ret = yopen_wifi_scan(wifi_config, &wifi_info);
yopen_trace("WiFi scan result: 0x%x, Duration: %dms", ret, yopen_rtos_get_system_tick() - tick);
if (ret != YOPEN_WIFI_SUCCESS || wifi_info.bssidNum == 0) {
yopen_trace("Scan failed or no hotspots found");
return;
}
构建请求URL
根据定位服务器要求的格式,拼接包含设备信息(如运营商代码、信号质量等)的请求 URL:
http://loc.yuge-info.com/index.php?mcc=%d&mnc=%d&lac=%d&ci=%d&csq=%d&rssi=%d&imei=%s&key=%s"
获取设备的mcc,mnc等信息用于构建请求url
yopen_nw_get_operator_name(uint8_t nSim, yopen_nw_operator_info_s *oper_info);//获取mcc
yopen_nw_get_reg_status(uint8_t nSim, yopen_nw_reg_status_info_s *reg_info);//获取lac以及ci
yopen_nw_get_csq(uint8_t nSim, unsigned char *csq);//获取csq
yopen_dev_get_imei(char *p_imei,size_t imei_len,uint8_t nSim);//获取imei
yopen_nw_get_signal_strength(uint8_t nSim, yopen_nw_signal_strength_info_s *pt_info);//获取rssi
http发送请求
将扫描到的 WiFi 热点信息(MAC 地址和信号强度)封装为 JSON 格式,作为 POST 请求的正文。
要求post内容为{"wifis":[{"macddress":"%s","signalstrength ":%d}]}
示例:
post_idx += snprintf(post_data + post_idx, sizeof(post_data) - post_idx, "{");
post_idx += snprintf(post_data + post_idx, sizeof(post_data) - post_idx, "\"wifis\":[");
for (uint32_t i = 0; i < wifi_info.bssidNum && i < WIFILOC_MAX_MINIGPS_NBRCELL_NUM; i++)
{
snprintf(temp, sizeof(temp), "%02x:%02x:%02x:%02x:%02x:%02x",
wifi_info.bssid[i][0], wifi_info.bssid[i][1],
wifi_info.bssid[i][2], wifi_info.bssid[i][3],
wifi_info.bssid[i][4], wifi_info.bssid[i][5]);
post_idx += snprintf(post_data + post_idx, sizeof(post_data) - post_idx,
"{\"macAddress\":\"%s\",\"signalstrength\":%d}",temp, cell.csq);
if (i < wifi_info.bssidNum - 1 && i < WIFILOC_MAX_MINIGPS_NBRCELL_NUM - 1) {
post_idx += snprintf(post_data + post_idx, sizeof(post_data) - post_idx, ",");
}
}
post_idx += snprintf(post_data + post_idx, sizeof(post_data) - post_idx, "]}");
构建请求URL后,通过httpConnect接口发起连接
httpConnect(clientContext, url);//连接至目标URL
连接成功后,通过httpSendRequest接口发起post请求
//配置请求参数
clientContext->timeout_s = 2;
clientContext->timeout_r = 20;
clientContext->pdpId = 1;
clientContext->saveMem = 1;
clientContext->ciphersuite[0] = 0xFFFF;
clientData->postBuf = post_data;
clientData->postBufLen = strlen(post_data);
clientData->postContentType = "application/json";
//发起post请求
httpSendRequest(clientContext, url, HTTP_POST, clientData);//发起post请求
接收返回数据
调用httpRecvResponse
接口接收服务器返回的JSON数据
示例:
httpRecvResponse(clientContext, clientData);//接受返回数据
解析JSON数据
服务器返回的响应通常是 JSON 格式的数据,需要从中提取出有用的信息,如 code
、msg
、lng
和 lat
字段的值。
以下是解析 JSON 数据的部分示例代码:
// 获取result对象
cJSON *result = cJSON_GetObjectItem(root, "result");
if (cJSON_IsObject(result)) {
// 获取result中的lng字段
cJSON *lng = cJSON_GetObjectItem(result, "lng");
if (cJSON_IsNumber(lng)) {
DEMO_LBS_TRACE("lng: %.6f\n", lng->valuedouble);
}
// 获取result中的lat字段
cJSON *lat = cJSON_GetObjectItem(result, "lat");
if (cJSON_IsNumber(lat)) {
DEMO_LBS_TRACE("lat: %.6f\n", lat->valuedouble);
}
举例演示
通过以上步骤,就可以完成基站定位的整个流程,从获取网络状态到最终解析出设备的经纬度信息。
打开 demo_wifilocate.c
,经编译运行后烧录至开发板,具体过程参考Yopen 入门篇开发入门
根据日志信息,获取到的位置经纬度为:
- 经度(lng):117.137964
- 纬度(lat):31.833135