[FL-2019] Battery test application (#940)
* Power: rework API * Applications: introduce battery test application * Power: fix typo * Desktop: cleanup merge artifacts Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									7522b111c2
								
							
						
					
					
						commit
						2cbf99e15a
					
				| @ -42,6 +42,7 @@ extern int32_t usb_mouse_app(void* p); | |||||||
| extern int32_t usb_test_app(void* p); | extern int32_t usb_test_app(void* p); | ||||||
| extern int32_t vibro_test_app(void* p); | extern int32_t vibro_test_app(void* p); | ||||||
| extern int32_t bt_hid_app(void* p); | extern int32_t bt_hid_app(void* p); | ||||||
|  | extern int32_t battery_test_app(void* p); | ||||||
| 
 | 
 | ||||||
| // Plugins
 | // Plugins
 | ||||||
| extern int32_t music_player_app(void* p); | extern int32_t music_player_app(void* p); | ||||||
| @ -278,6 +279,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { | |||||||
| #ifdef APP_DISPLAY_TEST | #ifdef APP_DISPLAY_TEST | ||||||
|     {.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL}, |     {.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL}, | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef APP_BATTERY_TEST | ||||||
|  |     {.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL}, | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication); | const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication); | ||||||
|  | |||||||
| @ -155,6 +155,11 @@ CFLAGS		+= -DAPP_DISPLAY_TEST | |||||||
| SRV_GUI = 1 | SRV_GUI = 1 | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | APP_BATTERY_TEST ?= 0 | ||||||
|  | ifeq ($(APP_BATTERY_TEST), 1) | ||||||
|  | CFLAGS		+= -DAPP_BATTERY_TEST | ||||||
|  | SRV_GUI = 1 | ||||||
|  | endif | ||||||
| 
 | 
 | ||||||
| APP_USB_MOUSE ?= 0 | APP_USB_MOUSE ?= 0 | ||||||
| ifeq ($(APP_USB_MOUSE), 1) | ifeq ($(APP_USB_MOUSE), 1) | ||||||
|  | |||||||
| @ -268,9 +268,7 @@ static StorageAnimation* | |||||||
|     animation_storage_fill_animation_list(&animation_list); |     animation_storage_fill_animation_list(&animation_list); | ||||||
| 
 | 
 | ||||||
|     Power* power = furi_record_open("power"); |     Power* power = furi_record_open("power"); | ||||||
|     PowerInfo info; |     bool battery_is_well = power_is_battery_healthy(power); | ||||||
|     power_get_info(power, &info); |  | ||||||
|     bool battery_is_well = power_is_battery_well(&info); |  | ||||||
|     furi_record_close("power"); |     furi_record_close("power"); | ||||||
| 
 | 
 | ||||||
|     Storage* storage = furi_record_open("storage"); |     Storage* storage = furi_record_open("storage"); | ||||||
|  | |||||||
							
								
								
									
										100
									
								
								applications/power/battery_test_app/battery_test_app.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										100
									
								
								applications/power/battery_test_app/battery_test_app.c
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,100 @@ | |||||||
|  | #include "battery_test_app.h" | ||||||
|  | 
 | ||||||
|  | #include <notification/notification-messages.h> | ||||||
|  | 
 | ||||||
