Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
Merge branch 'ble-refactor' into xfw-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Willy-JL committed Feb 17, 2024
2 parents 895627d + 0690071 commit ceae2bb
Show file tree
Hide file tree
Showing 117 changed files with 4,894 additions and 2,811 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 ceae2bb

Please sign in to comment.