Skip to content

Commit

Permalink
ble: profile rework (#3272)
Browse files Browse the repository at this point in the history
* ble: profile rework, initial
* apps: hid: fix for pairing cleanup
* app: hid: select transport based on #define
* fixing PVS warnings
* ble: serial service: fixed uid naming
* bt service: on-demand dialog init; ble profiles: docs; battery svc: proper update
* Added shci_cmd_resp_wait/shci_cmd_resp_release impl with semaphore
* app: hid: separated transport code
* ble: fixed service init order for serial svc; moved hardfault check to ble_glue
* cli: ps: added thread prio to output, fixed heap display
* ble_glue: naming changes; separate thread for event processing;
* furi: added runtime stats; cli: added cpu% to `ps`
* cli: fixed thread time calculation
* furi: added getter for thread priority
* fixing pvs warnings
* hid profile: fixed naming
* more naming fixes
* hal: ble init small cleanup
* cleanup & draft beacon api
* f18: api sync
* apps: moved example_custom_font from debug to examples
* BLE extra beacon demo app
* naming fix
* UI fixes for demo app (wip)
* desktop, ble svc: added statusbar icon for beacon
* minor cleanup
* Minor cleanup & naming fixes
* api sync
* Removed stale header
* hal: added FURI_BLE_EXTRA_LOG for extra logging; comments & code cleanup
* naming & macro fixes
* quick fixes from review
* Eliminated stock svc_ctl
* cli: ps: removed runtime stats
* minor include fixes
* (void)
* naming fixes
* More naming fixes
* fbt: always build all libs
* fbt: explicitly globbing libs; dist: logging SDK path
* scripts: fixed lib path precedence
* hal: bt: profiles: naming changes, support for passing params to a profile; include cleanup
* ble: hid: added parameter processing for profile template
* api sync
* BLE HID: long name trim
* Removed unused check
* desktop: updated beacon status icon; ble: hid: cleaner device name management
* desktop: updated status icon

Co-authored-by: あく <[email protected]>
Co-authored-by: nminaylov <[email protected]>
  • Loading branch information
3 people authored Feb 16, 2024
1 parent 8780437 commit 60a9d7e
Show file tree
Hide file tree
Showing 91 changed files with 3,352 additions and 1,730 deletions.
11 changes: 11 additions & 0 deletions applications/examples/example_ble_beacon/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
App(
appid="example_ble_beacon",
name="Example: BLE Beacon",
apptype=FlipperAppType.EXTERNAL,
entry_point="ble_beacon_app",
requires=["gui"],
stack_size=1 * 1024,
fap_icon="example_ble_beacon_10px.png",
fap_category="Examples",
fap_icon_assets="images",
)
149 changes: 149 additions & 0 deletions applications/examples/example_ble_beacon/ble_beacon_app.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#include "ble_beacon_app.h"

#include <extra_beacon.h>
#include <furi_hal_version.h>

#include <string.h>

#define TAG "ble_beacon_app"

static bool ble_beacon_app_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
BleBeaconApp* app = context;
return scene_manager_handle_custom_event(app->scene_manager, event);
}

static bool ble_beacon_app_back_event_callback(void* context) {
furi_assert(context);
BleBeaconApp* app = context;
return scene_manager_handle_back_event(app->scene_manager);
}

static void ble_beacon_app_tick_event_callback(void* context) {
furi_assert(context);
BleBeaconApp* app = context;
scene_manager_handle_tick_event(app->scene_manager);
}

static void ble_beacon_app_restore_beacon_state(BleBeaconApp* app) {
// Restore beacon data from service
GapExtraBeaconConfig* local_config = &app->beacon_config;
const GapExtraBeaconConfig* config = furi_hal_bt_extra_beacon_get_config();
if(config) {
// We have a config, copy it
memcpy(local_config, config, sizeof(app->beacon_config));
} else {
// No config, set up default values - they will stay until overriden or device is reset
local_config->min_adv_interval_ms = 50;
local_config->max_adv_interval_ms = 150;

local_config->adv_channel_map = GapAdvChannelMapAll;
local_config->adv_power_level = GapAdvPowerLevel_0dBm;

local_config->address_type = GapAddressTypePublic;
memcpy(
local_config->address, furi_hal_version_get_ble_mac(), sizeof(local_config->address));
// Modify MAC address to make it different from the one used by the main app
local_config->address[0] ^= 0xFF;
local_config->address[3] ^= 0xFF;

furi_check(furi_hal_bt_extra_beacon_set_config(local_config));
}

// Get beacon state
app->is_beacon_active = furi_hal_bt_extra_beacon_is_active();

// Restore last beacon data
app->beacon_data_len = furi_hal_bt_extra_beacon_get_data(app->beacon_data);
}

