Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic shutdown on idle #1647

Open
wants to merge 35 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6dc39ba
Merge pull request #1 from flipperdevices/dev
SHxKenzuto Aug 15, 2022
cf053b4
Merge remote-tracking branch 'upstream/dev' into dev
SHxKenzuto Aug 15, 2022
409151f
Merge remote-tracking branch 'upstream/dev' into dev
SHxKenzuto Aug 22, 2022
af8d236
added "Shutdown on Idle" setting under power settings
SHxKenzuto Aug 23, 2022
024326e
Merge remote-tracking branch 'upstream/dev' into dev
SHxKenzuto Aug 23, 2022
94b2d25
Merge remote-tracking branch 'origin/dev' into shutdown_idle
SHxKenzuto Aug 23, 2022
44e3842
fix issues Shutdown on idle
SHxKenzuto Aug 23, 2022
40cabd5
Merge remote-tracking branch 'upstream/dev' into shutdown_idle
SHxKenzuto Sep 19, 2022
6d83a3e
Merge branch 'dev' into shutdown_idle
skotopes Sep 28, 2022
a3ade92
Power: free variable_item_list after removing from view dispatcher
skotopes Sep 28, 2022
d3c1ff5
Merge remote-tracking branch 'upstream/dev' into shutdown_idle
SHxKenzuto Oct 10, 2022
82f2354
event based check for auto shutdown timer setting
SHxKenzuto Oct 10, 2022
12515b2
Merge remote-tracking branch 'upstream/dev' into shutdown_idle
SHxKenzuto Oct 21, 2022
dfe7828
Merge branch 'dev' into shutdown_idle
skotopes Oct 28, 2022
3a5d70b
Merge branch 'dev' into shutdown_idle
SHxKenzuto Nov 4, 2022
f07424f
added 2 hours interval option in shutdown on idle submenu
SHxKenzuto Nov 4, 2022
76c2ccd
Merge branch 'dev-upstream' into shutdown_idle
SHxKenzuto Dec 9, 2022
400558a
Shutdown on Idle: auto-shutdown timer arm/inhibit hooked to loader ev…
SHxKenzuto Dec 9, 2022
bfc563e
Merge remote-tracking branch 'upstream/dev' into shutdown_idle
SHxKenzuto Dec 9, 2022
4ed6950
Merge branch 'dev' into shutdown_idle
skotopes Dec 10, 2022
461aca0
Remove merge artifact
skotopes Dec 10, 2022
1cb5d6f
Merge branch 'dev' into shutdown_idle
skotopes Dec 10, 2022
b931ef7
Merge branch 'dev' into shutdown_idle
skotopes Dec 12, 2022
d8db432
Shutdown on Idle: moved timer allocation before callbacks subscriptions
SHxKenzuto Dec 18, 2022
d65fd6f
Shutdown on Idle: optimized loader callback subscription
SHxKenzuto Dec 18, 2022
d75e6a1
grouped furi_record_open instructions
SHxKenzuto Dec 18, 2022
8f46234
Merge remote-tracking branch 'upstream/dev' into shutdown_idle
SHxKenzuto Dec 18, 2022
3aa4229
changed power_off instruction to furi_hal_power_off
SHxKenzuto Dec 19, 2022
345c654
Merge remote-tracking branch 'origin/dev' into shutdown_idle
skotopes Feb 26, 2023
104e34d
Merge branch 'dev' into shutdown_idle
skotopes Mar 9, 2023
b69b4f4
Merge remote-tracking branch 'origin/dev' into shutdown_idle
skotopes Sep 1, 2023
4ab846b
Sync api symbols
skotopes Sep 1, 2023
9a86178
Merge branch 'dev' into shutdown_idle
skotopes Sep 4, 2023
0dbc1b6
Merge branch 'dev' into shutdown_idle
hedger Sep 5, 2023
4fdb8f0
Merge remote-tracking branch 'origin/dev' into shutdown_idle
skotopes Jun 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion applications/power/power_service/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,63 @@ static ViewPort* power_battery_view_port_alloc(Power* power) {
return battery_view_port;
}

