2023-2-9 17:56:51 [显示全部楼层]
3320浏览
查看: 3320|回复: 0

[入门] Arduino ESP32 WiFi定位

[复制链接]
本帖最后由 Fbuilke 于 2023-2-9 18:02 编辑

       最近项目用到定位,但是又不想重新画PCB,因此打算做一个仅通过WIFI来定位的小硬件,但找了很多家,比如高德、百度这些都没有面向个人开发者的硬件网络定位接口,兜兜转转还是找到了一家做物联网全域定位的公司叫维智科技,他们的物联网定位平台是这个https://lotboard.newayz.com/,个人开发者注册的话配额还是挺充裕的,特别是每日100次请求,很适合我们这些做智能硬件的。       根据开发手册体验了一下,只需要最少4个WiFi信息或者通过定位模块解析的坐标就可以返回详细的信息了,返回的数据是这样的。
  1. {
  2.     "id": "38efe26e-************************",
  3.     "asset": "d1c09200-9254-11ed-*******************",
  4.     "location": {
  5.         "timestamp": 1673513233302,
  6.         "address": {
  7.             "name": "湖北省武汉市*************************************",
  8.             "context": [
  9.                 {
  10.                     "type": "Country",
  11.                     "name": "中国",
  12.                     "code": "CN"
  13.                 },
  14.                 {
  15.                     "type": "Province",
  16.                     "name": "湖北省",
  17.                     "code": "420000"
  18.                 },
  19.                 {
  20.                     "type": "City",
  21.                     "name": "武汉市",
  22.                     "code": "420100"
  23.                 },
  24.                 {
  25.                     "type": "District",
  26.                     "name": "****",
  27.                     "code": "42****"
  28.                 },
  29.                 {
  30.                     "type": "Township",
  31.                     "name": "****",
  32.                     "code": "42****"
  33.                 },
  34.                 {
  35.                     "type": "Road",
  36.                     "name": "****"
  37.                 },
  38.                 {
  39.                     "type": "Building",
  40.                     "name": "*********"
  41.                 },
  42.                 {
  43.                     "type": "Floor",
  44.                     "name": "*********"
  45.                 }
  46.             ],
  47.             "level": 14
  48.         },
  49.         "place": {
  50.             "type": "Food",
  51.             "name": "***********",
  52.             "categories": [
  53.                 {
  54.                     "id": 30200,
  55.                     "name": "*****"
  56.                 }
  57.             ],
  58.             "distance": {
  59.                 "line": 15.863497
  60.             }
  61.         },
  62.         "position": {
  63.             "timestamp": 1673513234166,
  64.             "source": "wifi",
  65.             "point": {
  66.                 "longitude": 114.4*******,
  67.                 "latitude": 30.5******
  68.             },
  69.             "spatialReference": "gcj02",
  70.             "accuracy": 29
  71.         }
  72.     }
  73. }
复制代码


可以看到还是挺详细的,配合第三方json库直接就可以解析得到当前地址和坐标了,对于无定位模块的设备来说简直是个福音,这样一下子能做的事情就变得多起来了,话不多说就拿这个平台做个定位硬件出来玩玩。
======================================================================================
这个平台的注册和设备注册我另外一个帖子已经写了,这里就不写了。https://blog.csdn.net/m0_50846041/article/details/128792973
======================================================================================
我手上的话就是有一块ESP32-S2,如下图:
Arduino ESP32 WiFi定位图1
因为全程不需要其它引脚所以其它就不介绍了,直接开始。
整个流程就是:
Arduino ESP32 WiFi定位图2
可以看到还是非常简单的,首先引入头文件
  1. #include <WiFi.h>
复制代码

接着在setup()中添加WiFi初始化和连接函数
  1. void setup() {
  2.   Serial.begin(115200);
  3.   WiFi.mode(WIFI_STA);
  4.   WiFi.begin(id,psw);
  5.   while(WiFi.status()!=WL_CONNECTED){   
  6.     delay(500);
  7.     Serial.println("正在连接...");
  8.   }
  9.   Serial.println("连接成功!");   
  10.   delay(100);
  11.   Serial.println("Setup done");
  12. }
复制代码

因为需要上传各个扫描到的WiFi 信息,所以我们定义一个结构体来装
  1. typedef struct ap_info
  2. {
  3.   unsigned char count;
  4.   String mac;
  5.   signed char rssi;
  6. }apinfo;
复制代码

然后在最前面定义一个新函数用来控制WiFi扫描并赋值到刚刚创建的结构体上,也可以在最后面定义但是要声明。为了方便所以写前面,但代码多还是要写后面为妙。

  1. void wifi_scan()
  2. {
  3.   int n = WiFi.scanNetworks();
  4.   ApInfo.count =n;
  5.   Serial.println("scan done");
  6.   if (n == 0) {
  7.     Serial.println("no networks found");
  8.   } else {
  9.     Serial.print(n);
  10.     Serial.println(" networks found");
  11.     for (int i = 0; i < n; ++i) {
  12.       ApInfo.rssi = WiFi.RSSI(i);
  13.       ApInfo.mac = WiFi.BSSIDstr(i);
  14.       delay(10);
  15.     }
  16.   }
  17. }
复制代码
接下来就是进行封装Json了,首先引入头文件和初始化封装和解析用到的部分,之所以设置这么大是因为有些地方WiFi较多如果设置很小会导致上传不全,接收也是一样的道理。
  1. #include <ArduinoJson.h>
  2. DynamicJsonDocument doc(8192);
  3. DynamicJsonDocument rep(4096);
