flip_weather_callback.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "callback/flip_weather_callback.h"
  2. bool weather_request_success = false;
  3. bool sent_weather_request = false;
  4. bool got_weather_data = false;
  5. void flip_weather_popup_callback(void *context)
  6. {
  7. FlipWeatherApp *app = (FlipWeatherApp *)context;
  8. if (!app)
  9. {
  10. FURI_LOG_E(TAG, "FlipWeatherApp is NULL");
  11. return;
  12. }
  13. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewSubmenu);
  14. }
  15. void flip_weather_request_error(Canvas *canvas)
  16. {
  17. if (fhttp.last_response != NULL)
  18. {
  19. if (strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
  20. {
  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. }
  26. else if (strstr(fhttp.last_response, "[ERROR] Failed to connect to Wifi.") != NULL)
  27. {
  28. canvas_clear(canvas);
  29. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  30. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  31. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  32. }
  33. else if (strstr(fhttp.last_response, "[ERROR] GET request failed or returned empty data.") != NULL)
  34. {
  35. canvas_clear(canvas);
  36. canvas_draw_str(canvas, 0, 10, "[ERROR] WiFi error.");
  37. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  38. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  39. }
  40. else
  41. {
  42. canvas_clear(canvas);
  43. FURI_LOG_E(TAG, "Received an error: %s", fhttp.last_response);
  44. canvas_draw_str(canvas, 0, 10, "[ERROR] Unusual error...");
  45. canvas_draw_str(canvas, 0, 60, "Press BACK and retry.");
  46. }
  47. }
  48. else
  49. {
  50. canvas_clear(canvas);
  51. canvas_draw_str(canvas, 0, 10, "[ERROR] Unknown error.");
  52. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  53. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  54. }
  55. }
  56. void flip_weather_handle_gps_draw(Canvas *canvas, bool show_gps_data)
  57. {
  58. if (sent_get_request)
  59. {
  60. if (fhttp.state == RECEIVING)
  61. {
  62. if (show_gps_data)
  63. {
  64. canvas_clear(canvas);
  65. canvas_draw_str(canvas, 0, 10, "Loading GPS...");
  66. canvas_draw_str(canvas, 0, 22, "Receiving...");
  67. }
  68. }
  69. // check status
  70. else if (fhttp.state == ISSUE || !get_request_success || fhttp.last_response == NULL)
  71. {
  72. flip_weather_request_error(canvas);
  73. }
  74. else if (fhttp.state == IDLE && fhttp.last_response != NULL)
  75. {
  76. // success, draw GPS
  77. process_geo_location();
  78. if (show_gps_data)
  79. {
  80. canvas_clear(canvas);
  81. canvas_draw_str(canvas, 0, 10, city_data);
  82. canvas_draw_str(canvas, 0, 20, region_data);
  83. canvas_draw_str(canvas, 0, 30, country_data);
  84. canvas_draw_str(canvas, 0, 40, lat_data);
  85. canvas_draw_str(canvas, 0, 50, lon_data);
  86. canvas_draw_str(canvas, 0, 60, ip_data);
  87. }
  88. }
  89. }
  90. }
  91. // Callback for drawing the weather screen
  92. void flip_weather_view_draw_callback_weather(Canvas *canvas, void *model)
  93. {
  94. if (!canvas)
  95. {
  96. return;
  97. }
  98. UNUSED(model);
  99. canvas_set_font(canvas, FontSecondary);
  100. if (fhttp.state == INACTIVE)
  101. {
  102. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  103. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  104. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  105. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  106. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  107. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  108. return;
  109. }
  110. canvas_draw_str(canvas, 0, 10, "Loading Weather...");
  111. // handle geo location until it's processed and then handle weather
  112. // start the process
  113. if (!send_geo_location_request() || fhttp.state == ISSUE)
  114. {
  115. flip_weather_request_error(canvas);
  116. }
  117. // wait until geo location is processed
  118. if (!sent_get_request || !get_request_success || fhttp.state == RECEIVING)
  119. {
  120. return;
  121. }
  122. // get/set geo lcoation once
  123. if (!geo_information_processed)
  124. {
  125. flip_weather_handle_gps_draw(canvas, false);
  126. }
  127. // start the weather process
  128. if (!sent_weather_request && fhttp.state == IDLE)
  129. {
  130. sent_weather_request = true;
  131. char url[512];
  132. char *lattitude = lat_data + 10;
  133. char *longitude = lon_data + 11;
  134. char *headers = jsmn("Content-Type", "application/json");
  135. snprintf(url, 512, "https://api.open-meteo.com/v1/forecast?latitude=%s&longitude=%s&current=temperature_2m,precipitation,rain,showers,snowfall&temperature_unit=celsius&wind_speed_unit=mph&precipitation_unit=inch&forecast_days=1", lattitude, longitude);
  136. weather_request_success = flipper_http_get_request_with_headers(url, headers);
  137. free(headers);
  138. if (!weather_request_success)
  139. {
  140. FURI_LOG_E(TAG, "Failed to send GET request");
  141. fhttp.state = ISSUE;
  142. flip_weather_request_error(canvas);
  143. }
  144. fhttp.state = RECEIVING;
  145. }
  146. else
  147. {
  148. if (fhttp.state == RECEIVING)
  149. {
  150. canvas_draw_str(canvas, 0, 10, "Loading Weather...");
  151. canvas_draw_str(canvas, 0, 22, "Receiving...");
  152. return;
  153. }
  154. // check status
  155. if (fhttp.state == ISSUE || !weather_request_success || fhttp.last_response == NULL)
  156. {
  157. flip_weather_request_error(canvas);
  158. }
  159. else
  160. {
  161. // success, draw weather
  162. process_weather();
  163. canvas_clear(canvas);
  164. canvas_draw_str(canvas, 0, 10, temperature_data);
  165. canvas_draw_str(canvas, 0, 20, precipitation_data);
  166. canvas_draw_str(canvas, 0, 30, rain_data);
  167. canvas_draw_str(canvas, 0, 40, showers_data);
  168. canvas_draw_str(canvas, 0, 50, snowfall_data);
  169. canvas_draw_str(canvas, 0, 60, time_data);
  170. }
  171. }
  172. }
  173. // Callback for drawing the GPS screen
  174. void flip_weather_view_draw_callback_gps(Canvas *canvas, void *model)
  175. {
  176. if (!canvas)
  177. {
  178. return;
  179. }
  180. UNUSED(model);
  181. if (fhttp.state == INACTIVE)
  182. {
  183. canvas_set_font(canvas, FontSecondary);
  184. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  185. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  186. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  187. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  188. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  189. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  190. return;
  191. }
  192. if (!send_geo_location_request() || fhttp.state == ISSUE)
  193. {
  194. flip_weather_request_error(canvas);
  195. }
  196. flip_weather_handle_gps_draw(canvas, true);
  197. }
  198. void callback_submenu_choices(void *context, uint32_t index)
  199. {
  200. FlipWeatherApp *app = (FlipWeatherApp *)context;
  201. if (!app)
  202. {
  203. FURI_LOG_E(TAG, "FlipWeatherApp is NULL");
  204. return;
  205. }
  206. switch (index)
  207. {
  208. case FlipWeatherSubmenuIndexWeather:
  209. if (!flip_weather_handle_ip_address())
  210. {
  211. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewPopupError);
  212. }
  213. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewWeather);
  214. break;
  215. case FlipWeatherSubmenuIndexGPS:
  216. if (!flip_weather_handle_ip_address())
  217. {
  218. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewPopupError);
  219. }
  220. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewGPS);
  221. break;
  222. case FlipWeatherSubmenuIndexAbout:
  223. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewAbout);
  224. break;
  225. case FlipWeatherSubmenuIndexSettings:
  226. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewSettings);
  227. break;
  228. default:
  229. break;
  230. }
  231. }
  232. void text_updated_ssid(void *context)
  233. {
  234. FlipWeatherApp *app = (FlipWeatherApp *)context;
  235. if (!app)
  236. {
  237. FURI_LOG_E(TAG, "FlipWeatherApp is NULL");
  238. return;
  239. }
  240. // store the entered text
  241. strncpy(app->uart_text_input_buffer_ssid, app->uart_text_input_temp_buffer_ssid, app->uart_text_input_buffer_size_ssid);
  242. // Ensure null-termination
  243. app->uart_text_input_buffer_ssid[app->uart_text_input_buffer_size_ssid - 1] = '\0';
  244. // update the variable item text
  245. if (app->variable_item_ssid)
  246. {
  247. variable_item_set_current_value_text(app->variable_item_ssid, app->uart_text_input_buffer_ssid);
  248. }
  249. // save settings
  250. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  251. // save wifi settings to devboard
  252. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  253. {
  254. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  255. {
  256. FURI_LOG_E(TAG, "Failed to save wifi settings");
  257. }
  258. }
  259. // switch to the settings view
  260. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewSettings);
  261. }
  262. void text_updated_password(void *context)
  263. {
  264. FlipWeatherApp *app = (FlipWeatherApp *)context;
  265. if (!app)
  266. {
  267. FURI_LOG_E(TAG, "FlipWeatherApp is NULL");
  268. return;
  269. }
  270. // store the entered text
  271. strncpy(app->uart_text_input_buffer_password, app->uart_text_input_temp_buffer_password, app->uart_text_input_buffer_size_password);
  272. // Ensure null-termination
  273. app->uart_text_input_buffer_password[app->uart_text_input_buffer_size_password - 1] = '\0';
  274. // update the variable item text
  275. if (app->variable_item_password)
  276. {
  277. variable_item_set_current_value_text(app->variable_item_password, app->uart_text_input_buffer_password);
  278. }
  279. // save settings
  280. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  281. // save wifi settings to devboard
  282. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  283. {
  284. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  285. {
  286. FURI_LOG_E(TAG, "Failed to save wifi settings");
  287. }
  288. }
  289. // switch to the settings view
  290. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewSettings);
  291. }
  292. uint32_t callback_to_submenu(void *context)
  293. {
  294. if (!context)
  295. {
  296. FURI_LOG_E(TAG, "Context is NULL");
  297. return VIEW_NONE;
  298. }
  299. UNUSED(context);
  300. sent_get_request = false;
  301. get_request_success = false;
  302. got_ip_address = false;
  303. got_weather_data = false;
  304. geo_information_processed = false;
  305. weather_information_processed = false;
  306. sent_weather_request = false;
  307. weather_request_success = false;
  308. return FlipWeatherViewSubmenu;
  309. }
  310. void settings_item_selected(void *context, uint32_t index)
  311. {
  312. FlipWeatherApp *app = (FlipWeatherApp *)context;
  313. if (!app)
  314. {
  315. FURI_LOG_E(TAG, "FlipWeatherApp is NULL");
  316. return;
  317. }
  318. switch (index)
  319. {
  320. case 0: // Input SSID
  321. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewTextInputSSID);
  322. break;
  323. case 1: // Input Password
  324. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWeatherViewTextInputPassword);
  325. break;
  326. default:
  327. FURI_LOG_E(TAG, "Unknown configuration item index");
  328. break;
  329. }
  330. }
  331. /**
  332. * @brief Navigation callback for exiting the application
  333. * @param context The context - unused
  334. * @return next view id (VIEW_NONE to exit the app)
  335. */
  336. uint32_t callback_exit_app(void *context)
  337. {
  338. // Exit the application
  339. if (!context)
  340. {
  341. FURI_LOG_E(TAG, "Context is NULL");
  342. return VIEW_NONE;
  343. }
  344. UNUSED(context);
  345. return VIEW_NONE; // Return VIEW_NONE to exit the app
  346. }
  347. uint32_t callback_to_wifi_settings(void *context)
  348. {
  349. if (!context)
  350. {
  351. FURI_LOG_E(TAG, "Context is NULL");
  352. return VIEW_NONE;
  353. }
  354. UNUSED(context);
  355. return FlipWeatherViewSettings;
  356. }