pc_monitor.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include "pc_monitor.h"
  2. static void render_callback(Canvas* canvas, void* ctx) {
  3. furi_assert(ctx);
  4. PcMonitorApp* app = ctx;
  5. if(app->bt_state == BtStateRecieving) {
  6. canvas_clear(canvas);
  7. canvas_set_color(canvas, ColorBlack);
  8. canvas_set_font(canvas, FontKeyboard);
  9. uint8_t line = 0;
  10. uint8_t spacing = app->lines_count ? SCREEN_HEIGHT / app->lines_count : 0;
  11. uint8_t margin_top = spacing ? (spacing - LINE_HEIGHT) / 2 : 0;
  12. char str[32];
  13. if(app->data.cpu_usage <= 100) {
  14. if(app->lines_count) {
  15. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "CPU");
  16. snprintf(str, 32, "%d%%", app->data.cpu_usage);
  17. elements_progress_bar_with_text(
  18. canvas,
  19. BAR_X,
  20. margin_top + line * spacing,
  21. BAR_WIDTH,
  22. app->data.cpu_usage / 100.0f,
  23. str);
  24. }
  25. line++;
  26. }
  27. if(app->data.ram_usage <= 100) {
  28. if(app->lines_count) {
  29. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "RAM");
  30. snprintf(
  31. str,
  32. 32,
  33. "%.1f/%.1f %s",
  34. (double)(app->data.ram_max * 0.1f * app->data.ram_usage * 0.01f),
  35. (double)(app->data.ram_max * 0.1f),
  36. app->data.ram_unit);
  37. elements_progress_bar_with_text(
  38. canvas,
  39. BAR_X,
  40. margin_top + line * spacing,
  41. BAR_WIDTH,
  42. app->data.ram_usage * 0.01f,
  43. str);
  44. }
  45. line++;
  46. }
  47. if(app->data.gpu_usage <= 100) {
  48. if(app->lines_count) {
  49. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "GPU");
  50. snprintf(str, 32, "%d%%", app->data.gpu_usage);
  51. elements_progress_bar_with_text(
  52. canvas,
  53. BAR_X,
  54. margin_top + line * spacing,
  55. BAR_WIDTH,
  56. app->data.gpu_usage / 100.0f,
  57. str);
  58. }
  59. line++;
  60. }
  61. if(app->data.vram_usage <= 100) {
  62. if(app->lines_count) {
  63. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "VRAM");
  64. snprintf(
  65. str,
  66. 32,
  67. "%.1f/%.1f %s",
  68. (double)(app->data.vram_max * 0.1f * app->data.vram_usage * 0.01f),
  69. (double)(app->data.vram_max * 0.1f),
  70. app->data.vram_unit);
  71. elements_progress_bar_with_text(
  72. canvas,
  73. BAR_X,
  74. margin_top + line * spacing,
  75. BAR_WIDTH,
  76. app->data.vram_usage * 0.01f,
  77. str);
  78. }
  79. line++;
  80. }
  81. if(line == 0) app->bt_state = BtStateNoData;
  82. app->lines_count = line;
  83. } else {
  84. canvas_draw_str_aligned(
  85. canvas,
  86. 64,
  87. 32,
  88. AlignCenter,
  89. AlignCenter,
  90. app->bt_state == BtStateChecking ? "Checking BLE..." :
  91. app->bt_state == BtStateInactive ? "BLE inactive!" :
  92. app->bt_state == BtStateWaiting ? "Waiting for data..." :
  93. app->bt_state == BtStateLost ? "Connection lost!" :
  94. "No data!");
  95. }
  96. }
  97. static void input_callback(InputEvent* input_event, void* ctx) {
  98. furi_assert(ctx);
  99. FuriMessageQueue* event_queue = ctx;
  100. furi_message_queue_put(event_queue, input_event, FuriWaitForever);
  101. }
  102. static uint16_t bt_serial_callback(SerialServiceEvent event, void* ctx) {
  103. furi_assert(ctx);
  104. PcMonitorApp* app = ctx;
  105. if(event.event == SerialServiceEventTypeDataReceived) {
  106. FURI_LOG_D(
  107. TAG,
  108. "SerialServiceEventTypeDataReceived. Size: %u/%u. Data: %s",
  109. event.data.size,
  110. sizeof(DataStruct),
  111. (char*)event.data.buffer);
  112. if(event.data.size == sizeof(DataStruct)) {
  113. memcpy(&app->data, event.data.buffer, sizeof(DataStruct));
  114. app->bt_state = BtStateRecieving;
  115. app->last_packet = furi_hal_rtc_get_timestamp();
  116. }
  117. }
  118. return 0;
  119. }
  120. static PcMonitorApp* pc_monitor_alloc() {
  121. PcMonitorApp* app = malloc(sizeof(PcMonitorApp));
  122. app->view_port = view_port_alloc();
  123. app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  124. app->notification = furi_record_open(RECORD_NOTIFICATION);
  125. app->gui = furi_record_open(RECORD_GUI);
  126. app->bt = furi_record_open(RECORD_BT);
  127. gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
  128. view_port_draw_callback_set(app->view_port, render_callback, app);
  129. view_port_input_callback_set(app->view_port, input_callback, app->event_queue);
  130. return app;
  131. }
  132. static void pc_monitor_free(PcMonitorApp* app) {
  133. gui_remove_view_port(app->gui, app->view_port);
  134. view_port_free(app->view_port);
  135. furi_message_queue_free(app->event_queue);
  136. furi_record_close(RECORD_NOTIFICATION);
  137. furi_record_close(RECORD_GUI);
  138. furi_record_close(RECORD_BT);
  139. free(app);
  140. }
  141. int32_t pc_monitor_app(void* p) {
  142. UNUSED(p);
  143. PcMonitorApp* app = pc_monitor_alloc();
  144. bt_disconnect(app->bt);
  145. // Wait 2nd core to update nvm storage
  146. furi_delay_ms(200);
  147. bt_keys_storage_set_storage_path(app->bt, APP_DATA_PATH(".bt_serial.keys"));
  148. BleProfileSerialParams params = {
  149. .device_name_prefix = "PC Mon",
  150. .mac_xor = 0x0002,
  151. };
  152. app->ble_serial_profile = bt_profile_start(app->bt, ble_profile_serial, &params);
  153. furi_check(app->ble_serial_profile);
  154. ble_profile_serial_set_event_callback(
  155. app->ble_serial_profile, BT_SERIAL_BUFFER_SIZE, bt_serial_callback, app);
  156. furi_hal_bt_start_advertising();
  157. app->bt_state = BtStateWaiting;
  158. FURI_LOG_D(TAG, "Bluetooth is active!");
  159. // Main loop
  160. InputEvent event;
  161. while(true) {
  162. if(furi_message_queue_get(app->event_queue, &event, 1) == FuriStatusOk) {
  163. if(event.type == InputTypeShort && event.key == InputKeyBack) break;
  164. }
  165. if(app->bt_state == BtStateRecieving &&
  166. (furi_hal_rtc_get_timestamp() - app->last_packet > 5))
  167. app->bt_state = BtStateLost;
  168. }
  169. ble_profile_serial_set_event_callback(app->ble_serial_profile, 0, NULL, NULL);
  170. bt_disconnect(app->bt);
  171. // Wait 2nd core to update nvm storage
  172. furi_delay_ms(200);
  173. bt_keys_storage_set_default_path(app->bt);
  174. furi_check(bt_profile_restore_default(app->bt));
  175. pc_monitor_free(app);
  176. return 0;
  177. }