复制代码

如果报错的话需要去下载,期间可能会因为网络波动多次失败,实在不行就科学上网或者本地安装,这个教程很多就不叙述了。
Arduino ESP32 WiFi定位图3
定义一个Json封装函数用来构建post请求体,这个请求体的格式可以参考全域定位平台的API手册或者根据我下面这个格式去构建:
  1. {
  2.     "timestamp": 1670987434289,
  3.     "id": "1675840238995-****************",
  4.     "asset": {
  5.         "id": "ea32ce50-9323-****************",
  6.         "manufacturer": "esp32-s2"
  7.     },
  8.     "location": {
  9.         "timestamp": 1670987434289,
  10.         "wifis": [
  11.             {
  12.                 "macAddress": "9E:2B:A6:89:40:D2",
  13.                 "signalStrength": -34
  14.             },
  15.             {
  16.                 "macAddress": "9E:2B:A6:99:40:D2",
  17.                 "signalStrength": -34
  18.             },
  19.             {
  20.                 "macAddress": "9E:2B:A6:A9:40:D2",
  21.                 "signalStrength": -34
  22.             },
  23.             {
  24.                 "macAddress": "40:67:9B:AD:12:5E",
  25.                 "signalStrength": -41
  26.             }
  27.         ]
  28.     }
  29. }
复制代码

arduino这个json库跟python一样操作简单,用惯了CJson库的这个简直是福音。
  1. String JsonSerialization()
  2. {
  3.   String message;
  4.   doc["timestamp"] = tmp_ll;
  5.   doc["id"] = "1675840238995-****************";
  6.   doc["asset"]["id"] = "ea32ce50-9323-****************";
  7.   doc["asset"]["manufacturer"] = "esp32-s2";
  8.   doc["location"]["timestamp"] = tmp_ll;
  9.   for(int i = 0;i < ApInfo.count;i++)
  10.   {
  11.     doc["location"]["wifis"][i]["macAddress"] = WiFi.BSSIDstr(i);
  12.     doc["location"]["wifis"][i]["signalStrength"] = WiFi.RSSI(i);
  13.   }
  14.   serializeJson(doc, message);  // 序列化JSON数据并导出字符串
  15.   return message;
  16. }
复制代码

完成上述后,就可以开始写请求部分了,首先需要引入头文件
  1. #include <HTTPClient.h>
复制代码

ESP32的httpclient是这个
Arduino ESP32 WiFi定位图4
然后就是写请求,这部分还是很简单的,几行代码搞定
  1. void get_location(String postMessage)
  2. {
  3.   HTTPClient http;
  4.   http.begin("https://api.newayz.com/location/hub/v1/track_points?access_key=***********");      
  5.   http.addHeader("Content-Type", "application/json");
  6.   http.addHeader("Host", "api.newayz.com");
  7.   http.addHeader("Connection", "keep-alive");
  8.   int httpCode = http.POST(postMessage);
  9.   String payload = http.getString();                                    
  10.   Serial.println(httpCode);   
  11.   PraseJson(payload);
  12.   http.end();
  13. }
复制代码
完成上述后,就是用相同的方式去解析请求回调的数据
  1. void PraseJson(String json)
  2. {
  3.   DeserializationError error = deserializeJson(rep, json);
  4.   if (error)
  5.   {
  6.     Serial.print(F("prase failed: "));
  7.     Serial.println(error.f_str());
  8.     return;
  9.   }
  10.   const char * source = rep["location"]["position"]["source"];
  11.   const char * spatialReference = rep["location"]["position"]["spatialReference"];
  12.   double longitude = rep["location"]["position"]["point"]["longitude"];
  13.   double latitude = rep["location"]["position"]["point"]["latitude"];
  14.   const char * name = rep["location"]["address"]["name"];
  15.   Serial.print("当前地址:\t");
  16.   Serial.println(name);
  17.   Serial.print("当前经纬度坐标:\t");
  18.   Serial.print(longitude,6);
  19.   Serial.print("\t");
  20.   Serial.println(latitude,6);
  21.   Serial.print("定位获取来源:\t");
  22.   Serial.print(source);
  23.   Serial.print("\t坐标格式:\t");
  24.   Serial.println(spatialReference);
  25. }
复制代码

最后一步就是在loop调用上述的函数去实现定位效果了
  1. void loop() {
  2.   wifi_scan();
  3.   postMessage = JsonSerialization();
  4.   get_location(postMessage);
  5.   delay(5000);
  6.   // 重新连接
  7.   if (WiFi.status() != WL_CONNECTED) {
  8.     Serial.println("Reconnecting to WiFi...");
  9.     WiFi.disconnect();
  10.     WiFi.reconnect();
  11.   }
  12. }
复制代码

到这里就一切准备就绪了,全程不到100行代码轻松实现WiFi定位,解析定位效果如下
Arduino ESP32 WiFi定位图5
来到全域定位平台,他自带了监控大屏,上面可以看到当前设备所在位置
Arduino ESP32 WiFi定位图6
该平台还有电子围栏,轨迹查询等功能还需要各位自己去慢慢摸索,相应的API手册也很齐全,如果有什么问题欢迎留言,我会尽快回复。


​该贴原贴是在另外一个地方写的,不想重复工作所以移植一下https://blog.csdn.net/m0_50846041/article/details/128955571



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主

楼主的其它帖子

上海智位机器人股份有限公司 沪ICP备09038501号-4 备案

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail