فهرست منبع

Update 1.1

1. Updated for latest firmware (thanks @NaejEL)
2. Separated views
3. Desktop app QR code
Oleg Logvinov 10 ماه پیش
والد
کامیت
f4d0bd580e
15فایلهای تغییر یافته به همراه383 افزوده شده و 120 حذف شده
  1. 3 1
      README.md
  2. 4 3
      application.fam
  3. 0 0
      assets/icon_10px.png
  4. BIN
      assets/qr_33px.png
  5. 121 0
      helpers/ble_serial.c
  6. 60 0
      helpers/ble_serial.h
  7. BIN
      icons/icon_10px.pdn
  8. 43 111
      pc_monitor.c
  9. 11 5
      pc_monitor.h
  10. 93 0
      views/bars_view.c
  11. 6 0
      views/bars_view.h
  12. 13 0
      views/connect_view.c
  13. 7 0
      views/connect_view.h
  14. 16 0
      views/status_view.c
  15. 6 0
      views/status_view.h

+ 3 - 1
README.md

@@ -1,4 +1,6 @@
 # PC Monitor
 Flipper Application for monitoring PC resources
 
-**[A backend running on your PC is required](https://github.com/TheSainEyereg/flipper-pc-monitor-backend/releases)**
+**[A backend running on your PC is required](https://github.com/TheSainEyereg/flipper-pc-monitor-backend/releases)**
+
+Thanks [NaejEL](https://github.com/NaejEL) for bringing this application back to life

+ 4 - 3
application.fam

@@ -5,9 +5,10 @@ App(
     entry_point="pc_monitor_app",
     requires=["bt", "gui"],
     stack_size=1 * 1024,
-	fap_description="Application for monitoring PC resources",
+    fap_description="Application for monitoring PC resources",
     fap_category="Bluetooth",
-    fap_icon="icons/icon_10px.png",
-    fap_version="1.0",
+    fap_icon_assets="assets",
+    fap_icon="assets/icon_10px.png",
+    fap_version="1.1",
     fap_author="Olejka",
 )

+ 0 - 0
icons/icon_10px.png → assets/icon_10px.png


BIN
assets/qr_33px.png


+ 121 - 0
helpers/ble_serial.c

@@ -0,0 +1,121 @@
+/*
+ * This code is based on the NaejEL's (https://github.com/NaejEL) BLE fix.
+ * 
+ * Thank you to NaejEL for providing this code and making it available under the https://github.com/Flipper-XFW/Xtreme-Apps repository.
+ * Your contribution has been invaluable for this project.
+ */
+
+#include "ble_serial.h"
+
+#include <gap.h>
+#include <furi_ble/profile_interface.h>
+#include <services/serial_service.h>
+#include <furi.h>
+
+typedef struct {
+    FuriHalBleProfileBase base;
+
+    BleServiceSerial* serial_svc;
+} BleProfileSerial;
+_Static_assert(offsetof(BleProfileSerial, base) == 0, "Wrong layout");
+
+static FuriHalBleProfileBase* ble_profile_serial_start(FuriHalBleProfileParams profile_params) {
+    UNUSED(profile_params);
+
+    BleProfileSerial* profile = malloc(sizeof(BleProfileSerial));
+
+    profile->base.config = ble_profile_serial;
+
+    profile->serial_svc = ble_svc_serial_start();
+
+    return &profile->base;
+}
+
+static void ble_profile_serial_stop(FuriHalBleProfileBase* profile) {
+    furi_check(profile);
+    furi_check(profile->config == ble_profile_serial);
+
+    BleProfileSerial* serial_profile = (BleProfileSerial*)profile;
+    ble_svc_serial_stop(serial_profile->serial_svc);
+}
+
+static GapConfig serial_template_config = {
+    .adv_service_uuid = 0x3080,
+    .appearance_char = 0x8600,
+    .bonding_mode = true,
+    .pairing_method = GapPairingPinCodeShow,
+    .conn_param = {
+        .conn_int_min = 0x18, // 30 ms
+        .conn_int_max = 0x24, // 45 ms
+        .slave_latency = 0,
+        .supervisor_timeout = 0,
+    }};
+
+static void
+    ble_profile_serial_get_config(GapConfig* config, FuriHalBleProfileParams profile_params) {
+    BleProfileSerialParams* serial_profile_params = profile_params;
+
+    furi_check(config);
+    memcpy(config, &serial_template_config, sizeof(GapConfig));
+    // Set mac address
+    memcpy(config->mac_address, furi_hal_version_get_ble_mac(), sizeof(config->mac_address));
+
+    // Change MAC address for HID profile
+    config->mac_address[2]++;
+    if(serial_profile_params) {
+        config->mac_address[0] ^= serial_profile_params->mac_xor;
+        config->mac_address[1] ^= serial_profile_params->mac_xor >> 8;
+    }
+
+    // Set advertise name
+    memset(config->adv_name, 0, sizeof(config->adv_name));
+
+    const char* clicker_str = "Serial";
+    if(serial_profile_params && serial_profile_params->device_name_prefix) {
+        clicker_str = serial_profile_params->device_name_prefix;
+    }
+    // We don't have Flipper in BLE name, use printf instead of replace
+    FuriString* name = furi_string_alloc_printf(
+        "%c%s %s",
+        furi_hal_version_get_ble_local_device_name_ptr()[0],
+        clicker_str,
+        furi_hal_version_get_ble_local_device_name_ptr() + 1);
+    if(furi_string_size(name) >= sizeof(config->adv_name)) {
+        furi_string_left(name, sizeof(config->adv_name) - 1);
+    }
+    memcpy(config->adv_name, furi_string_get_cstr(name), furi_string_size(name));
+    furi_string_free(name);
+
+    config->adv_service_uuid |= furi_hal_version_get_hw_color();
+}
+
+static const FuriHalBleProfileTemplate profile_callbacks = {
+    .start = ble_profile_serial_start,
+    .stop = ble_profile_serial_stop,
+    .get_gap_config = ble_profile_serial_get_config,
+};
+
+const FuriHalBleProfileTemplate* ble_profile_serial = &profile_callbacks;
+
+void ble_profile_serial_set_event_callback(
+    FuriHalBleProfileBase* profile,
+    uint16_t buff_size,
+    FuriHalBtSerialCallback callback,
+    void* context) {
+    furi_check(profile && (profile->config == ble_profile_serial));
+
+    BleProfileSerial* serial_profile = (BleProfileSerial*)profile;
+    ble_svc_serial_set_callbacks(serial_profile->serial_svc, buff_size, callback, context);
+}
+
+bool ble_profile_serial_tx(FuriHalBleProfileBase* profile, uint8_t* data, uint16_t size) {
+    furi_check(profile && (profile->config == ble_profile_serial));
+
+    BleProfileSerial* serial_profile = (BleProfileSerial*)profile;
+
+    if(size > BLE_PROFILE_SERIAL_PACKET_SIZE_MAX) {
+        return false;
+    }
+
+    return ble_svc_serial_update_tx(serial_profile->serial_svc, data, size);
+}

+ 60 - 0
helpers/ble_serial.h

@@ -0,0 +1,60 @@
+/*
+ * This code is based on the NaejEL's (https://github.com/NaejEL) BLE fix.
+ * 
+ * Thank you to NaejEL for providing this code and making it available under the https://github.com/Flipper-XFW/Xtreme-Apps repository.
+ * Your contribution has been invaluable for this project.
+ */
+
+#pragma once
+
+#include <furi_ble/profile_interface.h>
+
+#include <services/serial_service.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+ * Optional arguments to pass along with profile template as 
+ * FuriHalBleProfileParams for tuning profile behavior 
+ **/
+typedef struct {
+    const char* device_name_prefix; /**< Prefix for device name. Length must be less than 8 */
+    uint16_t mac_xor; /**< XOR mask for device address, for uniqueness */
+} BleProfileSerialParams;
+
+#define BLE_PROFILE_SERIAL_PACKET_SIZE_MAX BLE_SVC_SERIAL_DATA_LEN_MAX
+
+/** Serial service callback type */
+typedef SerialServiceEventCallback FuriHalBtSerialCallback;
+
+/** Serial profile descriptor */
+extern const FuriHalBleProfileTemplate* ble_profile_serial;
+
+/** Send data through BLE
+ *
+ * @param profile       Profile instance
+ * @param data          data buffer
+ * @param size          data buffer size
+ *
+ * @return      true on success
+ */
+bool ble_profile_serial_tx(FuriHalBleProfileBase* profile, uint8_t* data, uint16_t size);
+
+/** Set Serial service events callback
+ *
+ * @param profile       Profile instance
+ * @param buffer_size   Applicaition buffer size
+ * @param calback       FuriHalBtSerialCallback instance
+ * @param context       pointer to context
+ */
+void ble_profile_serial_set_event_callback(
+    FuriHalBleProfileBase* profile,
+    uint16_t buff_size,
+    FuriHalBtSerialCallback callback,
+    void* context);
+
+#ifdef __cplusplus
+}
+#endif

BIN
icons/icon_10px.pdn


+ 43 - 111
pc_monitor.c

@@ -4,106 +4,18 @@ static void render_callback(Canvas* canvas, void* ctx) {
     furi_assert(ctx);
     PcMonitorApp* app = ctx;
 
-    if(app->bt_state == BtStateRecieving) {
-        canvas_clear(canvas);
-        canvas_set_color(canvas, ColorBlack);
-        canvas_set_font(canvas, FontKeyboard);
-
-        uint8_t line = 0;
-        uint8_t spacing = app->lines_count ? SCREEN_HEIGHT / app->lines_count : 0;
-        uint8_t margin_top = spacing ? (spacing - LINE_HEIGHT) / 2 : 0;
-        char str[32];
-
-        if(app->data.cpu_usage <= 100) {
-            if(app->lines_count) {
-                canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "CPU");
-                snprintf(str, 32, "%d%%", app->data.cpu_usage);
-                elements_progress_bar_with_text(
-                    canvas,
-                    BAR_X,
-                    margin_top + line * spacing,
-                    BAR_WIDTH,
-                    app->data.cpu_usage / 100.0f,
-                    str);
-            }
-
-            line++;
-        }
-
-        if(app->data.ram_usage <= 100) {
-            if(app->lines_count) {
-                canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "RAM");
-                snprintf(
-                    str,
-                    32,
-                    "%.1f/%.1f %s",
-                    (double)(app->data.ram_max * 0.1f * app->data.ram_usage * 0.01f),
-                    (double)(app->data.ram_max * 0.1f),
-                    app->data.ram_unit);
-                elements_progress_bar_with_text(
-                    canvas,
-                    BAR_X,
-                    margin_top + line * spacing,
-                    BAR_WIDTH,
-                    app->data.ram_usage * 0.01f,
-                    str);
-            }
-
-            line++;
-        }
-
-        if(app->data.gpu_usage <= 100) {
-            if(app->lines_count) {
-                canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "GPU");
-                snprintf(str, 32, "%d%%", app->data.gpu_usage);
-                elements_progress_bar_with_text(
-                    canvas,
-                    BAR_X,
-                    margin_top + line * spacing,
-                    BAR_WIDTH,
-                    app->data.gpu_usage / 100.0f,
-                    str);
-            }
-
-            line++;
-        }
-
-        if(app->data.vram_usage <= 100) {
-            if(app->lines_count) {
-                canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "VRAM");
-                snprintf(
-                    str,
-                    32,
-                    "%.1f/%.1f %s",
-                    (double)(app->data.vram_max * 0.1f * app->data.vram_usage * 0.01f),
-                    (double)(app->data.vram_max * 0.1f),
-                    app->data.vram_unit);
-                elements_progress_bar_with_text(
-                    canvas,
-                    BAR_X,
-                    margin_top + line * spacing,
-                    BAR_WIDTH,
-                    app->data.vram_usage * 0.01f,
-                    str);
-            }
-
-            line++;
-        }
-
-        if(line == 0) app->bt_state = BtStateNoData;
-        app->lines_count = line;
-    } else {
-        canvas_draw_str_aligned(
-            canvas,
-            64,
-            32,
-            AlignCenter,
-            AlignCenter,
-            app->bt_state == BtStateChecking ? "Checking BLE..." :
-            app->bt_state == BtStateInactive ? "BLE inactive!" :
-            app->bt_state == BtStateWaiting  ? "Waiting for data..." :
-            app->bt_state == BtStateLost     ? "Connection lost!" :
-                                               "No data!");
+    switch(app->bt_state) {
+    case BtStateWaiting:
+        draw_connect_view(canvas);
+        break;
+
+    case BtStateRecieving:
+        draw_bars_view(canvas, app);
+        break;
+
+    default:
+        draw_status_view(canvas, app);
+        break;
     }
 }
 