static void power_start_auto_shutdown_timer(Power* power) {
furi_timer_start(power->auto_shutdown_timer, furi_ms_to_ticks(power->shutdown_idle_delay_ms));
}

static void power_stop_auto_shutdown_timer(Power* power) {
furi_timer_stop(power->auto_shutdown_timer);
}

static void power_input_event_callback(const void* value, void* context) {
furi_assert(value);
furi_assert(context);
const InputEvent* event = value;
Power* power = context;
if(event->type == InputTypePress) {
power_start_auto_shutdown_timer(power);
}
}

static void power_auto_shutdown_arm(Power* power) {
if(power->shutdown_idle_delay_ms) {
power->input_events_subscription =
furi_pubsub_subscribe(power->input_events_pubsub, power_input_event_callback, power);
power_start_auto_shutdown_timer(power);
}
}

static void power_auto_shutdown_inhibit(Power* power) {
power_stop_auto_shutdown_timer(power);
if(power->input_events_subscription) {
furi_pubsub_unsubscribe(power->input_events_pubsub, power->input_events_subscription);
power->input_events_subscription = NULL;
}
}

static void power_auto_shutdown_timer_callback(void* context) {
furi_assert(context);
Power* power = context;
power_auto_shutdown_inhibit(power);
power_off(power);
}

static void auto_shutdown_update(Power* power) {
uint32_t old_time = power->shutdown_idle_delay_ms;
LOAD_POWER_SETTINGS(&power->shutdown_idle_delay_ms);
if(power->shutdown_idle_delay_ms) {
if(power->shutdown_idle_delay_ms != old_time) {
if(old_time) {
power_start_auto_shutdown_timer(power);
} else {
power_auto_shutdown_arm(power);
}
}
} else if(old_time) {
power_auto_shutdown_inhibit(power);
}
}