static BleBeaconApp* ble_beacon_app_alloc() {
BleBeaconApp* app = malloc(sizeof(BleBeaconApp));

app->gui = furi_record_open(RECORD_GUI);

app->scene_manager = scene_manager_alloc(&ble_beacon_app_scene_handlers, app);
app->view_dispatcher = view_dispatcher_alloc();

app->status_string = furi_string_alloc();

view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
view_dispatcher_set_custom_event_callback(
app->view_dispatcher, ble_beacon_app_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, ble_beacon_app_back_event_callback);
view_dispatcher_set_tick_event_callback(
app->view_dispatcher, ble_beacon_app_tick_event_callback, 100);
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_enable_queue(app->view_dispatcher);

app->submenu = submenu_alloc();
view_dispatcher_add_view(
app->view_dispatcher, BleBeaconAppViewSubmenu, submenu_get_view(app->submenu));

app->dialog_ex = dialog_ex_alloc();
view_dispatcher_add_view(
app->view_dispatcher, BleBeaconAppViewDialog, dialog_ex_get_view(app->dialog_ex));

app->byte_input = byte_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, BleBeaconAppViewByteInput, byte_input_get_view(app->byte_input));

ble_beacon_app_restore_beacon_state(app);

return app;
}

static void ble_beacon_app_free(BleBeaconApp* app) {
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewByteInput);
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewSubmenu);
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewDialog);

free(app->byte_input);
free(app->submenu);
free(app->dialog_ex);

free(app->scene_manager);
free(app->view_dispatcher);

free(app->status_string);

furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_GUI);
app->gui = NULL;

free(app);
}

int32_t ble_beacon_app(void* args) {
UNUSED(args);

BleBeaconApp* app = ble_beacon_app_alloc();

scene_manager_next_scene(app->scene_manager, BleBeaconAppSceneRunBeacon);

view_dispatcher_run(app->view_dispatcher);

ble_beacon_app_free(app);
return 0;
}

void ble_beacon_app_update_state(BleBeaconApp* app) {
furi_hal_bt_extra_beacon_stop();

furi_check(furi_hal_bt_extra_beacon_set_config(&app->beacon_config));

app->beacon_data_len = 0;
while((app->beacon_data[app->beacon_data_len] != 0) &&
(app->beacon_data_len < sizeof(app->beacon_data))) {
app->beacon_data_len++;
}

FURI_LOG_I(TAG, "beacon_data_len: %d", app->beacon_data_len);

furi_check(furi_hal_bt_extra_beacon_set_data(app->beacon_data, app->beacon_data_len));

if(app->is_beacon_active) {
furi_check(furi_hal_bt_extra_beacon_start());
}
}
50 changes: 50 additions & 0 deletions applications/examples/example_ble_beacon/ble_beacon_app.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include "extra_beacon.h"
#include <furi.h>
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/scene_manager.h>
#include <gui/view_dispatcher.h>

#include <gui/modules/widget.h>
#include <gui/modules/submenu.h>
#include <gui/modules/byte_input.h>
#include <gui/modules/dialog_ex.h>

#include <rpc/rpc_app.h>
#include <notification/notification_messages.h>

#include <furi_hal_bt.h>

#include "scenes/scenes.h"
#include <stdint.h>

typedef struct {
Gui* gui;
SceneManager* scene_manager;
ViewDispatcher* view_dispatcher;

Submenu* submenu;
ByteInput* byte_input;
DialogEx* dialog_ex;

FuriString* status_string;

GapExtraBeaconConfig beacon_config;
uint8_t beacon_data[EXTRA_BEACON_MAX_DATA_SIZE];
uint8_t beacon_data_len;
bool is_beacon_active;
} BleBeaconApp;

typedef enum {
BleBeaconAppViewSubmenu,
BleBeaconAppViewByteInput,
BleBeaconAppViewDialog,
} BleBeaconAppView;

typedef enum {
BleBeaconAppCustomEventDataEditResult = 100,
} BleBeaconAppCustomEvent;

void ble_beacon_app_update_state(BleBeaconApp* app);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ADD_SCENE(ble_beacon_app, menu, Menu)
ADD_SCENE(ble_beacon_app, input_mac_addr, InputMacAddress)
ADD_SCENE(ble_beacon_app, input_beacon_data, InputBeaconData)
ADD_SCENE(ble_beacon_app, run_beacon, RunBeacon)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "../ble_beacon_app.h"