@@ -163,16 +75,27 @@ int32_t pc_monitor_app(void* p) {
     UNUSED(p);
     PcMonitorApp* app = pc_monitor_alloc();
 
-    if(furi_hal_bt_is_active()) {
-        furi_hal_bt_serial_set_event_callback(BT_SERIAL_BUFFER_SIZE, bt_serial_callback, app);
-        furi_hal_bt_start_advertising();
+    bt_disconnect(app->bt);
 
-        app->bt_state = BtStateWaiting;
-        FURI_LOG_D(TAG, "Bluetooth is active!");
-    } else {
-        app->bt_state = BtStateInactive;
-        FURI_LOG_W(TAG, "Please, enable the Bluetooth and restart the app");
-    }
+    // Wait 2nd core to update nvm storage
+    furi_delay_ms(200);
+
+    bt_keys_storage_set_storage_path(app->bt, APP_DATA_PATH(".bt_serial.keys"));
+
+    BleProfileSerialParams params = {
+        .device_name_prefix = "PC Mon",
+        .mac_xor = 0x0002,
+    };
+    app->ble_serial_profile = bt_profile_start(app->bt, ble_profile_serial, &params);
+
+    furi_check(app->ble_serial_profile);
+
+    ble_profile_serial_set_event_callback(
+        app->ble_serial_profile, BT_SERIAL_BUFFER_SIZE, bt_serial_callback, app);
+    furi_hal_bt_start_advertising();
+
+    app->bt_state = BtStateWaiting;
+    FURI_LOG_D(TAG, "Bluetooth is active!");
 
     // Main loop
     InputEvent event;
@@ -186,9 +109,18 @@ int32_t pc_monitor_app(void* p) {
             app->bt_state = BtStateLost;
     }
 
-    furi_hal_bt_serial_set_event_callback(0, NULL, NULL);
+    ble_profile_serial_set_event_callback(app->ble_serial_profile, 0, NULL, NULL);
+
+    bt_disconnect(app->bt);
+
+    // Wait 2nd core to update nvm storage
+    furi_delay_ms(200);
+
+    bt_keys_storage_set_default_path(app->bt);
+
+    furi_check(bt_profile_restore_default(app->bt));
 
     pc_monitor_free(app);
 
     return 0;
-}
+}