Power* power_alloc() {
Power* power = malloc(sizeof(Power));

Expand All @@ -47,6 +104,9 @@ Power* power_alloc() {
// Pubsub
power->event_pubsub = furi_pubsub_alloc();

power->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS);
power->input_events_subscription = NULL;

// State initialization
power->state = PowerStateNotCharging;
power->battery_low = false;
Expand All @@ -70,6 +130,10 @@ Power* power_alloc() {
power->battery_view_port = power_battery_view_port_alloc(power);
power->show_low_bat_level_message = true;

//Auto shutdown timer
power->auto_shutdown_timer =
furi_timer_alloc(power_auto_shutdown_timer_callback, FuriTimerTypeOnce, power);

return power;
}

Expand All @@ -89,6 +153,12 @@ void power_free(Power* power) {

// FuriPubSub
furi_pubsub_free(power->event_pubsub);
furi_pubsub_free(power->input_events_pubsub);

if(power->input_events_subscription) {
furi_pubsub_unsubscribe(power->input_events_pubsub, power->input_events_subscription);
power->input_events_subscription = NULL;
}

// Records
furi_record_close(RECORD_NOTIFICATION);
Expand Down Expand Up @@ -204,10 +274,18 @@ static void power_check_battery_level_change(Power* power) {
int32_t power_srv(void* p) {
UNUSED(p);
Power* power = power_alloc();
if(!LOAD_POWER_SETTINGS(&power->shutdown_idle_delay_ms)) {
power->shutdown_idle_delay_ms = 0;
SAVE_POWER_SETTINGS(&power->shutdown_idle_delay_ms);
}
power_auto_shutdown_arm(power);
power_update_info(power);
furi_record_create(RECORD_POWER, power);

while(1) {
//Check current setting for automatic shutdown
auto_shutdown_update(power);

// Update data from gauge and charger
bool need_refresh = power_update_info(power);

Expand All @@ -230,7 +308,7 @@ int32_t power_srv(void* p) {

furi_delay_ms(1000);
}

power_auto_shutdown_inhibit(power);
power_free(power);

return 0;
Expand Down
6 changes: 6 additions & 0 deletions applications/power/power_service/power_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <gui/modules/popup.h>
#include "views/power_off.h"
#include "power/power_settings.h"
#include "views/power_unplug_usb.h"

#include <notification/notification_messages.h>
Expand All @@ -29,6 +30,8 @@ struct Power {
Gui* gui;
NotificationApp* notification;
FuriPubSub* event_pubsub;
FuriPubSub* input_events_pubsub;
FuriPubSubSubscription* input_events_subscription;
PowerEvent event;

PowerState state;
Expand All @@ -39,6 +42,9 @@ struct Power {
uint8_t battery_level;
uint8_t power_off_timeout;

uint32_t shutdown_idle_delay_ms;
FuriTimer* auto_shutdown_timer;

FuriMutex* api_mtx;
};

Expand Down
16 changes: 16 additions & 0 deletions applications/power/power_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <toolbox/saved_struct.h>
#include <storage/storage.h>
#include "power_settings_filename.h"

#define POWER_SETTINGS_VER (1)

#define POWER_SETTINGS_PATH INT_PATH(POWER_SETTINGS_FILE_NAME)
#define POWER_SETTINGS_MAGIC (0x21)

#define SAVE_POWER_SETTINGS(x) \
saved_struct_save( \
POWER_SETTINGS_PATH, (x), sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER)

#define LOAD_POWER_SETTINGS(x) \
saved_struct_load( \
POWER_SETTINGS_PATH, (x), sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER)
7 changes: 7 additions & 0 deletions applications/power/power_settings_app/power_settings_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ PowerSettingsApp* power_settings_app_alloc(uint32_t first_scene) {
PowerSettingsAppViewBatteryInfo,
battery_info_get_view(app->batery_info));
app->submenu = submenu_alloc();
app->variable_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
app->view_dispatcher, PowerSettingsAppViewSubmenu, submenu_get_view(app->submenu));
app->dialog = dialog_ex_alloc();
view_dispatcher_add_view(
app->view_dispatcher, PowerSettingsAppViewDialog, dialog_ex_get_view(app->dialog));
view_dispatcher_add_view(
app->view_dispatcher,
PowerSettingsAppViewVariableItemList,
variable_item_list_get_view(app->variable_item_list));

// Set first scene
scene_manager_next_scene(app->scene_manager, first_scene);
Expand All @@ -63,8 +68,10 @@ void power_settings_app_free(PowerSettingsApp* app) {
battery_info_free(app->batery_info);
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewSubmenu);
submenu_free(app->submenu);
variable_item_list_free(app->variable_item_list);
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewDialog);
dialog_ex_free(app->dialog);
view_dispatcher_remove_view(app->view_dispatcher, PowerSettingsAppViewVariableItemList);
// View dispatcher
view_dispatcher_free(app->view_dispatcher);
scene_manager_free(app->scene_manager);
Expand Down
5 changes: 5 additions & 0 deletions applications/power/power_settings_app/power_settings_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include "views/battery_info.h"
#include <gui/modules/submenu.h>
#include <gui/modules/dialog_ex.h>
#include <gui/modules/variable_item_list.h>

#include "power/power_settings.h"
#include "scenes/power_settings_scene.h"

typedef struct {
Expand All @@ -22,10 +24,13 @@ typedef struct {
Submenu* submenu;
DialogEx* dialog;
PowerInfo info;
VariableItemList* variable_item_list;
uint32_t shutdown_idle_delay_ms;
} PowerSettingsApp;

typedef enum {
PowerSettingsAppViewBatteryInfo,
PowerSettingsAppViewSubmenu,
PowerSettingsAppViewDialog,
PowerSettingsAppViewVariableItemList
} PowerSettingsAppView;
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ ADD_SCENE(power_settings, start, Start)
ADD_SCENE(power_settings, battery_info, BatteryInfo)
ADD_SCENE(power_settings, reboot, Reboot)
ADD_SCENE(power_settings, power_off, PowerOff)
ADD_SCENE(power_settings, shutdown_idle, ShutdownIdle)
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "../power_settings_app.h"
#include <lib/toolbox/value_index.h>

#define SHUTDOWN_IDLE_DELAY_COUNT 8
#define SCENE_EVENT_SELECT_SHUTDOWN_IDLE_DELAY 0

const char* const shutdown_idle_delay_text[SHUTDOWN_IDLE_DELAY_COUNT] =
{"OFF", "15min", "30min", "1h", "6h", "12h", "24h", "48h"};

const uint32_t shutdown_idle_delay_value[SHUTDOWN_IDLE_DELAY_COUNT] =
{0, 900000, 1800000, 3600000, 21600000, 43200000, 86400000, 172800000};

static void power_settings_scene_shutodwn_idle_callback(void* context, uint32_t index) {
PowerSettingsApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, index);
}

static void power_settings_scene_start_shutdown_idle_delay_changed(VariableItem* item) {
PowerSettingsApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);

variable_item_set_current_value_text(item, shutdown_idle_delay_text[index]);
app->shutdown_idle_delay_ms = shutdown_idle_delay_value[index];
}

void power_settings_scene_shutdown_idle_on_enter(void* context) {
PowerSettingsApp* app = context;
LOAD_POWER_SETTINGS(&app->shutdown_idle_delay_ms);
VariableItemList* variable_item_list = app->variable_item_list;
VariableItem* item;
uint8_t value_index;

item = variable_item_list_add(
variable_item_list,
"Set Time",
SHUTDOWN_IDLE_DELAY_COUNT,
power_settings_scene_start_shutdown_idle_delay_changed,
app);

variable_item_list_set_enter_callback(
variable_item_list, power_settings_scene_shutodwn_idle_callback, app);

value_index = value_index_uint32(
app->shutdown_idle_delay_ms, shutdown_idle_delay_value, SHUTDOWN_IDLE_DELAY_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, shutdown_idle_delay_text[value_index]);

view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewVariableItemList);
}

bool power_settings_scene_shutdown_idle_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SCENE_EVENT_SELECT_SHUTDOWN_IDLE_DELAY) {
consumed = true;
}
}
return consumed;
}

