WiFi_TX.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. WiFi NAN and Beacon driver
  3. with thanks to https://github.com/sxjack/uav_electronic_ids for WiFi calls
  4. */
  5. #include "WiFi_TX.h"
  6. #include <esp_wifi.h>
  7. #include <WiFi.h>
  8. #include <esp_system.h>
  9. #include "parameters.h"
  10. bool WiFi_TX::init(void)
  11. {
  12. if (initialised) {
  13. return true;
  14. }
  15. initialised = true;
  16. //use a local MAC address to avoid tracking transponders based on their MAC address
  17. uint8_t mac_addr[6];
  18. generate_random_mac(mac_addr);
  19. mac_addr[0] |= 0x02; // set MAC local bit
  20. mac_addr[0] &= 0xFE; // unset MAC multicast bit
  21. Serial.printf("Setting MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
  22. mac_addr[0], mac_addr[1], mac_addr[2],
  23. mac_addr[3], mac_addr[4], mac_addr[5]);
  24. //set MAC address
  25. esp_base_mac_addr_set(mac_addr);
  26. // 2.4Gwifi信道默认是信道6 5.8GHZ应使用信道149
  27. if (g.webserver_enable == 0) {
  28. WiFi.softAP(g.wifi_ssid, g.wifi_password, g.wifi_channel, false, 0); //make it visible and allow no connection
  29. } else {
  30. WiFi.softAP(g.wifi_ssid, g.wifi_password, g.wifi_channel, false, 1); //make it visible and allow only 1 connection
  31. }
  32. if (esp_wifi_set_bandwidth(WIFI_IF_AP, WIFI_BW_HT20) != ESP_OK) { // 国标要求 20MHZ带宽
  33. return false;
  34. }
  35. memcpy(WiFi_mac_addr,mac_addr,6); //use generated random MAC address for OpenDroneID messages
  36. esp_wifi_set_max_tx_power(dBm_to_tx_power(g.wifi_power)); // 按国标要求来说设置不同的功率
  37. return true;
  38. }
  39. // 发送中国国标的数据包
  40. bool WiFi_TX::transmit_cn_nan(CNDID_UAS_Data &UAS_data)
  41. {
  42. init();
  43. uint8_t buffer[1024] {};
  44. int length;
  45. if ((length = cndid_wifi_build_nan_sync_beacon_frame((char *)WiFi_mac_addr,
  46. buffer,sizeof(buffer))) > 0) {
  47. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  48. return false;
  49. }
  50. }
  51. if ((length = cndid_wifi_build_message_pack_nan_action_frame(&UAS_data, (char *)WiFi_mac_addr,
  52. ++send_counter_cn_nan,
  53. buffer,sizeof(buffer))) > 0) {
  54. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  55. return false;
  56. }
  57. }
  58. return true;
  59. }
  60. // 发送国际标准的数据包
  61. bool WiFi_TX::transmit_nan(ODID_UAS_Data &UAS_data)
  62. {
  63. init();
  64. uint8_t buffer[1024] {};
  65. int length;
  66. if ((length = odid_wifi_build_nan_sync_beacon_frame((char *)WiFi_mac_addr,
  67. buffer,sizeof(buffer))) > 0) {
  68. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  69. return false;
  70. }
  71. }
  72. if ((length = odid_wifi_build_message_pack_nan_action_frame(&UAS_data,(char *)WiFi_mac_addr,
  73. ++send_counter_nan,
  74. buffer,sizeof(buffer))) > 0) {
  75. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  76. return false;
  77. }
  78. }
  79. return true;
  80. }
  81. bool WiFi_TX::transmit_cn_beacon(CNDID_UAS_Data &UAS_data)
  82. {
  83. init();
  84. uint8_t buffer[1024] {};
  85. int length;
  86. if ((length = cndid_wifi_build_message_pack_beacon_frame(&UAS_data,(char *)WiFi_mac_addr,
  87. "UAS_ID_OPEN", strlen("UAS_ID_OPEN"), //use dummy SSID, as we only extract payload data
  88. 1000/g.wifi_beacon_rate, ++send_counter_cn_beacon, buffer, sizeof(buffer))) > 0) {
  89. //set the RID IE element
  90. uint8_t header_offset = 58; // 固定包头长度
  91. vendor_ie_data_t IE_data;
  92. IE_data.element_id = 0xDD; // 国标要求
  93. // 符合国标
  94. IE_data.vendor_oui[0] = 0xFA;
  95. IE_data.vendor_oui[1] = 0x0B;
  96. IE_data.vendor_oui[2] = 0xBC;
  97. IE_data.vendor_oui_type = 0x0D;
  98. IE_data.length = length - header_offset + 4; // 添加4作为esp_wifi_set_vendor_ie的定义
  99. // 也就是 uoi vender类型是4个字节
  100. memcpy(IE_data.payload,&buffer[header_offset],length - header_offset);
  101. // 所以首先移除旧元素,之后添加新元素
  102. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  103. return false;
  104. }
  105. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  106. return false;
  107. }
  108. //也将有效载荷设置为探测请求,以提高手机上的更新速率
  109. //因此,先移除旧元素,之后再添加新元素
  110. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  111. return false;
  112. }
  113. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  114. return false;
  115. }
  116. return true;
  117. }
  118. else {
  119. return false;
  120. }
  121. }
  122. //update the payload of the beacon frames in this function
  123. bool WiFi_TX::transmit_beacon(ODID_UAS_Data &UAS_data)
  124. {
  125. init();
  126. uint8_t buffer[1024] {};
  127. int length;
  128. if ((length = odid_wifi_build_message_pack_beacon_frame(&UAS_data,(char *)WiFi_mac_addr,
  129. "UAS_ID_OPEN", strlen("UAS_ID_OPEN"), //use dummy SSID, as we only extract payload data
  130. 1000/g.wifi_beacon_rate, ++send_counter_beacon, buffer, sizeof(buffer))) > 0) {
  131. //设置厂商 RID的元素
  132. uint8_t header_offset = 58; // 定义IE元素头部偏移(58字节是Beacon帧固定头部长度,跳过头部取核心数据)
  133. vendor_ie_data_t IE_data; // 定义厂商IE元素结构体(ESP32 WiFi驱动要求的格式)
  134. IE_data.element_id = WIFI_VENDOR_IE_ELEMENT_ID; // 固定值,标识是厂商自定义IE
  135. IE_data.vendor_oui[0] = 0xFA; // 设置Open Drone ID标准的厂商OUI(FA:0B:BC是无人机Remote ID的专属OUI)
  136. IE_data.vendor_oui[1] = 0x0B;
  137. IE_data.vendor_oui[2] = 0xBC;
  138. IE_data.vendor_oui_type = 0x0D; // Open Drone ID定义的WiFi IE类型值
  139. // // 步骤4:设置IE元素长度(核心Remote ID数据长度 + 4字节ESP32驱动要求的额外长度)
  140. IE_data.length = length - header_offset + 4; //add 4 as of definition esp_wifi_set_vendor_ie
  141. // 拷贝Remote ID核心数据到IE元素的payload(跳过Beacon帧固定头部)
  142. memcpy(IE_data.payload,&buffer[header_offset],length - header_offset);
  143. // 删除旧的Beacon帧厂商IE元素(false=禁用)
  144. // so first remove old element, add new afterwards
  145. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  146. return false;
  147. }
  148. // 添加新的Beacon帧厂商IE元素(true=启用)
  149. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  150. return false;
  151. }
  152. // 为Probe Response帧(手机探测WiFi时的响应帧)也添加相同的Remote ID IE元素
  153. //set the payload also to probe requests, to increase update rate on mobile phones
  154. // so first remove old element, add new afterwards
  155. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  156. return false;
  157. }
  158. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  159. return false;
  160. }
  161. return true;
  162. }
  163. else {
  164. return false;
  165. }
  166. }
  167. bool WiFi_TX::transmit_GB2025_nan(UavIdentificationData &UAS_data)
  168. {
  169. init();
  170. uint8_t buffer[1024] {};
  171. int length;
  172. if ((length = did_GB2025_wifi_build_nan_sync_beacon_frame((char *)WiFi_mac_addr,
  173. buffer,sizeof(buffer))) > 0) {
  174. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  175. return false;
  176. }
  177. }
  178. if ((length = did_GB2025_wifi_build_message_pack_nan_action_frame(&UAS_data,(char *)WiFi_mac_addr,
  179. ++send_counter_GB2025_nan,
  180. buffer,sizeof(buffer))) > 0) {
  181. if (esp_wifi_80211_tx(WIFI_IF_AP,buffer,length,true) != ESP_OK) {
  182. return false;
  183. }
  184. }
  185. return true;
  186. }
  187. bool WiFi_TX::transmit_GB2025_beacon(UavIdentificationData &UAS_data)
  188. {
  189. init();
  190. uint8_t buffer[1024] {};
  191. int length;
  192. if ((length = did_GB2025_wifi_build_message_pack_beacon_frame(&UAS_data,(char *)WiFi_mac_addr,
  193. "UAS_ID_OPEN", strlen("UAS_ID_OPEN"), //use dummy SSID, as we only extract payload data
  194. 1000/g.wifi_beacon_rate, ++send_counter_GB2025_beacon, buffer, sizeof(buffer))) > 0) {
  195. //set the RID IE element
  196. uint8_t header_offset = 58; // 固定包头长度
  197. vendor_ie_data_t IE_data;
  198. IE_data.element_id = 0xDD; // 国标要求
  199. // 符合国标
  200. IE_data.vendor_oui[0] = 0xFA;
  201. IE_data.vendor_oui[1] = 0x0B;
  202. IE_data.vendor_oui[2] = 0xBC;
  203. IE_data.vendor_oui_type = 0x0D;
  204. IE_data.length = length - header_offset + 4; // 添加4作为esp_wifi_set_vendor_ie的定义
  205. // 也就是 uoi vender类型是4个字节
  206. memcpy(IE_data.payload,&buffer[header_offset],length - header_offset);
  207. // 所以首先移除旧元素,之后添加新元素
  208. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  209. return false;
  210. }
  211. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_BEACON, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  212. return false;
  213. }
  214. //也将有效载荷设置为探测请求,以提高手机上的更新速率
  215. //因此,先移除旧元素,之后再添加新元素
  216. if (esp_wifi_set_vendor_ie(false, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  217. return false;
  218. }
  219. if (esp_wifi_set_vendor_ie(true, WIFI_VND_IE_TYPE_PROBE_RESP, WIFI_VND_IE_ID_0, &IE_data) != ESP_OK){
  220. return false;
  221. }
  222. return true;
  223. }
  224. else {
  225. return false;
  226. }
  227. }
  228. /*
  229. map dBm to a TX power
  230. */
  231. uint8_t WiFi_TX::dBm_to_tx_power(float dBm) const
  232. {
  233. if (dBm < 2) {
  234. dBm = 2;
  235. }
  236. if (dBm > 20) {
  237. dBm = 20;
  238. }
  239. return uint8_t((dBm+1.125) * 4);
  240. }