+ 11 - 5
pc_monitor.h

@@ -3,20 +3,25 @@
 #include <furi.h>
 #include <furi_hal.h>
 #include <furi_hal_bt.h>
-#include <furi_hal_bt_serial.h>
+#include "helpers/ble_serial.h"
 #include <bt/bt_service/bt.h>
 #include <gui/gui.h>
 #include <gui/elements.h>
 #include <notification/notification_messages.h>
 #include <input/input.h>
+#include <storage/storage.h>
 
-#define TAG "PCMonitor"
+#include "views/bars_view.h"
+#include "views/connect_view.h"
+#include "views/status_view.h"
+
+#define TAG                   "PCMonitor"
 #define BT_SERIAL_BUFFER_SIZE 128
 
 #define SCREEN_HEIGHT 64
-#define LINE_HEIGHT 11
+#define LINE_HEIGHT   11
 
-#define BAR_X 30
+#define BAR_X     30
 #define BAR_WIDTH 97
 
 typedef enum {
@@ -48,9 +53,10 @@ typedef struct {
     FuriMutex* app_mutex;
     FuriMessageQueue* event_queue;
     NotificationApp* notification;
+    FuriHalBleProfileBase* ble_serial_profile;
 
     BtState bt_state;
     DataStruct data;
     uint8_t lines_count;
     uint32_t last_packet;
-} PcMonitorApp;
+} PcMonitorApp;