static void ble_beacon_app_scene_add_type_byte_input_callback(void* context) {
BleBeaconApp* ble_beacon = context;
view_dispatcher_send_custom_event(
ble_beacon->view_dispatcher, BleBeaconAppCustomEventDataEditResult);
}

void ble_beacon_app_scene_input_beacon_data_on_enter(void* context) {
BleBeaconApp* ble_beacon = context;
byte_input_set_header_text(ble_beacon->byte_input, "Enter beacon data");

byte_input_set_result_callback(
ble_beacon->byte_input,
ble_beacon_app_scene_add_type_byte_input_callback,
NULL,
context,
ble_beacon->beacon_data,
sizeof(ble_beacon->beacon_data));

view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewByteInput);
}

bool ble_beacon_app_scene_input_beacon_data_on_event(void* context, SceneManagerEvent event) {
BleBeaconApp* ble_beacon = context;
SceneManager* scene_manager = ble_beacon->scene_manager;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == BleBeaconAppCustomEventDataEditResult) {
ble_beacon_app_update_state(ble_beacon);
scene_manager_previous_scene(scene_manager);
return true;
}
}

return false;
}

void ble_beacon_app_scene_input_beacon_data_on_exit(void* context) {
BleBeaconApp* ble_beacon = context;

byte_input_set_result_callback(ble_beacon->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(ble_beacon->byte_input, NULL);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "../ble_beacon_app.h"

static void ble_beacon_app_scene_add_type_byte_input_callback(void* context) {
BleBeaconApp* ble_beacon = context;
view_dispatcher_send_custom_event(
ble_beacon->view_dispatcher, BleBeaconAppCustomEventDataEditResult);
}

void ble_beacon_app_scene_input_mac_addr_on_enter(void* context) {
BleBeaconApp* ble_beacon = context;
byte_input_set_header_text(ble_beacon->byte_input, "Enter MAC (reversed)");

byte_input_set_result_callback(
ble_beacon->byte_input,
ble_beacon_app_scene_add_type_byte_input_callback,
NULL,
context,
ble_beacon->beacon_config.address,
sizeof(ble_beacon->beacon_config.address));

view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewByteInput);
}

bool ble_beacon_app_scene_input_mac_addr_on_event(void* context, SceneManagerEvent event) {
BleBeaconApp* ble_beacon = context;
SceneManager* scene_manager = ble_beacon->scene_manager;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == BleBeaconAppCustomEventDataEditResult) {
ble_beacon_app_update_state(ble_beacon);
scene_manager_previous_scene(scene_manager);
return true;
}
}

return false;
}

void ble_beacon_app_scene_input_mac_addr_on_exit(void* context) {
BleBeaconApp* ble_beacon = context;

byte_input_set_result_callback(ble_beacon->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(ble_beacon->byte_input, NULL);
}
56 changes: 56 additions & 0 deletions applications/examples/example_ble_beacon/scenes/scene_menu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "../ble_beacon_app.h"

enum SubmenuIndex {
SubmenuIndexSetMac,
SubmenuIndexSetData,
};

static void ble_beacon_app_scene_menu_submenu_callback(void* context, uint32_t index) {
BleBeaconApp* ble_beacon = context;
view_dispatcher_send_custom_event(ble_beacon->view_dispatcher, index);
}

void ble_beacon_app_scene_menu_on_enter(void* context) {
BleBeaconApp* ble_beacon = context;
Submenu* submenu = ble_beacon->submenu;

submenu_add_item(
submenu,
"Set MAC",
SubmenuIndexSetMac,
ble_beacon_app_scene_menu_submenu_callback,
ble_beacon);
submenu_add_item(
submenu,
"Set Data",
SubmenuIndexSetData,
ble_beacon_app_scene_menu_submenu_callback,
ble_beacon);

view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewSubmenu);
}

bool ble_beacon_app_scene_menu_on_event(void* context, SceneManagerEvent event) {
BleBeaconApp* ble_beacon = context;
SceneManager* scene_manager = ble_beacon->scene_manager;

bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
const uint32_t submenu_index = event.event;
if(submenu_index == SubmenuIndexSetMac) {
scene_manager_next_scene(scene_manager, BleBeaconAppSceneInputMacAddress);
consumed = true;
} else if(submenu_index == SubmenuIndexSetData) {
scene_manager_next_scene(scene_manager, BleBeaconAppSceneInputBeaconData);
consumed = true;
}
}

return consumed;
}

void ble_beacon_app_scene_menu_on_exit(void* context) {
BleBeaconApp* ble_beacon = context;
submenu_reset(ble_beacon->submenu);
}
Loading

0 comments on commit 60a9d7e

Please sign in to comment.