|  | void battery_test_dialog_callback(DialogExResult result, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     BatteryTestApp* app = context; | ||||||
|  |     if(result == DialogExResultLeft) { | ||||||
|  |         view_dispatcher_stop(app->view_dispatcher); | ||||||
|  |     } else if(result == DialogExResultRight) { | ||||||
|  |         view_dispatcher_switch_to_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t battery_test_exit_confirm_view() { | ||||||
|  |     return BatteryTestAppViewExitDialog; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void battery_test_battery_info_update_model(void* context) { | ||||||
|  |     BatteryTestApp* app = context; | ||||||
|  |     power_get_info(app->power, &app->info); | ||||||
|  |     BatteryInfoModel battery_info_data = { | ||||||
|  |         .vbus_voltage = app->info.voltage_vbus, | ||||||
|  |         .gauge_voltage = app->info.voltage_gauge, | ||||||
|  |         .gauge_current = app->info.current_gauge, | ||||||
|  |         .gauge_temperature = app->info.temperature_gauge, | ||||||
|  |         .charge = app->info.charge, | ||||||
|  |         .health = app->info.health, | ||||||
|  |     }; | ||||||
|  |     battery_info_set_data(app->batery_info, &battery_info_data); | ||||||
|  |     notification_message(app->notifications, &sequence_display_on); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BatteryTestApp* battery_test_alloc() { | ||||||
|  |     BatteryTestApp* app = furi_alloc(sizeof(BatteryTestApp)); | ||||||
|  | 
 | ||||||
|  |     // Records
 | ||||||
|  |     app->gui = furi_record_open("gui"); | ||||||
|  |     app->power = furi_record_open("power"); | ||||||
|  |     app->notifications = furi_record_open("notification"); | ||||||
|  | 
 | ||||||
|  |     // View dispatcher
 | ||||||
|  |     app->view_dispatcher = view_dispatcher_alloc(); | ||||||
|  |     view_dispatcher_enable_queue(app->view_dispatcher); | ||||||
|  |     view_dispatcher_set_event_callback_context(app->view_dispatcher, app); | ||||||
|  |     view_dispatcher_set_tick_event_callback( | ||||||
|  |         app->view_dispatcher, battery_test_battery_info_update_model, 500); | ||||||
|  |     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); | ||||||
|  | 
 | ||||||
|  |     // Views
 | ||||||
|  |     app->batery_info = battery_info_alloc(); | ||||||
|  |     view_set_previous_callback( | ||||||
|  |         battery_info_get_view(app->batery_info), battery_test_exit_confirm_view); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         app->view_dispatcher, | ||||||
|  |         BatteryTestAppViewBatteryInfo, | ||||||
|  |         battery_info_get_view(app->batery_info)); | ||||||
|  | 
 | ||||||
|  |     app->dialog = dialog_ex_alloc(); | ||||||
|  |     dialog_ex_set_header(app->dialog, "Close battery test?", 64, 12, AlignCenter, AlignTop); | ||||||
|  |     dialog_ex_set_left_button_text(app->dialog, "Exit"); | ||||||
|  |     dialog_ex_set_right_button_text(app->dialog, "Stay"); | ||||||
|  |     dialog_ex_set_result_callback(app->dialog, battery_test_dialog_callback); | ||||||
|  |     dialog_ex_set_context(app->dialog, app); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         app->view_dispatcher, BatteryTestAppViewExitDialog, dialog_ex_get_view(app->dialog)); | ||||||
|  | 
 | ||||||
|  |     battery_test_battery_info_update_model(app); | ||||||
|  |     view_dispatcher_switch_to_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); | ||||||
|  |     return app; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void battery_test_free(BatteryTestApp* app) { | ||||||
|  |     furi_assert(app); | ||||||
|  | 
 | ||||||
|  |     // Views
 | ||||||
|  |     view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewBatteryInfo); | ||||||
|  |     battery_info_free(app->batery_info); | ||||||
|  |     view_dispatcher_remove_view(app->view_dispatcher, BatteryTestAppViewExitDialog); | ||||||
|  |     dialog_ex_free(app->dialog); | ||||||
|  |     // View dispatcher
 | ||||||
|  |     view_dispatcher_free(app->view_dispatcher); | ||||||
|  |     // Records
 | ||||||
|  |     furi_record_close("power"); | ||||||
|  |     furi_record_close("gui"); | ||||||
|  |     furi_record_close("notification"); | ||||||
|  |     free(app); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t battery_test_app(void* p) { | ||||||
|  |     BatteryTestApp* app = battery_test_alloc(); | ||||||
|  |     // Disable battery low level notification
 | ||||||
|  |     power_enable_low_battery_level_notification(app->power, false); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_run(app->view_dispatcher); | ||||||
|  |     power_enable_low_battery_level_notification(app->power, true); | ||||||
|  |     battery_test_free(app); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								applications/power/battery_test_app/battery_test_app.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								applications/power/battery_test_app/battery_test_app.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | #include <furi.h> | ||||||
|  | #include <power/power_service/power.h> | ||||||
|  | #include <gui/gui.h> | ||||||
|  | #include <gui/view.h> | ||||||
|  | #include <gui/view_dispatcher.h> | ||||||
|  | #include <notification/notification.h> | ||||||
|  | 
 | ||||||
|  | #include <gui/modules/dialog_ex.h> | ||||||
|  | #include <power/power_settings_app/views/battery_info.h> | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     Power* power; | ||||||
|  |     Gui* gui; | ||||||
|  |     NotificationApp* notifications; | ||||||
|  |     ViewDispatcher* view_dispatcher; | ||||||
|  |     BatteryInfo* batery_info; | ||||||
|  |     DialogEx* dialog; | ||||||
|  |     PowerInfo info; | ||||||
|  | } BatteryTestApp; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     BatteryTestAppViewBatteryInfo, | ||||||
|  |     BatteryTestAppViewExitDialog, | ||||||
|  | } BatteryTestAppView; | ||||||
							
								
								
									
										17
									
								
								applications/power/power_service/power.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										17
									
								
								applications/power/power_service/power.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -7,11 +7,6 @@ | |||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