+ 93 - 0
views/bars_view.c

@@ -0,0 +1,93 @@
+#include "bars_view.h"
+
+void draw_bars_view(Canvas* canvas, void* ctx) {
+    PcMonitorApp* app = ctx;
+
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_set_font(canvas, FontKeyboard);
+
+    uint8_t line = 0;
+    uint8_t spacing = app->lines_count ? SCREEN_HEIGHT / app->lines_count : 0;
+    uint8_t margin_top = spacing ? (spacing - LINE_HEIGHT) / 2 : 0;
+    char str[32];
+
+    if(app->data.cpu_usage <= 100) {
+        if(app->lines_count) {
+            canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "CPU");
+            snprintf(str, 32, "%d%%", app->data.cpu_usage);
+            elements_progress_bar_with_text(
+                canvas,
+                BAR_X,
+                margin_top + line * spacing,
+                BAR_WIDTH,
+                app->data.cpu_usage / 100.0f,
+                str);
+        }
+
+        line++;
+    }
+
+    if(app->data.ram_usage <= 100) {
+        if(app->lines_count) {
+            canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "RAM");
+            snprintf(
+                str,
+                32,
+                "%.1f/%.1f %s",
+                (double)(app->data.ram_max * 0.1f * app->data.ram_usage * 0.01f),
+                (double)(app->data.ram_max * 0.1f),
+                app->data.ram_unit);
+            elements_progress_bar_with_text(
+                canvas,
+                BAR_X,
+                margin_top + line * spacing,
+                BAR_WIDTH,
+                app->data.ram_usage * 0.01f,
+                str);
+        }
+
+        line++;
+    }
+
+    if(app->data.gpu_usage <= 100) {
+        if(app->lines_count) {
+            canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "GPU");
+            snprintf(str, 32, "%d%%", app->data.gpu_usage);
+            elements_progress_bar_with_text(
+                canvas,
+                BAR_X,
+                margin_top + line * spacing,
+                BAR_WIDTH,
+                app->data.gpu_usage / 100.0f,
+                str);
+        }
+
+        line++;
+    }
+
+    if(app->data.vram_usage <= 100) {
+        if(app->lines_count) {
+            canvas_draw_str(canvas, 1, margin_top + line * spacing + 9, "VRAM");
+            snprintf(
+                str,
+                32,
+                "%.1f/%.1f %s",
+                (double)(app->data.vram_max * 0.1f * app->data.vram_usage * 0.01f),
+                (double)(app->data.vram_max * 0.1f),
+                app->data.vram_unit);
+            elements_progress_bar_with_text(
+                canvas,
+                BAR_X,
+                margin_top + line * spacing,
+                BAR_WIDTH,
+                app->data.vram_usage * 0.01f,
+                str);
+        }
+
+        line++;
+    }
+
+    if(line == 0) app->bt_state = BtStateNoData;
+    app->lines_count = line;
+}

