From 5aa308ec50e98cbfcf0b08cb0965f9232e247d74 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 4 Apr 2024 23:11:43 -0400 Subject: [PATCH] Add Battery Reporting to FindMy --- applications/system/findmy/findmy.c | 22 +++++++++ applications/system/findmy/findmy_i.h | 6 +++ applications/system/findmy/findmy_state.c | 48 ++++++++++++++++--- applications/system/findmy/findmy_state.h | 5 ++ .../system/findmy/scenes/findmy_scene_main.c | 3 +- 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/applications/system/findmy/findmy.c b/applications/system/findmy/findmy.c index 1cafcf8cbd..da8bceb2ae 100644 --- a/applications/system/findmy/findmy.c +++ b/applications/system/findmy/findmy.c @@ -1,4 +1,5 @@ #include "findmy_i.h" +#include static bool findmy_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -148,6 +149,7 @@ void findmy_toggle_beacon(FindMy* app) { furi_check(furi_hal_bt_extra_beacon_start()); } findmy_main_update_active(app->findmy_main, furi_hal_bt_extra_beacon_is_active()); + findmy_update_battery(app, app->state.battery_level); } void findmy_set_tag_type(FindMy* app, FindMyType type) { @@ -158,6 +160,26 @@ void findmy_set_tag_type(FindMy* app, FindMyType type) { FURI_LOG_I("TagType2", "Tag Type: %d", type); } +void findmy_update_battery(FindMy* app, uint8_t battery_level) { + uint32_t battery_capacity = furi_hal_power_get_battery_full_capacity(); + uint32_t battery_remaining = furi_hal_power_get_battery_remaining_capacity(); + uint16_t battery_percent = (battery_remaining * 100) / battery_capacity; + + if(battery_percent > 80) { + battery_level = BATTERY_FULL; + } else if(battery_percent > 50) { + battery_level = BATTERY_MEDIUM; + } else if(battery_percent > 20) { + battery_level = BATTERY_LOW; + } else { + battery_level = BATTERY_CRITICAL; + } + + app->state.battery_level = battery_level; + findmy_state_sync_config(&app->state); + findmy_state_save(&app->state); +} + void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) { uint8_t tmp; for(size_t i = 0; i < GAP_MAC_ADDR_SIZE / 2; i++) { diff --git a/applications/system/findmy/findmy_i.h b/applications/system/findmy/findmy_i.h index af7458f8c8..2283b4a7aa 100644 --- a/applications/system/findmy/findmy_i.h +++ b/applications/system/findmy/findmy_i.h @@ -24,6 +24,11 @@ void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]); #endif +#define BATTERY_FULL 0x00 +#define BATTERY_MEDIUM 0x50 +#define BATTERY_LOW 0xA0 +#define BATTERY_CRITICAL 0xF0 + struct FindMy { Gui* gui; Storage* storage; @@ -54,3 +59,4 @@ void findmy_change_transmit_power(FindMy* app, uint8_t value); void findmy_toggle_show_mac(FindMy* app, bool show_mac); void findmy_set_tag_type(FindMy* app, FindMyType type); void findmy_toggle_beacon(FindMy* app); +void findmy_update_battery(FindMy* app, uint8_t battery_level); diff --git a/applications/system/findmy/findmy_state.c b/applications/system/findmy/findmy_state.c index ae81eab839..2f39c268ad 100644 --- a/applications/system/findmy/findmy_state.c +++ b/applications/system/findmy/findmy_state.c @@ -1,5 +1,6 @@ #include "findmy_state.h" +#include "findmy_i.h" #include #include #include @@ -42,6 +43,13 @@ bool findmy_state_load(FindMyState* out_state) { } state.tag_type = tmp; + if(!flipper_format_read_uint32(file, "battery_level", &tmp, 1)) { + tmp = 0x00; // Default battery level set to Full + flipper_format_rewind(file); + } + FURI_LOG_I("findmy_load", "Saved Battery: %ld", tmp); + state.battery_level = tmp; + if(!flipper_format_read_hex(file, "mac", state.mac, sizeof(state.mac))) break; if(!flipper_format_read_hex( @@ -74,12 +82,12 @@ bool findmy_state_load(FindMyState* out_state) { *data++ = 0x00; // ... *data++ = 0x12; // Type (FindMy) *data++ = 0x19; // Length - *data++ = 0x00; // Status + *data++ = 0x00; // Battery Status set to Full // Placeholder Empty Public Key without the MAC address for(size_t i = 0; i < 22; ++i) { *data++ = 0x00; } - *data++ = 0x00; // First 2 bits are the version, the rest is the battery level + *data++ = 0x00; // First 2 bits are the version *data++ = 0x00; // Hint (0x00) } @@ -102,12 +110,11 @@ void findmy_state_apply(FindMyState* state) { if(furi_hal_bt_extra_beacon_is_active()) { furi_check(furi_hal_bt_extra_beacon_stop()); } - furi_check(furi_hal_bt_extra_beacon_set_config(&state->config)); - + findmy_update_payload_battery(state->data, state->battery_level, state->tag_type); + furi_check( furi_hal_bt_extra_beacon_set_data(state->data, findmy_state_data_size(state->tag_type))); - if(state->beacon_active) { furi_check(furi_hal_bt_extra_beacon_start()); } @@ -118,6 +125,32 @@ void findmy_state_sync_config(FindMyState* state) { state->config.max_adv_interval_ms = (state->broadcast_interval * 1000) + 150; state->config.adv_power_level = GapAdvPowerLevel_0dBm + state->transmit_power; memcpy(state->config.address, state->mac, sizeof(state->config.address)); + findmy_update_payload_battery(state->data, state->battery_level, state->tag_type); +} + +void findmy_update_payload_battery(uint8_t* data, uint8_t battery_level, FindMyType type) { + // Update the battery level in the payload + FURI_LOG_I("update_bat", "Before update: %d", battery_level); + if(type == FindMyTypeApple) { + switch(battery_level) { + case BATTERY_FULL: + data[6] = BATTERY_FULL; + break; + case BATTERY_MEDIUM: + data[6] = BATTERY_MEDIUM; + break; + case BATTERY_LOW: + data[6] = BATTERY_LOW; + break; + case BATTERY_CRITICAL: + data[6] = BATTERY_CRITICAL; + break; + default: + FURI_LOG_E("update_bat", "Invalid battery level: %d", battery_level); + return; + } + } + FURI_LOG_I("update_bat", "After update: %02X", data[6]); } void findmy_state_save(FindMyState* state) { @@ -141,10 +174,13 @@ void findmy_state_save(FindMyState* state) { tmp = state->tag_type; if(!flipper_format_write_uint32(file, "tag_type", &tmp, 1)) break; + tmp = state->battery_level; + if(!flipper_format_write_uint32(file, "battery_level", &tmp, 1)) break; + if(!flipper_format_write_bool(file, "show_mac", &state->show_mac, 1)) break; if(!flipper_format_write_hex(file, "mac", state->mac, sizeof(state->mac))) break; - + findmy_update_payload_battery(state->data, state->battery_level, state->tag_type); if(!flipper_format_write_hex( file, "data", state->data, findmy_state_data_size(state->tag_type))) break; diff --git a/applications/system/findmy/findmy_state.h b/applications/system/findmy/findmy_state.h index 813dfee414..e6b60ec7be 100644 --- a/applications/system/findmy/findmy_state.h +++ b/applications/system/findmy/findmy_state.h @@ -13,6 +13,7 @@ typedef enum { FindMyTypeTile, } FindMyType; + typedef struct { bool beacon_active; uint8_t broadcast_interval; @@ -24,6 +25,8 @@ typedef struct { // Generated from the other state values GapExtraBeaconConfig config; + + uint8_t battery_level; } FindMyState; bool findmy_state_load(FindMyState* out_state); @@ -34,4 +37,6 @@ void findmy_state_sync_config(FindMyState* state); void findmy_state_save(FindMyState* state); +void findmy_update_payload_battery(uint8_t* data, uint8_t battery_level, FindMyType type); + uint8_t findmy_state_data_size(FindMyType type); diff --git a/applications/system/findmy/scenes/findmy_scene_main.c b/applications/system/findmy/scenes/findmy_scene_main.c index e70b59fc54..86501f13d2 100644 --- a/applications/system/findmy/scenes/findmy_scene_main.c +++ b/applications/system/findmy/scenes/findmy_scene_main.c @@ -10,7 +10,7 @@ void findmy_scene_main_on_enter(void* context) { FindMy* app = context; findmy_main_set_callback(app->findmy_main, findmy_scene_main_callback, app); - + findmy_update_battery(app, app->state.battery_level); view_dispatcher_switch_to_view(app->view_dispatcher, FindMyViewMain); } @@ -26,6 +26,7 @@ bool findmy_scene_main_on_event(void* context, SceneManagerEvent event) { break; case FindMyMainEventBackground: app->state.beacon_active = true; + findmy_update_battery(app, app->state.battery_level); findmy_state_save(&app->state); if(!furi_hal_bt_extra_beacon_is_active()) { furi_check(furi_hal_bt_extra_beacon_start());