Skip to content

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 格式的数据,需要从中提取出有用的信息,如 codemsglnglat 字段的值。

以下是解析 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