+ 6 - 0
views/bars_view.h

@@ -0,0 +1,6 @@
+#pragma once
+
+#include <gui/gui.h>
+#include "../pc_monitor.h"
+
+void draw_bars_view(Canvas* canvas, void* ctx);

+ 13 - 0
views/connect_view.c

@@ -0,0 +1,13 @@
+#include "connect_view.h"
+
+void draw_connect_view(Canvas* canvas) {
+    canvas_draw_str(
+        canvas, 0, 10, "Waiting for connection...");
+
+    canvas_draw_str(
+        canvas, 0, 40, "Download back-end");
+    canvas_draw_str(
+        canvas, 0, 50, "app for your PC from:");
+
+    canvas_draw_icon(canvas, 128-33, 64-33, &I_qr_33px);
+}

+ 7 - 0
views/connect_view.h

@@ -0,0 +1,7 @@
+#pragma once
+
+#include <gui/gui.h>
+#include <pc_monitor_icons.h>
+#include "../pc_monitor.h"
+
+void draw_connect_view(Canvas* canvas);

+ 16 - 0
views/status_view.c

@@ -0,0 +1,16 @@
+#include "status_view.h"
+
+void draw_status_view(Canvas* canvas, void* ctx) {
+    PcMonitorApp* app = ctx;
+
+    canvas_draw_str_aligned(
+        canvas,
+        64,
+        32,
+        AlignCenter,
+        AlignCenter,
+        app->bt_state == BtStateChecking ? "Checking BLE..." :
+        app->bt_state == BtStateInactive ? "BLE inactive!" :
+        app->bt_state == BtStateLost     ? "Connection lost!" :
+                                           "No data!");
+}

+ 6 - 0
views/status_view.h

@@ -0,0 +1,6 @@
+#pragma once
+
+#include <gui/gui.h>
+#include "../pc_monitor.h"
+
+void draw_status_view(Canvas* canvas, void* ctx);