| 
 | 
 | ||||||
| #define POWER_OFF_TIMEOUT 90 | #define POWER_OFF_TIMEOUT 90 | ||||||
| #define POWER_BATTERY_WELL_LEVEL 70 |  | ||||||
| 
 |  | ||||||
| bool power_is_battery_well(PowerInfo* info) { |  | ||||||
|     return info->health > POWER_BATTERY_WELL_LEVEL; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void power_draw_battery_callback(Canvas* canvas, void* context) { | void power_draw_battery_callback(Canvas* canvas, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
| @ -50,7 +45,7 @@ Power* power_alloc() { | |||||||
|     power->state = PowerStateNotCharging; |     power->state = PowerStateNotCharging; | ||||||
|     power->battery_low = false; |     power->battery_low = false; | ||||||
|     power->power_off_timeout = POWER_OFF_TIMEOUT; |     power->power_off_timeout = POWER_OFF_TIMEOUT; | ||||||
|     power->info_mtx = osMutexNew(NULL); |     power->api_mtx = osMutexNew(NULL); | ||||||
| 
 | 
 | ||||||
|     // Gui
 |     // Gui
 | ||||||
|     power->view_dispatcher = view_dispatcher_alloc(); |     power->view_dispatcher = view_dispatcher_alloc(); | ||||||
| @ -66,6 +61,7 @@ Power* power_alloc() { | |||||||
| 
 | 
 | ||||||
|     // Battery view port
 |     // Battery view port
 | ||||||
|     power->battery_view_port = power_battery_view_port_alloc(power); |     power->battery_view_port = power_battery_view_port_alloc(power); | ||||||
|  |     power->show_low_bat_level_message = true; | ||||||
| 
 | 
 | ||||||
|     return power; |     return power; | ||||||
| } | } | ||||||
| @ -81,7 +77,7 @@ void power_free(Power* power) { | |||||||
|     view_port_free(power->battery_view_port); |     view_port_free(power->battery_view_port); | ||||||
| 
 | 
 | ||||||
|     // State
 |     // State
 | ||||||
|     osMutexDelete(power->info_mtx); |     osMutexDelete(power->api_mtx); | ||||||
| 
 | 
 | ||||||
|     // FuriPubSub
 |     // FuriPubSub
 | ||||||
|     furi_pubsub_free(power->event_pubsub); |     furi_pubsub_free(power->event_pubsub); | ||||||
| @ -135,17 +131,18 @@ static bool power_update_info(Power* power) { | |||||||
|     info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger); |     info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger); | ||||||
|     info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); |     info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); | ||||||
| 
 | 
 | ||||||
|     osMutexAcquire(power->info_mtx, osWaitForever); |     osMutexAcquire(power->api_mtx, osWaitForever); | ||||||
|     bool need_refresh = power->info.charge != info.charge; |     bool need_refresh = power->info.charge != info.charge; | ||||||
|     power->info = info; |     power->info = info; | ||||||
|     osMutexRelease(power->info_mtx); |     osMutexRelease(power->api_mtx); | ||||||
| 
 | 
 | ||||||
|     return need_refresh; |     return need_refresh; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void power_check_low_battery(Power* power) { | static void power_check_low_battery(Power* power) { | ||||||
|     // Check battery charge and vbus voltage
 |     // Check battery charge and vbus voltage
 | ||||||
|     if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f)) { |     if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f) && | ||||||
|  |        power->show_low_bat_level_message) { | ||||||
|         if(!power->battery_low) { |         if(!power->battery_low) { | ||||||
|             view_dispatcher_send_to_front(power->view_dispatcher); |             view_dispatcher_send_to_front(power->view_dispatcher); | ||||||
|             view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewOff); |             view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewOff); | ||||||
|  | |||||||
| @ -50,19 +50,35 @@ typedef struct { | |||||||
| void power_off(Power* power); | void power_off(Power* power); | ||||||
| 
 | 
 | ||||||
| /** Reboot device
 | /** Reboot device
 | ||||||
|  * @param mode - PowerBootMode |  * | ||||||
|  |  * @param mode      PowerBootMode | ||||||
|  */ |  */ | ||||||
| void power_reboot(PowerBootMode mode); | void power_reboot(PowerBootMode mode); | ||||||
| 
 | 
 | ||||||
| /** Get power info
 | /** Get power info
 | ||||||
|  * @param power - Power instance |  * | ||||||
|  * @param info - PowerInfo instance |  * @param power     Power instance | ||||||
|  |  * @param info      PowerInfo instance | ||||||
|  */ |  */ | ||||||
| void power_get_info(Power* power, PowerInfo* info); | void power_get_info(Power* power, PowerInfo* info); | ||||||
| 
 | 
 | ||||||
| /** Get power event pubsub handler
 | /** Get power event pubsub handler
 | ||||||
|  * @param power - Power instance |  * | ||||||
|  |  * @param power     Power instance | ||||||
|  |  * | ||||||
|  |  * @return          FuriPubSub instance | ||||||
|  */ |  */ | ||||||
| FuriPubSub* power_get_pubsub(Power* power); | FuriPubSub* power_get_pubsub(Power* power); | ||||||
| 
 | 
 | ||||||
| bool power_is_battery_well(PowerInfo* info); | /** Check battery health
 | ||||||
|  |  * | ||||||
|  |  * @return          true if battery is healthy | ||||||
|  |  */ | ||||||
|  | bool power_is_battery_healthy(Power* power); | ||||||
|  | 
 | ||||||
|  | /** Enable or disable battery low level notification mesage
 | ||||||
|  |  * | ||||||
|  |  * @param power     Power instance | ||||||
|  |  * @param enable    true - enable, false - disable | ||||||
|  |  */ | ||||||
|  | void power_enable_low_battery_level_notification(Power* power, bool enable); | ||||||
|  | |||||||
| @ -26,12 +26,28 @@ void power_get_info(Power* power, PowerInfo* info) { | |||||||
|     furi_assert(power); |     furi_assert(power); | ||||||
|     furi_assert(info); |     furi_assert(info); | ||||||
| 
 | 
 | ||||||
|     osMutexAcquire(power->info_mtx, osWaitForever); |     osMutexAcquire(power->api_mtx, osWaitForever); | ||||||
|     memcpy(info, &power->info, sizeof(power->info)); |     memcpy(info, &power->info, sizeof(power->info)); | ||||||
|     osMutexRelease(power->info_mtx); |     osMutexRelease(power->api_mtx); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FuriPubSub* power_get_pubsub(Power* power) { | FuriPubSub* power_get_pubsub(Power* power) { | ||||||
|     furi_assert(power); |     furi_assert(power); | ||||||
|     return power->event_pubsub; |     return power->event_pubsub; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool power_is_battery_healthy(Power* power) { | ||||||
|  |     furi_assert(power); | ||||||
|  |     bool is_healthy = false; | ||||||
|  |     osMutexAcquire(power->api_mtx, osWaitForever); | ||||||
|  |     is_healthy = power->info.health > POWER_BATTERY_HEALTHY_LEVEL; | ||||||
|  |     osMutexRelease(power->api_mtx); | ||||||
|  |     return is_healthy; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void power_enable_low_battery_level_notification(Power* power, bool enable) { | ||||||
|  |     furi_assert(power); | ||||||
|  |     osMutexAcquire(power->api_mtx, osWaitForever); | ||||||
|  |     power->show_low_bat_level_message = enable; | ||||||
|  |     osMutexRelease(power->api_mtx); | ||||||
|  | } | ||||||
|  | |||||||
| @ -11,6 +11,8 @@ | |||||||
| 
 | 
 | ||||||
| #include <notification/notification-messages.h> | #include <notification/notification-messages.h> | ||||||
| 
 | 
 | ||||||
|  | #define POWER_BATTERY_HEALTHY_LEVEL 70 | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     PowerStateNotCharging, |     PowerStateNotCharging, | ||||||
|     PowerStateCharging, |     PowerStateCharging, | ||||||
| @ -30,11 +32,13 @@ struct Power { | |||||||
| 
 | 
 | ||||||
|     PowerState state; |     PowerState state; | ||||||
|     PowerInfo info; |     PowerInfo info; | ||||||
|     osMutexId_t info_mtx; |  | ||||||
| 
 | 
 | ||||||
|     bool battery_low; |     bool battery_low; | ||||||
|  |     bool show_low_bat_level_message; | ||||||
|     uint8_t battery_level; |     uint8_t battery_level; | ||||||
|     uint8_t power_off_timeout; |     uint8_t power_off_timeout; | ||||||
|  | 
 | ||||||
|  |     osMutexId_t api_mtx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  | |||||||
| @ -74,7 +74,7 @@ void power_settings_app_free(PowerSettingsApp* app) { | |||||||
|     free(app); |     free(app); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| extern int32_t power_settings_app(void* p) { | int32_t power_settings_app(void* p) { | ||||||
|     PowerSettingsApp* app = power_settings_app_alloc(); |     PowerSettingsApp* app = power_settings_app_alloc(); | ||||||
|     view_dispatcher_run(app->view_dispatcher); |     view_dispatcher_run(app->view_dispatcher); | ||||||
|     power_settings_app_free(app); |     power_settings_app_free(app); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich