pc_monitor.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "CPU");
  15. snprintf(str, 32, "%d%%", app->data.cpu_usage);
  16. elements_progress_bar_with_text(
  17. canvas, BAR_X, margin_top + line * spacing, BAR_WIDTH, app->data.cpu_usage / 100.0f, str);
  18. line++;
  19. }
  20. if(app->data.ram_usage <= 100) {
  21. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "RAM");
  22. snprintf(
  23. str,
  24. 32,
  25. "%.1f/%.1f %s",
  26. (double)(app->data.ram_max * 0.1f * app->data.ram_usage * 0.01f),
  27. (double)(app->data.ram_max * 0.1f),
  28. app->data.ram_unit);
  29. elements_progress_bar_with_text(
  30. canvas, BAR_X, margin_top + line * spacing, BAR_WIDTH, app->data.ram_usage * 0.01f, str);
  31. line++;
  32. }
  33. if(app->data.gpu_usage <= 100) {
  34. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "GPU");
  35. snprintf(str, 32, "%d%%", app->data.gpu_usage);
  36. elements_progress_bar_with_text(
  37. canvas, BAR_X, margin_top + line * spacing, BAR_WIDTH, app->data.gpu_usage / 100.0f, str);
  38. line++;
  39. }
  40. if(app->data.vram_usage <= 100) {
  41. canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "VRAM");
  42. snprintf(
  43. str,
  44. 32,
  45. "%.1f/%.1f %s",
  46. (double)(app->data.vram_max * 0.1f * app->data.vram_usage * 0.01f),
  47. (double)(app->data.vram_max * 0.1f),
  48. app->data.vram_unit);
  49. elements_progress_bar_with_text(
  50. canvas, BAR_X, margin_top + line * spacing, BAR_WIDTH, app->data.vram_usage * 0.01f, str);
  51. line++;
  52. }
  53. if (line == 0) app->bt_state = BtStateNoData;
  54. app->lines_count = line;
  55. } else {
  56. canvas_draw_str_aligned(
  57. canvas,
  58. 64,
  59. 32,
  60. AlignCenter,
  61. AlignCenter,
  62. app->bt_state == BtStateChecking ? "Checking BLE..." :
  63. app->bt_state == BtStateInactive ? "BLE inactive!" :
  64. app->bt_state == BtStateWaiting ? "Waiting for data..." :
  65. app->bt_state == BtStateLost ? "Connection lost!" :
  66. "No data!");
  67. }
  68. }
  69. static void input_callback(InputEvent* input_event, void* ctx) {
  70. furi_assert(ctx);
  71. FuriMessageQueue* event_queue = ctx;
  72. furi_message_queue_put(event_queue, input_event, FuriWaitForever);
  73. }
  74. static uint16_t bt_serial_callback(SerialServiceEvent event, void* ctx) {
  75. furi_assert(ctx);
  76. PcMonitorApp* app = ctx;
  77. if(event.event == SerialServiceEventTypeDataReceived) {
  78. FURI_LOG_D(
  79. TAG,
  80. "SerialServiceEventTypeDataReceived. Size: %u/%u. Data: %s",
  81. event.data.size,
  82. sizeof(DataStruct),
  83. (char*)event.data.buffer);
  84. if(event.data.size == sizeof(DataStruct)) {
  85. memcpy(&app->data, event.data.buffer, sizeof(DataStruct));
  86. app->bt_state = BtStateRecieving;
  87. app->last_packet = furi_hal_rtc_get_timestamp();
  88. }
  89. }
  90. return 0;
  91. }
  92. static PcMonitorApp* pc_monitor_alloc() {
  93. PcMonitorApp* app = malloc(sizeof(PcMonitorApp));
  94. app->view_port = view_port_alloc();
  95. app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  96. app->notification = furi_record_open(RECORD_NOTIFICATION);
  97. app->gui = furi_record_open(RECORD_GUI);
  98. app->bt = furi_record_open(RECORD_BT);
  99. app->data.cpu_usage = UINT8_MAX;
  100. app->data.ram_usage = UINT8_MAX;
  101. app->data.gpu_usage = UINT8_MAX;
  102. app->data.vram_usage = UINT8_MAX;
  103. gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
  104. view_port_draw_callback_set(app->view_port, render_callback, app);
  105. view_port_input_callback_set(app->view_port, input_callback, app->event_queue);
  106. return app;
  107. }
  108. static void pc_monitor_free(PcMonitorApp* app) {
  109. gui_remove_view_port(app->gui, app->view_port);
  110. view_port_free(app->view_port);
  111. furi_message_queue_free(app->event_queue);
  112. furi_record_close(RECORD_NOTIFICATION);
  113. furi_record_close(RECORD_GUI);
  114. furi_record_close(RECORD_BT);
  115. free(app);
  116. }
  117. int32_t pc_monitor_app(void* p) {
  118. UNUSED(p);
  119. PcMonitorApp* app = pc_monitor_alloc();
  120. if(furi_hal_bt_is_active()) {
  121. furi_hal_bt_serial_set_event_callback(BT_SERIAL_BUFFER_SIZE, bt_serial_callback, app);
  122. furi_hal_bt_start_advertising();
  123. app->bt_state = BtStateWaiting;
  124. FURI_LOG_D(TAG, "Bluetooth is active!");
  125. } else {
  126. app->bt_state = BtStateInactive;
  127. FURI_LOG_W(TAG, "Please, enable the Bluetooth and restart the app");
  128. }
  129. // Main loop
  130. InputEvent event;
  131. while(true) {
  132. if(furi_message_queue_get(app->event_queue, &event, 1) == FuriStatusOk) {
  133. if(event.type == InputTypeShort && event.key == InputKeyBack) break;
  134. }
  135. if(app->bt_state == BtStateRecieving &&
  136. (furi_hal_rtc_get_timestamp() - app->last_packet > 5))
  137. app->bt_state = BtStateLost;
  138. }
  139. furi_hal_bt_serial_set_event_callback(0, NULL, NULL);
  140. pc_monitor_free(app);
  141. return 0;
  142. }