wardriver_uart.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. #include "wardriver_uart.h"
  2. static void removeSpaces(char* str) {
  3. int i = 0;
  4. while(isspace((unsigned char)str[i])) {
  5. i++;
  6. }
  7. int j = 0;
  8. while(str[i] != '\0') {
  9. str[j++] = str[i++];
  10. }
  11. str[j] = '\0';
  12. int len = strlen(str);
  13. while(len > 0 && isspace((unsigned char)str[len - 1])) {
  14. str[--len] = '\0';
  15. }
  16. }
  17. static void sort_access_points(Context* ctx) {
  18. for(int i = 0; i < ctx->access_points_count; i++) {
  19. for(int j = i + 1; j < ctx->access_points_count; j++) {
  20. if(strcmp(ctx->access_points[i].ssid, ctx->access_points[j].ssid) > 0) {
  21. AccessPoint temp = ctx->access_points[i];
  22. ctx->access_points[i] = ctx->access_points[j];
  23. ctx->access_points[j] = temp;
  24. }
  25. }
  26. }
  27. }
  28. static void set_index_from_access_points(Context* ctx) {
  29. for(int i = 0; i < ctx->access_points_count; i++) {
  30. if(ctx->access_points[i].bssid == ctx->active_access_point.bssid) {
  31. ctx->access_points_index = i;
  32. break;
  33. }
  34. }
  35. }
  36. static void uart_parse_esp(void* context, char* line) {
  37. Context* ctx = context;
  38. AccessPoint ap = {.ssid = malloc(MAX_SSID_LENGTH + 1), .bssid = malloc(MAX_BSSID_LENGTH + 1)};
  39. Packet pkt = {.recievedMac = malloc(18 + 1), .sentMac = malloc(18 + 1)};
  40. char* token = strtok(line, ",");
  41. int i = 0;
  42. bool isAp = false;
  43. bool isValid = false;
  44. while(token != NULL) {
  45. switch(i) {
  46. case 0:
  47. if(strcmp(token, "AR") == 0) {
  48. isAp = true;
  49. isValid = true;
  50. } else if(strcmp(token, "PK") == 0) {
  51. isValid = true;
  52. }
  53. break;
  54. case 1:
  55. if(isAp && isValid) {
  56. removeSpaces(token);
  57. strcpy(ap.ssid, token);
  58. } else if(!isAp && isValid) {
  59. strncpy(pkt.recievedMac, token, 18);
  60. pkt.recievedMac[18] = '\0';
  61. }
  62. break;
  63. case 2:
  64. if(isAp && isValid) {
  65. strcpy(ap.bssid, token);
  66. } else if(!isAp && isValid) {
  67. strncpy(pkt.sentMac, token, 18);
  68. pkt.sentMac[18] = '\0';
  69. }
  70. break;
  71. case 3:
  72. if(isAp && isValid) {
  73. ap.rssi = atoi(token);
  74. }
  75. break;
  76. case 4:
  77. if(isAp && isValid) {
  78. ap.channel = atoi(token);
  79. }
  80. break;
  81. }
  82. token = strtok(NULL, ",");
  83. i++;
  84. }
  85. if(isAp && isValid) {
  86. // free the packet
  87. free(pkt.recievedMac);
  88. free(pkt.sentMac);
  89. if(ctx->view_state == NO_APS) {
  90. ctx->view_state = NORMAL;
  91. }
  92. // check if values are valid
  93. // bssid needs an ":"
  94. // rssi needs to be negative
  95. // channel needs to be between 1 and 14
  96. // ssid needs to be at least 1 character long
  97. if(ap.bssid[2] != ':' || ap.bssid[5] != ':' || ap.bssid[8] != ':' || ap.bssid[11] != ':' ||
  98. ap.bssid[14] != ':' || ap.rssi > 0 || ap.channel < 1 || ap.channel > 14 ||
  99. strlen(ap.ssid) < 1) {
  100. free(ap.ssid);
  101. free(ap.bssid);
  102. return;
  103. }
  104. furi_hal_light_set(LightBlue, 0);
  105. furi_hal_light_set(LightGreen, 255);
  106. furi_hal_rtc_get_datetime(&ap.datetime);
  107. if(isnan(ctx->gps_data.latitude) || isnan(ctx->gps_data.longitude)) {
  108. ap.latitude = 0;
  109. ap.longitude = 0;
  110. } else {
  111. ap.latitude = ctx->gps_data.latitude;
  112. ap.longitude = ctx->gps_data.longitude;
  113. }
  114. // check if ap is already in the list otherwise add it but update the rssi
  115. bool found = false;
  116. for(size_t i = 0; i < ctx->access_points_count; i++) {
  117. if(strcmp(ctx->access_points[i].bssid, ap.bssid) == 0) {
  118. found = true;
  119. //update rssi channel datetime
  120. ctx->access_points[i].rssi = ap.rssi;
  121. ctx->access_points[i].channel = ap.channel;
  122. ctx->access_points[i].datetime = ap.datetime;
  123. ctx->access_points[i].latitude = ap.latitude;
  124. ctx->access_points[i].longitude = ap.longitude;
  125. if(strcmp(ctx->active_access_point.bssid, ap.bssid) == 0) {
  126. ctx->active_access_point.rssi = ap.rssi;
  127. ctx->active_access_point.channel = ap.channel;
  128. ctx->active_access_point.datetime = ap.datetime;
  129. ctx->active_access_point.latitude = ap.latitude;
  130. ctx->active_access_point.longitude = ap.longitude;
  131. }
  132. free(ap.ssid);
  133. free(ap.bssid);
  134. break;
  135. }
  136. }
  137. if(!found) {
  138. memcpy(&ctx->access_points[ctx->access_points_count], &ap, sizeof(AccessPoint));
  139. ctx->access_points_count++;
  140. }
  141. sort_access_points(ctx);
  142. set_index_from_access_points(ctx);
  143. } else {
  144. // it is a packet so screw the ap
  145. free(ap.ssid);
  146. free(ap.bssid);
  147. // check if values are valid
  148. // mac needs to be 6 characters long
  149. if(strlen(pkt.recievedMac) != 17 || strlen(pkt.sentMac) != 17 ||
  150. ctx->access_points_count == 0) {
  151. free(pkt.recievedMac);
  152. free(pkt.sentMac);
  153. return;
  154. }
  155. furi_hal_light_set(LightGreen, 0);
  156. furi_hal_light_set(LightBlue, 255);
  157. for(size_t i = 0; i < ctx->access_points_count; i++) {
  158. if(strcmp(ctx->access_points[i].bssid, pkt.recievedMac) == 0) {
  159. ctx->access_points[i].packetRxCount++;
  160. break;
  161. }
  162. }
  163. for(size_t i = 0; i < ctx->access_points_count; i++) {
  164. if(strcmp(ctx->access_points[i].bssid, pkt.sentMac) == 0) {
  165. ctx->access_points[i].packetTxCount++;
  166. break;
  167. }
  168. }
  169. free(pkt.recievedMac);
  170. free(pkt.sentMac);
  171. }
  172. }
  173. static void uart_cb_esp(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
  174. Context* ctx = (Context*)context;
  175. if(event == FuriHalSerialRxEventData) {
  176. uint8_t data = furi_hal_serial_async_rx(handle);
  177. furi_stream_buffer_send(ctx->rx_stream_esp, &data, 1, 0);
  178. furi_thread_flags_set(furi_thread_get_id(ctx->thread_esp), WorkerEvtRxDone);
  179. }
  180. }
  181. static int32_t uart_worker_esp(void* context) {
  182. Context* ctx = (Context*)context;
  183. size_t rx_offset = 0;
  184. while(1) {
  185. uint32_t events =
  186. furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  187. furi_check((events & FuriFlagError) == 0);
  188. if(events & WorkerEvtStop) {
  189. break;
  190. }
  191. if(events & WorkerEvtRxDone) {
  192. size_t len = 0;
  193. do {
  194. // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer
  195. // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset
  196. len = furi_stream_buffer_receive(
  197. ctx->rx_stream_esp,
  198. ctx->rx_buf_esp + rx_offset,
  199. RX_BUF_SIZE - 1 - rx_offset,
  200. 0);
  201. if(len > 0) {
  202. // increase rx_offset by the number of bytes received, and null-terminate rx_buf
  203. rx_offset += len;
  204. ctx->rx_buf_esp[rx_offset] = '\0';
  205. // look for strings ending in newlines, starting at the start of rx_buf
  206. char* line_current = (char*)ctx->rx_buf_esp;
  207. while(1) {
  208. // skip null characters
  209. while(*line_current == '\0' &&
  210. line_current < (char*)ctx->rx_buf_esp + rx_offset - 1) {
  211. line_current++;
  212. }
  213. // find the next newline
  214. char* newline = strchr(line_current, '\n');
  215. if(newline) // newline found
  216. {
  217. // put a null terminator in place of the newline, to delimit the line string
  218. *newline = '\0';
  219. uart_parse_esp(ctx, line_current);
  220. // move the cursor to the character after the newline
  221. line_current = newline + 1;
  222. } else // no more newlines found
  223. {
  224. if(line_current >
  225. (char*)ctx->rx_buf_esp) // at least one line was found
  226. {
  227. // clear parsed lines, and move any leftover bytes to the start of rx_buf
  228. rx_offset = 0;
  229. while(
  230. *line_current) // stop when the original rx_offset terminator is reached
  231. {
  232. ctx->rx_buf_esp[rx_offset++] = *(line_current++);
  233. }
  234. }
  235. break; // go back to receiving bytes from the serial stream
  236. }
  237. }
  238. }
  239. } while(len > 0);
  240. }
  241. }
  242. return 0;
  243. }
  244. static void uart_parse_gps(Context* ctx, char* line) {
  245. switch(minmea_sentence_id(line, false)) {
  246. case MINMEA_SENTENCE_RMC: {
  247. struct minmea_sentence_rmc frame;
  248. if(minmea_parse_rmc(&frame, line)) {
  249. ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
  250. ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
  251. ctx->gps_data.hour = frame.time.hours;
  252. ctx->gps_data.minute = frame.time.minutes;
  253. ctx->gps_data.second = frame.time.seconds;
  254. }
  255. } break;
  256. case MINMEA_SENTENCE_GGA: {
  257. struct minmea_sentence_gga frame;
  258. if(minmea_parse_gga(&frame, line)) {
  259. ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
  260. ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
  261. ctx->gps_data.hour = frame.time.hours;
  262. ctx->gps_data.minute = frame.time.minutes;
  263. ctx->gps_data.second = frame.time.seconds;
  264. ctx->gps_data.satelites = frame.satellites_tracked;
  265. }
  266. } break;
  267. case MINMEA_SENTENCE_GLL: {
  268. struct minmea_sentence_gll frame;
  269. if(minmea_parse_gll(&frame, line)) {
  270. ctx->gps_data.latitude = minmea_tocoord(&frame.latitude);
  271. ctx->gps_data.longitude = minmea_tocoord(&frame.longitude);
  272. ctx->gps_data.hour = frame.time.hours;
  273. ctx->gps_data.minute = frame.time.minutes;
  274. ctx->gps_data.second = frame.time.seconds;
  275. }
  276. } break;
  277. default:
  278. break;
  279. }
  280. }
  281. static void uart_cb_gps(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
  282. Context* ctx = (Context*)context;
  283. if(event == FuriHalSerialRxEventData) {
  284. uint8_t data = furi_hal_serial_async_rx(handle);
  285. furi_stream_buffer_send(ctx->rx_stream_gps, &data, 1, 0);
  286. furi_thread_flags_set(furi_thread_get_id(ctx->thread_gps), WorkerEvtRxDone);
  287. }
  288. }
  289. static int32_t uart_worker_gps(void* context) {
  290. Context* ctx = (Context*)context;
  291. size_t rx_offset = 0;
  292. while(1) {
  293. uint32_t events =
  294. furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  295. furi_check((events & FuriFlagError) == 0);
  296. if(events & WorkerEvtStop) {
  297. break;
  298. }
  299. if(events & WorkerEvtRxDone) {
  300. size_t len = 0;
  301. do {
  302. // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer
  303. // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset
  304. len = furi_stream_buffer_receive(
  305. ctx->rx_stream_gps,
  306. ctx->rx_buf_gps + rx_offset,
  307. RX_BUF_SIZE - 1 - rx_offset,
  308. 0);
  309. if(len > 0) {
  310. // increase rx_offset by the number of bytes received, and null-terminate rx_buf
  311. rx_offset += len;
  312. ctx->rx_buf_gps[rx_offset] = '\0';
  313. // look for strings ending in newlines, starting at the start of rx_buf
  314. char* line_current = (char*)ctx->rx_buf_gps;
  315. while(1) {
  316. // skip null characters
  317. while(*line_current == '\0' &&
  318. line_current < (char*)ctx->rx_buf_gps + rx_offset - 1) {
  319. line_current++;
  320. }
  321. // find the next newline
  322. char* newline = strchr(line_current, '\n');
  323. if(newline) // newline found
  324. {
  325. // put a null terminator in place of the newline, to delimit the line string
  326. *newline = '\0';
  327. uart_parse_gps(ctx, line_current);
  328. // move the cursor to the character after the newline
  329. line_current = newline + 1;
  330. } else // no more newlines found
  331. {
  332. if(line_current >
  333. (char*)ctx->rx_buf_gps) // at least one line was found
  334. {
  335. // clear parsed lines, and move any leftover bytes to the start of rx_buf
  336. rx_offset = 0;
  337. while(
  338. *line_current) // stop when the original rx_offset terminator is reached
  339. {
  340. ctx->rx_buf_gps[rx_offset++] = *(line_current++);
  341. }
  342. }
  343. break; // go back to receiving bytes from the serial stream
  344. }
  345. }
  346. }
  347. } while(len > 0);
  348. }
  349. }
  350. return 0;
  351. }
  352. void wardriver_uart_init(Context* ctx) {
  353. ctx->rx_stream_esp = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
  354. ctx->thread_esp = furi_thread_alloc();
  355. furi_thread_set_name(ctx->thread_esp, "LLwardriverUartWorkerESP");
  356. furi_thread_set_stack_size(ctx->thread_esp, 2048);
  357. furi_thread_set_context(ctx->thread_esp, ctx);
  358. furi_thread_set_callback(ctx->thread_esp, uart_worker_esp);
  359. furi_thread_start(ctx->thread_esp);
  360. ctx->serial_handle_esp = furi_hal_serial_control_acquire(UART_CH_ESP);
  361. furi_check(ctx->serial_handle_esp);
  362. furi_hal_serial_init(ctx->serial_handle_esp, 115200);
  363. furi_hal_serial_async_rx_start(ctx->serial_handle_esp, uart_cb_esp, ctx, false);
  364. if(UART_CH_ESP != UART_CH_GPS) {
  365. ctx->rx_stream_gps = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
  366. ctx->thread_gps = furi_thread_alloc();
  367. furi_thread_set_name(ctx->thread_gps, "LLwardriverUartWorkerGPS");
  368. furi_thread_set_stack_size(ctx->thread_gps, 2048);
  369. furi_thread_set_context(ctx->thread_gps, ctx);
  370. furi_thread_set_callback(ctx->thread_gps, uart_worker_gps);
  371. furi_thread_start(ctx->thread_gps);
  372. ctx->serial_handle_gps = furi_hal_serial_control_acquire(UART_CH_GPS);
  373. furi_check(ctx->serial_handle_gps);
  374. furi_hal_serial_init(ctx->serial_handle_gps, 9600);
  375. furi_hal_serial_async_rx_start(ctx->serial_handle_gps, uart_cb_gps, ctx, false);
  376. }
  377. return;
  378. }
  379. void wardriver_uart_deinit(Context* ctx) {
  380. furi_hal_serial_async_rx_stop(ctx->serial_handle_esp);
  381. furi_hal_serial_deinit(ctx->serial_handle_esp);
  382. furi_hal_serial_control_release(ctx->serial_handle_esp);
  383. if(UART_CH_ESP != UART_CH_GPS) {
  384. furi_hal_serial_async_rx_stop(ctx->serial_handle_gps);
  385. furi_hal_serial_deinit(ctx->serial_handle_gps);
  386. furi_hal_serial_control_release(ctx->serial_handle_gps);
  387. }
  388. furi_thread_flags_set(furi_thread_get_id(ctx->thread_esp), WorkerEvtStop);
  389. furi_thread_join(ctx->thread_esp);
  390. furi_thread_free(ctx->thread_esp);
  391. furi_stream_buffer_free(ctx->rx_stream_esp);
  392. if(UART_CH_ESP != UART_CH_GPS) {
  393. furi_thread_flags_set(furi_thread_get_id(ctx->thread_gps), WorkerEvtStop);
  394. furi_thread_join(ctx->thread_gps);
  395. furi_thread_free(ctx->thread_gps);
  396. furi_stream_buffer_free(ctx->rx_stream_gps);
  397. }
  398. return;
  399. }