flip_trader_callback.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #include <callback/flip_trader_callback.h>
  2. // hold the price of the asset
  3. char asset_price[64];
  4. bool sent_get_request = false;
  5. bool get_request_success = false;
  6. bool request_processed = false;
  7. void flip_trader_request_error(Canvas *canvas)
  8. {
  9. if (fhttp.last_response != NULL)
  10. {
  11. if (strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
  12. {
  13. canvas_clear(canvas);
  14. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  15. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  16. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  17. }
  18. else if (strstr(fhttp.last_response, "[ERROR] Failed to connect to Wifi.") != NULL)
  19. {
  20. canvas_clear(canvas);
  21. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  22. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  23. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  24. }
  25. else if (strstr(fhttp.last_response, "[ERROR] WiFi SSID or Password is empty") != NULL)
  26. {
  27. canvas_clear(canvas);
  28. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  29. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  30. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  31. }
  32. else
  33. {
  34. canvas_clear(canvas);
  35. FURI_LOG_E(TAG, "Received an error: %s", fhttp.last_response);
  36. canvas_draw_str(canvas, 0, 10, "[ERROR] Unusual error...");
  37. canvas_draw_str(canvas, 0, 60, "Press BACK and retry.");
  38. }
  39. }
  40. else
  41. {
  42. canvas_clear(canvas);
  43. canvas_draw_str(canvas, 0, 10, "[ERROR] Unknown error.");
  44. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  45. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  46. }
  47. }
  48. bool send_price_request()
  49. {
  50. if (!sent_get_request && fhttp.state == IDLE)
  51. {
  52. sent_get_request = true;
  53. char url[128];
  54. char *headers = jsmn("Content-Type", "application/json");
  55. snprintf(
  56. fhttp.file_path,
  57. sizeof(fhttp.file_path),
  58. STORAGE_EXT_PATH_PREFIX "/apps_data/flip_trader/price.txt");
  59. fhttp.save_received_data = true;
  60. snprintf(url, 128, "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=%s&apikey=2X90WLEFMP43OJKE", asset_names[asset_index]);
  61. get_request_success = flipper_http_get_request_with_headers(url, headers);
  62. free(headers);
  63. if (!get_request_success)
  64. {
  65. FURI_LOG_E(TAG, "Failed to send GET request");
  66. fhttp.state = ISSUE;
  67. return false;
  68. }
  69. fhttp.state = RECEIVING;
  70. }
  71. return true;
  72. }
  73. void process_asset_price()
  74. {
  75. // load the received data from the saved file
  76. FuriString *price_data = flipper_http_load_from_file(fhttp.file_path);
  77. if (price_data == NULL)
  78. {
  79. FURI_LOG_E(TAG, "Failed to load received data from file.");
  80. fhttp.state = ISSUE;
  81. return;
  82. }
  83. char *data_cstr = (char *)furi_string_get_cstr(price_data);
  84. if (data_cstr == NULL)
  85. {
  86. FURI_LOG_E(TAG, "Failed to get C-string from FuriString.");
  87. furi_string_free(price_data);
  88. fhttp.state = ISSUE;
  89. return;
  90. }
  91. if (!request_processed)
  92. {
  93. request_processed = true;
  94. char *global_quote = get_json_value("Global Quote", data_cstr, MAX_TOKENS);
  95. if (global_quote == NULL)
  96. {
  97. FURI_LOG_E(TAG, "Failed to get Global Quote");
  98. fhttp.state = ISSUE;
  99. furi_string_free(price_data);
  100. free(global_quote);
  101. free(data_cstr);
  102. return;
  103. }
  104. char *price = get_json_value("05. price", global_quote, MAX_TOKENS);
  105. if (price == NULL)
  106. {
  107. FURI_LOG_E(TAG, "Failed to get price");
  108. fhttp.state = ISSUE;
  109. furi_string_free(price_data);
  110. free(global_quote);
  111. free(price);
  112. free(data_cstr);
  113. return;
  114. }
  115. // store the price "Asset: $price"
  116. snprintf(asset_price, 64, "%s: $%s", asset_names[asset_index], price);
  117. fhttp.state = IDLE;
  118. furi_string_free(price_data);
  119. free(global_quote);
  120. free(price);
  121. free(data_cstr);
  122. }
  123. }
  124. // Callback for drawing the main screen
  125. void flip_trader_view_draw_callback(Canvas *canvas, void *model)
  126. {
  127. if (!canvas)
  128. {
  129. return;
  130. }
  131. UNUSED(model);
  132. canvas_set_font(canvas, FontSecondary);
  133. if (fhttp.state == INACTIVE)
  134. {
  135. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  136. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  137. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  138. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  139. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  140. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  141. return;
  142. }
  143. canvas_draw_str(canvas, 0, 10, "Loading...");
  144. // canvas_draw_str(canvas, 0, 10, asset_names[asset_index]);
  145. // start the process
  146. if (!send_price_request())
  147. {
  148. flip_trader_request_error(canvas);
  149. }
  150. // wait until the request is processed
  151. if (!sent_get_request || !get_request_success || fhttp.state == RECEIVING)
  152. {
  153. return;
  154. }
  155. // check status
  156. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  157. {
  158. flip_trader_request_error(canvas);
  159. }
  160. // success, process the data
  161. process_asset_price();
  162. canvas_clear(canvas);
  163. canvas_draw_str(canvas, 0, 10, asset_price);
  164. }
  165. // Input callback for the view (async input handling)
  166. bool flip_trader_view_input_callback(InputEvent *event, void *context)
  167. {
  168. FlipTraderApp *app = (FlipTraderApp *)context;
  169. if (event->type == InputTypePress && event->key == InputKeyBack)
  170. {
  171. // Exit the app when the back button is pressed
  172. view_dispatcher_stop(app->view_dispatcher);
  173. return true;
  174. }
  175. return false;
  176. }
  177. void callback_submenu_choices(void *context, uint32_t index)
  178. {
  179. FlipTraderApp *app = (FlipTraderApp *)context;
  180. if (!app)
  181. {
  182. FURI_LOG_E(TAG, "FlipTraderApp is NULL");
  183. return;
  184. }
  185. switch (index)
  186. {
  187. // view the assets submenu
  188. case FlipTradeSubmenuIndexAssets:
  189. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewAssetsSubmenu);
  190. break;
  191. // view the about screen
  192. case FlipTraderSubmenuIndexAbout:
  193. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewAbout);
  194. break;
  195. // view the wifi settings screen
  196. case FlipTraderSubmenuIndexSettings:
  197. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewWiFiSettings);
  198. break;
  199. default:
  200. // handle FlipTraderSubmenuIndexAssetStartIndex + index
  201. if (index >= FlipTraderSubmenuIndexAssetStartIndex)
  202. {
  203. asset_index = index - FlipTraderSubmenuIndexAssetStartIndex;
  204. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewMain);
  205. }
  206. else
  207. {
  208. FURI_LOG_E(TAG, "Unknown submenu index");
  209. }
  210. break;
  211. }
  212. }
  213. void text_updated_ssid(void *context)
  214. {
  215. FlipTraderApp *app = (FlipTraderApp *)context;
  216. if (!app)
  217. {
  218. FURI_LOG_E(TAG, "FlipTraderApp is NULL");
  219. return;
  220. }
  221. // store the entered text
  222. strncpy(app->uart_text_input_buffer_ssid, app->uart_text_input_temp_buffer_ssid, app->uart_text_input_buffer_size_ssid);
  223. // Ensure null-termination
  224. app->uart_text_input_buffer_ssid[app->uart_text_input_buffer_size_ssid - 1] = '\0';
  225. // update the variable item text
  226. if (app->variable_item_ssid)
  227. {
  228. variable_item_set_current_value_text(app->variable_item_ssid, app->uart_text_input_buffer_ssid);
  229. }
  230. // save settings
  231. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  232. // save wifi settings to devboard
  233. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  234. {
  235. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  236. {
  237. FURI_LOG_E(TAG, "Failed to save wifi settings");
  238. }
  239. }
  240. // switch to the settings view
  241. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewWiFiSettings);
  242. }
  243. void text_updated_password(void *context)
  244. {
  245. FlipTraderApp *app = (FlipTraderApp *)context;
  246. if (!app)
  247. {
  248. FURI_LOG_E(TAG, "FlipTraderApp is NULL");
  249. return;
  250. }
  251. // store the entered text
  252. strncpy(app->uart_text_input_buffer_password, app->uart_text_input_temp_buffer_password, app->uart_text_input_buffer_size_password);
  253. // Ensure null-termination
  254. app->uart_text_input_buffer_password[app->uart_text_input_buffer_size_password - 1] = '\0';
  255. // update the variable item text
  256. if (app->variable_item_password)
  257. {
  258. variable_item_set_current_value_text(app->variable_item_password, app->uart_text_input_buffer_password);
  259. }
  260. // save settings
  261. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  262. // save wifi settings to devboard
  263. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  264. {
  265. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  266. {
  267. FURI_LOG_E(TAG, "Failed to save wifi settings");
  268. }
  269. }
  270. // switch to the settings view
  271. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewWiFiSettings);
  272. }
  273. uint32_t callback_to_submenu(void *context)
  274. {
  275. if (!context)
  276. {
  277. FURI_LOG_E(TAG, "Context is NULL");
  278. return VIEW_NONE;
  279. }
  280. UNUSED(context);
  281. sent_get_request = false;
  282. get_request_success = false;
  283. request_processed = false;
  284. asset_index = 0;
  285. return FlipTraderViewMainSubmenu;
  286. }
  287. uint32_t callback_to_wifi_settings(void *context)
  288. {
  289. if (!context)
  290. {
  291. FURI_LOG_E(TAG, "Context is NULL");
  292. return VIEW_NONE;
  293. }
  294. UNUSED(context);
  295. return FlipTraderViewWiFiSettings;
  296. }
  297. uint32_t callback_to_assets_submenu(void *context)
  298. {
  299. if (!context)
  300. {
  301. FURI_LOG_E(TAG, "Context is NULL");
  302. return VIEW_NONE;
  303. }
  304. UNUSED(context);
  305. sent_get_request = false;
  306. get_request_success = false;
  307. request_processed = false;
  308. asset_index = 0;
  309. return FlipTraderViewAssetsSubmenu;
  310. }
  311. void settings_item_selected(void *context, uint32_t index)
  312. {
  313. FlipTraderApp *app = (FlipTraderApp *)context;
  314. if (!app)
  315. {
  316. FURI_LOG_E(TAG, "FlipTraderApp is NULL");
  317. return;
  318. }
  319. switch (index)
  320. {
  321. case 0: // Input SSID
  322. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewTextInputSSID);
  323. break;
  324. case 1: // Input Password
  325. view_dispatcher_switch_to_view(app->view_dispatcher, FlipTraderViewTextInputPassword);
  326. break;
  327. default:
  328. FURI_LOG_E(TAG, "Unknown configuration item index");
  329. break;
  330. }
  331. }