flip_trader_callback.c 11 KB

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