void power_settings_scene_shutdown_idle_on_exit(void* context) {
PowerSettingsApp* app = context;
SAVE_POWER_SETTINGS(&app->shutdown_idle_delay_ms);
variable_item_list_reset(app->variable_item_list);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum PowerSettingsSubmenuIndex {
PowerSettingsSubmenuIndexBatteryInfo,
PowerSettingsSubmenuIndexReboot,
PowerSettingsSubmenuIndexOff,
PowerSettingsSubmenuShutdownIdle
};

static void power_settings_scene_start_submenu_callback(void* context, uint32_t index) {
Expand Down Expand Up @@ -34,6 +35,12 @@ void power_settings_scene_start_on_enter(void* context) {
PowerSettingsSubmenuIndexOff,
power_settings_scene_start_submenu_callback,
app);
submenu_add_item(
submenu,
"Shutdown on Idle",
PowerSettingsSubmenuShutdownIdle,
power_settings_scene_start_submenu_callback,
app);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(app->scene_manager, PowerSettingsAppSceneStart));

Expand All @@ -51,6 +58,8 @@ bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event)
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneReboot);
} else if(event.event == PowerSettingsSubmenuIndexOff) {
scene_manager_next_scene(app->scene_manager, PowerSettingsAppScenePowerOff);
} else if(event.event == PowerSettingsSubmenuShutdownIdle) {
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneShutdownIdle);
}
scene_manager_set_scene_state(app->scene_manager, PowerSettingsAppSceneStart, event.event);
consumed = true;
Expand Down
3 changes: 3 additions & 0 deletions applications/power/power_settings_filename.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#define POWER_SETTINGS_FILE_NAME ".power.settings"