diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 8fb501c72..6ee8365f7 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -10,6 +10,8 @@ App( # Sources separation breaks linking with subghz on internal, commented for now # sources=[ # "*.c", + # "!helpers/subghz_gps.c", + # "!helpers/minmea.c", # "!subghz_cli.c", # "!helpers/subghz_chat.c", # "!subghz_extended_freq.c", @@ -32,6 +34,15 @@ App( fap_category="Sub-GHz", ) +App( + appid="subghz_gps", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="subghz_gps_plugin_ep", + requires=["subghz"], + sources=["helpers/subghz_gps.c", "helpers/minmea.c"], +) + App( appid="subghz_cli", targets=["f7"], diff --git a/applications/main/subghz/helpers/subghz_gps.c b/applications/main/subghz/helpers/subghz_gps.c index 56108620a..d284f7cc5 100644 --- a/applications/main/subghz/helpers/subghz_gps.c +++ b/applications/main/subghz/helpers/subghz_gps.c @@ -1,6 +1,18 @@ #include "subghz_gps.h" #include "minmea.h" +#include +#include + +#define UART_CH (momentum_settings.uart_nmea_channel) + +typedef enum { + WorkerEvtStop = (1 << 0), + WorkerEvtRxDone = (1 << 1), +} WorkerEvtFlags; + +#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) + static void subghz_gps_uart_parse_nmea(SubGhzGPS* subghz_gps, char* line) { switch(minmea_sentence_id(line, false)) { case MINMEA_SENTENCE_RMC: { @@ -113,9 +125,93 @@ static int32_t subghz_gps_uart_worker(void* context) { return 0; } -SubGhzGPS* subghz_gps_init() { - SubGhzGPS* subghz_gps = malloc(sizeof(SubGhzGPS)); +static void subghz_gps_deinit(SubGhzGPS* subghz_gps) { + furi_assert(subghz_gps); + furi_hal_serial_async_rx_stop(subghz_gps->serial_handle); + furi_hal_serial_deinit(subghz_gps->serial_handle); + furi_hal_serial_control_release(subghz_gps->serial_handle); + + expansion_enable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + + furi_thread_flags_set(furi_thread_get_id(subghz_gps->thread), WorkerEvtStop); + furi_thread_join(subghz_gps->thread); + furi_thread_free(subghz_gps->thread); + + furi_stream_buffer_free(subghz_gps->rx_stream); +} + +static float subghz_gps_deg2rad(float deg) { + return (deg * M_PI / 180); +} + +static float subghz_gps_calc_distance(float lat1d, float lon1d, float lat2d, float lon2d) { + float lat1r, lon1r, lat2r, lon2r; + double u, v; + lat1r = subghz_gps_deg2rad(lat1d); + lon1r = subghz_gps_deg2rad(lon1d); + lat2r = subghz_gps_deg2rad(lat2d); + lon2r = subghz_gps_deg2rad(lon2d); + u = sin((lat2r - lat1r) / 2); + v = sin((lon2r - lon1r) / 2); + return 2 * 6371 * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v)); +} + +static float subghz_gps_calc_angle(float lat1, float lon1, float lat2, float lon2) { + return atan2(lat1 - lat2, lon1 - lon2) * 180 / (double)M_PI; +} + +static void subghz_gps_get_descr( + SubGhzGPS* subghz_gps, + FuriString* descr, + float latitude, + float longitude) { + float distance = + subghz_gps_calc_distance(latitude, longitude, subghz_gps->latitude, subghz_gps->longitude); + + float angle = + subghz_gps_calc_angle(latitude, longitude, subghz_gps->latitude, subghz_gps->longitude); + + char* angle_str = "?"; + if(angle > -22.5 && angle <= 22.5) { + angle_str = "E"; + } else if(angle > 22.5 && angle <= 67.5) { + angle_str = "NE"; + } else if(angle > 67.5 && angle <= 112.5) { + angle_str = "N"; + } else if(angle > 112.5 && angle <= 157.5) { + angle_str = "NW"; + } else if(angle < -22.5 && angle >= -67.5) { + angle_str = "SE"; + } else if(angle < -67.5 && angle >= -112.5) { + angle_str = "S"; + } else if(angle < -112.5 && angle >= -157.5) { + angle_str = "SW"; + } else if(angle < -157.5 || angle >= 157.5) { + angle_str = "W"; + } + + furi_string_printf( + descr, + "Captured at: %f,\r\n" + "%f\r\n" + "\r\n" + "Realtime: Sats: %d\r\n" + "Distance: %.2f%s Dir: %s\r\n" + "GPS time: %02d:%02d:%02d UTC", + (double)latitude, + (double)longitude, + subghz_gps->satellites, + (double)(subghz_gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0), + distance > 1 ? "km" : "m", + angle_str, + subghz_gps->fix_hour, + subghz_gps->fix_minute, + subghz_gps->fix_second); +} + +static void subghz_gps_init(SubGhzGPS* subghz_gps, uint32_t baudrate) { subghz_gps->latitude = NAN; subghz_gps->longitude = NAN; subghz_gps->satellites = 0; @@ -125,69 +221,32 @@ SubGhzGPS* subghz_gps_init() { subghz_gps->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); - subghz_gps->thread = furi_thread_alloc(); - furi_thread_set_name(subghz_gps->thread, "SubGhzGPSWorker"); - furi_thread_set_stack_size(subghz_gps->thread, 1024); - furi_thread_set_context(subghz_gps->thread, subghz_gps); - furi_thread_set_callback(subghz_gps->thread, subghz_gps_uart_worker); + subghz_gps->thread = + furi_thread_alloc_ex("SubGhzGPSWorker", 1024, subghz_gps_uart_worker, subghz_gps); + furi_thread_start(subghz_gps->thread); - subghz_gps->expansion = furi_record_open(RECORD_EXPANSION); - expansion_disable(subghz_gps->expansion); + expansion_disable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); subghz_gps->serial_handle = furi_hal_serial_control_acquire(UART_CH); furi_check(subghz_gps->serial_handle); - furi_hal_serial_init(subghz_gps->serial_handle, 9600); + furi_hal_serial_init(subghz_gps->serial_handle, baudrate); furi_hal_serial_async_rx_start( subghz_gps->serial_handle, subghz_gps_uart_on_irq_cb, subghz_gps, false); - return subghz_gps; + subghz_gps->deinit = &subghz_gps_deinit; + subghz_gps->get_descr = &subghz_gps_get_descr; } -void subghz_gps_deinit(SubGhzGPS* subghz_gps) { - furi_assert(subghz_gps); +#include - furi_hal_serial_async_rx_stop(subghz_gps->serial_handle); - furi_hal_serial_deinit(subghz_gps->serial_handle); - furi_hal_serial_control_release(subghz_gps->serial_handle); +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "subghz_gps", + .ep_api_version = 1, + .entry_point = &subghz_gps_init, +}; - expansion_enable(subghz_gps->expansion); - furi_record_close(RECORD_EXPANSION); - - furi_thread_free(subghz_gps->thread); - furi_stream_buffer_free(subghz_gps->rx_stream); - - free(subghz_gps); +const FlipperAppPluginDescriptor* subghz_gps_plugin_ep(void) { + return &plugin_descriptor; } - -void subghz_gps_start(SubGhzGPS* subghz_gps) { - furi_thread_start(subghz_gps->thread); -} - -void subghz_gps_stop(SubGhzGPS* subghz_gps) { - furi_thread_flags_set(furi_thread_get_id(subghz_gps->thread), WorkerEvtStop); - furi_thread_join(subghz_gps->thread); -} - -void subghz_gps_set_baudrate(SubGhzGPS* subghz_gps, uint32_t baudrate) { - furi_hal_serial_set_br(subghz_gps->serial_handle, baudrate); -} - -double subghz_gps_deg2rad(double deg) { - return (deg * (double)M_PI / 180); -} - -double subghz_gps_calc_distance(double lat1d, double lon1d, double lat2d, double lon2d) { - double lat1r, lon1r, lat2r, lon2r, u, v; - lat1r = subghz_gps_deg2rad(lat1d); - lon1r = subghz_gps_deg2rad(lon1d); - lat2r = subghz_gps_deg2rad(lat2d); - lon2r = subghz_gps_deg2rad(lon2d); - u = sin((lat2r - lat1r) / 2); - v = sin((lon2r - lon1r) / 2); - return 2 * 6371 * asin(sqrt(u * u + cos((double)lat1r) * cos((double)lat2r) * v * v)); -} - -double subghz_gps_calc_angle(double lat1, double lon1, double lat2, double lon2) { - return atan2(lat1 - lat2, lon1 - lon2) * 180 / (double)M_PI; -} \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_gps.h b/applications/main/subghz/helpers/subghz_gps.h index f28cecb5f..402fd0214 100644 --- a/applications/main/subghz/helpers/subghz_gps.h +++ b/applications/main/subghz/helpers/subghz_gps.h @@ -1,25 +1,18 @@ -#include -#include -#include +#pragma once -#define UART_CH (momentum_settings.uart_nmea_channel) +#include +#include #define RX_BUF_SIZE 1024 -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), -} WorkerEvtFlags; +typedef struct SubGhzGPS SubGhzGPS; -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) - -typedef struct { - Expansion* expansion; +struct SubGhzGPS { + FlipperApplication* plugin_app; FuriThread* thread; FuriStreamBuffer* rx_stream; uint8_t rx_buf[RX_BUF_SIZE]; FuriHalSerialHandle* serial_handle; - FuriTimer* timer; float latitude; @@ -28,73 +21,40 @@ typedef struct { uint8_t fix_second; uint8_t fix_minute; uint8_t fix_hour; -} SubGhzGPS; + + /** + * Deinitialize SubGhzGPS object + * To be used by plugin handler + * + * @param subghz_gps SubGhzGPS object + * @return void + */ + void (*deinit)(SubGhzGPS* subghz_gps); + + /** + * Get description for signal info + * + * @param subghz_gps SubGhzGPS object + * @param descr Output string + * @param latitude Latitude + * @param longitude Longitude + * @return void + */ + void (*get_descr)(SubGhzGPS* subghz_gps, FuriString* descr, float latitude, float longitude); +}; /** - * Initialize SubGhzGPS object - * + * Initialize SubGhzGPS plugin + * Fails and returns NULL if Expansion is connected + * * @return SubGhzGPS* SubGhzGPS object */ -SubGhzGPS* subghz_gps_init(); +SubGhzGPS* subghz_gps_plugin_init(); /** - * Deinitialize SubGhzGPS object + * Deinitialize SubGhzGPS plugin * * @param subghz_gps SubGhzGPS object * @return void */ -void subghz_gps_deinit(SubGhzGPS* subghz_gps); - -/** - * Start GPS thread - * - * @param subghz_gps SubGhzGPS object - * @return void -*/ -void subghz_gps_start(SubGhzGPS* subghz_gps); - -/** - * Stop GPS thread - * - * @param subghz_gps SubGhzGPS object - * @return void -*/ -void subghz_gps_stop(SubGhzGPS* subghz_gps); - -/** - * Set baudrate for GPS - * - * @param baudrate Baudrate - * @return void -*/ -void subghz_gps_set_baudrate(SubGhzGPS* subghz_gps, uint32_t baudrate); - -/** - * Convert degree to radian - * - * @param deg Degree - * @return double Radian - */ -double subghz_gps_deg2rad(double deg); - -/** - * Calculate distance between two coordinates - * - * @param lat1d Latitude 1 - * @param lon1d Longitude 1 - * @param lat2d Latitude 2 - * @param lon2d Longitude 2 - * @return double Distance in km -*/ -double subghz_gps_calc_distance(double lat1d, double lon1d, double lat2d, double lon2d); - -/** - * Calculate angle between two coordinates - * - * @param lat1 Latitude 1 - * @param lon1 Longitude 1 - * @param lat2 Latitude 2 - * @param lon2 Longitude 2 - * @return double Angle in degree -*/ -double subghz_gps_calc_angle(double lat1, double lon1, double lat2, double lon2); +void subghz_gps_plugin_deinit(SubGhzGPS* subghz_gps); diff --git a/applications/main/subghz/helpers/subghz_gps_plugin.c b/applications/main/subghz/helpers/subghz_gps_plugin.c new file mode 100644 index 000000000..0f41d0b38 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_gps_plugin.c @@ -0,0 +1,71 @@ +#include "subghz_gps.h" + +#include +#include +#include + +#define TAG "SubGhzGPS" + +SubGhzGPS* subghz_gps_plugin_init(uint32_t baudrate) { + bool connected = expansion_is_connected(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + if(connected) return NULL; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperApplication* plugin_app = flipper_application_alloc(storage, firmware_api_interface); + do { + FlipperApplicationPreloadStatus preload_res = flipper_application_preload( + plugin_app, EXT_PATH("apps_data/subghz/plugins/subghz_gps.fal")); + + if(preload_res != FlipperApplicationPreloadStatusSuccess) { + FURI_LOG_E(TAG, "Failed to preload GPS plugin. Code: %d\r\n", preload_res); + break; + } + + if(!flipper_application_is_plugin(plugin_app)) { + FURI_LOG_E(TAG, "GPS plugin file is not a library\r\n"); + break; + } + + FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(plugin_app); + if(load_status != FlipperApplicationLoadStatusSuccess) { + FURI_LOG_E(TAG, "Failed to load GPS plugin file. Code %d\r\n", load_status); + break; + } + + const FlipperAppPluginDescriptor* app_descriptor = + flipper_application_plugin_get_descriptor(plugin_app); + + if(strcmp(app_descriptor->appid, "subghz_gps") != 0) { + FURI_LOG_E(TAG, "GPS plugin type doesn't match\r\n"); + break; + } + + if(app_descriptor->ep_api_version != 1) { + FURI_LOG_E( + TAG, + "GPS plugin version %" PRIu32 " doesn't match\r\n", + app_descriptor->ep_api_version); + break; + } + + void (*subghz_gps_init)(SubGhzGPS* subghz_gps, uint32_t baudrate) = + app_descriptor->entry_point; + + SubGhzGPS* subghz_gps = malloc(sizeof(SubGhzGPS)); + subghz_gps->plugin_app = plugin_app; + subghz_gps_init(subghz_gps, baudrate); + return subghz_gps; + + } while(false); + flipper_application_free(plugin_app); + furi_record_close(RECORD_STORAGE); + return NULL; +} + +void subghz_gps_plugin_deinit(SubGhzGPS* subghz_gps) { + subghz_gps->deinit(subghz_gps); + flipper_application_free(subghz_gps->plugin_app); + free(subghz_gps); + furi_record_close(RECORD_STORAGE); +} diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index 513052bfa..70ec48ab7 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -158,18 +158,14 @@ void subghz_txrx_get_frequency_and_modulation( } } -void subghz_txrx_get_latitude_and_longitude( - SubGhzTxRx* instance, - FuriString* latitude, - FuriString* longitude) { +float subghz_txrx_get_latitude(SubGhzTxRx* instance) { furi_assert(instance); - SubGhzRadioPreset* preset = instance->preset; - if(latitude != NULL) { - furi_string_printf(latitude, "%f", (double)preset->latitude); - } - if(longitude != NULL) { - furi_string_printf(longitude, "%f", (double)preset->longitude); - } + return instance->preset->latitude; +} + +float subghz_txrx_get_longitude(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->preset->longitude; } static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { diff --git a/applications/main/subghz/helpers/subghz_txrx.h b/applications/main/subghz/helpers/subghz_txrx.h index 243f21ba5..072509bdc 100644 --- a/applications/main/subghz/helpers/subghz_txrx.h +++ b/applications/main/subghz/helpers/subghz_txrx.h @@ -92,16 +92,20 @@ void subghz_txrx_get_frequency_and_modulation( bool long_name); /** - * Get string latitude and longitude - * + * Get latitude value + * * @param instance Pointer to a SubGhzTxRx - * @param latitude Pointer to a string latitude - * @param longitude Pointer to a string longitude + * @return latitude */ -void subghz_txrx_get_latitude_and_longitude( - SubGhzTxRx* instance, - FuriString* latitude, - FuriString* longitude); +float subghz_txrx_get_latitude(SubGhzTxRx* instance); + +/** + * Get longitude value + * + * @param instance Pointer to a SubGhzTxRx + * @return longitude +*/ +float subghz_txrx_get_longitude(SubGhzTxRx* instance); /** * Start TX CC1101 diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index 1f4f94e44..9530b86ef 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -23,5 +23,4 @@ ADD_SCENE(subghz, decode_raw, DecodeRAW) ADD_SCENE(subghz, delete_raw, DeleteRAW) ADD_SCENE(subghz, need_saving, NeedSaving) ADD_SCENE(subghz, rpc, Rpc) -ADD_SCENE(subghz, show_gps, ShowGps) -ADD_SCENE(subghz, saved_show_gps, SavedShowGps) \ No newline at end of file +ADD_SCENE(subghz, show_gps, ShowGps) \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_decode_raw.c b/applications/main/subghz/scenes/subghz_scene_decode_raw.c index a14e203f4..2595b7c49 100644 --- a/applications/main/subghz/scenes/subghz_scene_decode_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_decode_raw.c @@ -9,7 +9,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) { if(!subghz_history_get_text_space_left( subghz->history, history_stat_str, - subghz->gps->satellites, + subghz->gps ? subghz->gps->satellites : 0, subghz->last_settings->delete_old_signals)) { FuriString* frequency_str = furi_string_alloc(); FuriString* modulation_str = furi_string_alloc(); @@ -57,8 +57,13 @@ static void subghz_scene_add_to_history_callback( FuriString* item_time = furi_string_alloc(); uint16_t idx = subghz_history_get_item(subghz->history); SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); - preset.latitude = subghz->gps->latitude; - preset.longitude = subghz->gps->longitude; + if(subghz->gps) { + preset.latitude = subghz->gps->latitude; + preset.longitude = subghz->gps->longitude; + } else { + preset.latitude = 0; + preset.longitude = 0; + } if(subghz->last_settings->delete_old_signals && subghz_history_full(subghz->history)) { subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver); diff --git a/applications/main/subghz/scenes/subghz_scene_radio_settings.c b/applications/main/subghz/scenes/subghz_scene_radio_settings.c index 731eceeac..0483f6c2b 100644 --- a/applications/main/subghz/scenes/subghz_scene_radio_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_radio_settings.c @@ -154,11 +154,17 @@ static void subghz_scene_receiver_config_set_gps(VariableItem* item) { subghz_last_settings_save(subghz->last_settings); if(subghz->last_settings->gps_baudrate != 0) { - subghz_gps_stop(subghz->gps); - subghz_gps_set_baudrate(subghz->gps, subghz->last_settings->gps_baudrate); - subghz_gps_start(subghz->gps); + if(subghz->gps) { + furi_hal_serial_set_br( + subghz->gps->serial_handle, subghz->last_settings->gps_baudrate); + } else { + subghz->gps = subghz_gps_plugin_init(subghz->last_settings->gps_baudrate); + } } else { - subghz_gps_stop(subghz->gps); + if(subghz->gps) { + subghz_gps_plugin_deinit(subghz->gps); + subghz->gps = NULL; + } } } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 83406594b..cd300e7c1 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -53,7 +53,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) { if(!subghz_history_get_text_space_left( subghz->history, history_stat_str, - subghz->gps->satellites, + subghz->gps ? subghz->gps->satellites : 0, subghz->last_settings->delete_old_signals)) { FuriString* frequency_str = furi_string_alloc(); FuriString* modulation_str = furi_string_alloc(); @@ -131,8 +131,13 @@ static void subghz_scene_add_to_history_callback( uint16_t idx = subghz_history_get_item(history); SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); - preset.latitude = subghz->gps->latitude; - preset.longitude = subghz->gps->longitude; + if(subghz->gps) { + preset.latitude = subghz->gps->latitude; + preset.longitude = subghz->gps->longitude; + } else { + preset.latitude = 0; + preset.longitude = 0; + } if(subghz->last_settings->delete_old_signals && subghz_history_full(subghz->history)) { subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver); @@ -484,7 +489,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data( subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx)); - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { DateTime datetime; furi_hal_rtc_get_datetime(&datetime); if((datetime.second - subghz->gps->fix_second) > 15) { @@ -506,7 +511,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { switch(subghz->state_notifications) { case SubGhzNotificationStateRx: - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { if(subghz->gps->satellites > 0) { notification_message(subghz->notifications, &sequence_blink_green_10); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index abe85eb68..87cdefcd2 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -17,9 +17,7 @@ void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, v } else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { view_dispatcher_send_custom_event( subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoSave); - } else if( - (result == GuiButtonTypeLeft) && (type == InputTypeShort) && - subghz->last_settings->gps_baudrate != 0) { + } else if((result == GuiButtonTypeLeft) && (type == InputTypeShort) && subghz->gps) { view_dispatcher_send_custom_event( subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoSats); } @@ -81,7 +79,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) { widget_add_string_multiline_element( subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text)); - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { widget_add_button_element( subghz->widget, GuiButtonTypeLeft, @@ -189,7 +187,8 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) } return true; } else if(event.event == SubGhzCustomEventSceneReceiverInfoSats) { - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { + scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneShowGps, false); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowGps); return true; } else { @@ -205,7 +204,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) notification_message(subghz->notifications, &sequence_blink_magenta_10); break; case SubGhzNotificationStateRx: - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { if(subghz->gps->satellites > 0) { notification_message(subghz->notifications, &sequence_blink_green_10); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_saved_menu.c b/applications/main/subghz/scenes/subghz_scene_saved_menu.c index 5dcd1c61d..81390dbd9 100644 --- a/applications/main/subghz/scenes/subghz_scene_saved_menu.c +++ b/applications/main/subghz/scenes/subghz_scene_saved_menu.c @@ -35,13 +35,8 @@ void subghz_scene_saved_menu_on_enter(void* context) { subghz_scene_saved_menu_submenu_callback, subghz); - FuriString* lat_str = furi_string_alloc(); - FuriString* lon_str = furi_string_alloc(); - - subghz_txrx_get_latitude_and_longitude(subghz->txrx, lat_str, lon_str); - - if(strcmp(furi_string_get_cstr(lat_str), "nan") != 0 && - strcmp(furi_string_get_cstr(lon_str), "nan") != 0) { + if(!isnanf(subghz_txrx_get_latitude(subghz->txrx)) && + !isnanf(subghz_txrx_get_longitude(subghz->txrx))) { submenu_add_item( subghz->submenu, "Geographic info", @@ -50,9 +45,6 @@ void subghz_scene_saved_menu_on_enter(void* context) { subghz); } - furi_string_free(lon_str); - furi_string_free(lat_str); - submenu_set_selected_item( subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSavedMenu)); @@ -82,7 +74,8 @@ bool subghz_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubmenuIndexGeo) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexGeo); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedShowGps); + scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneShowGps, true); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowGps); return true; } } diff --git a/applications/main/subghz/scenes/subghz_scene_saved_show_gps.c b/applications/main/subghz/scenes/subghz_scene_saved_show_gps.c deleted file mode 100644 index cbc95f400..000000000 --- a/applications/main/subghz/scenes/subghz_scene_saved_show_gps.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "../subghz_i.h" -#include "../helpers/subghz_custom_event.h" - -void subghz_scene_saved_show_gps_draw_satellites(void* context) { - SubGhz* subghz = context; - - FuriString* text_str = furi_string_alloc(); - FuriString* lat_str = furi_string_alloc(); - FuriString* lon_str = furi_string_alloc(); - - subghz_txrx_get_latitude_and_longitude(subghz->txrx, lat_str, lon_str); - - DateTime datetime; - furi_hal_rtc_get_datetime(&datetime); - if((datetime.second - subghz->gps->fix_second) > 15) { - subghz->gps->latitude = NAN; - subghz->gps->longitude = NAN; - subghz->gps->satellites = 0; - subghz->gps->fix_hour = 0; - subghz->gps->fix_minute = 0; - subghz->gps->fix_second = 0; - } - - double latitude = atof(furi_string_get_cstr(lat_str)); - double longitude = atof(furi_string_get_cstr(lon_str)); - - double distance = subghz_gps_calc_distance( - latitude, longitude, (double)subghz->gps->latitude, (double)subghz->gps->longitude); - - float angle = subghz_gps_calc_angle( - latitude, longitude, (double)subghz->gps->latitude, (double)subghz->gps->longitude); - - char* angle_str = "?"; - if(angle > -22.5 && angle <= 22.5) { - angle_str = "E"; - } else if(angle > 22.5 && angle <= 67.5) { - angle_str = "NE"; - } else if(angle > 67.5 && angle <= 112.5) { - angle_str = "N"; - } else if(angle > 112.5 && angle <= 157.5) { - angle_str = "NW"; - } else if(angle < -22.5 && angle >= -67.5) { - angle_str = "SE"; - } else if(angle < -67.5 && angle >= -112.5) { - angle_str = "S"; - } else if(angle < -112.5 && angle >= -157.5) { - angle_str = "SW"; - } else if(angle < -157.5 || angle >= 157.5) { - angle_str = "W"; - } - - furi_string_printf( - text_str, - "Captured at: %f,\r\n%f\r\n\r\nRealtime: Sats: %d\r\nDistance: %.2f%s Dir: %s\r\nGPS time: %02d:%02d:%02d UTC", - latitude, - longitude, - subghz->gps->satellites, - subghz->gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0, - distance > 1 ? "km" : "m", - angle_str, - subghz->gps->fix_hour, - subghz->gps->fix_minute, - subghz->gps->fix_second); - - widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text_str)); - - furi_string_free(text_str); - furi_string_free(lat_str); - furi_string_free(lon_str); -} - -void subghz_scene_saved_show_gps_refresh_screen(void* context) { - SubGhz* subghz = context; - widget_reset(subghz->widget); - subghz_scene_saved_show_gps_draw_satellites(subghz); -} - -void subghz_scene_saved_show_gps_on_enter(void* context) { - SubGhz* subghz = context; - - subghz_scene_saved_show_gps_draw_satellites(subghz); - - if(subghz->last_settings->gps_baudrate != 0) { - subghz->gps->timer = furi_timer_alloc( - subghz_scene_saved_show_gps_refresh_screen, FuriTimerTypePeriodic, subghz); - furi_timer_start(subghz->gps->timer, 1000); - } - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget); -} - -bool subghz_scene_saved_show_gps_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void subghz_scene_saved_show_gps_on_exit(void* context) { - SubGhz* subghz = context; - - if(subghz->last_settings->gps_baudrate != 0) { - furi_timer_stop(subghz->gps->timer); - furi_timer_free(subghz->gps->timer); - } - - widget_reset(subghz->widget); -} \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_show_gps.c b/applications/main/subghz/scenes/subghz_scene_show_gps.c index f28607652..3ade8c506 100644 --- a/applications/main/subghz/scenes/subghz_scene_show_gps.c +++ b/applications/main/subghz/scenes/subghz_scene_show_gps.c @@ -4,9 +4,6 @@ void subghz_scene_show_gps_draw_satellites(void* context) { SubGhz* subghz = context; - FuriString* text = furi_string_alloc(); - FuriString* time_text = furi_string_alloc(); - DateTime datetime; furi_hal_rtc_get_datetime(&datetime); if((datetime.second - subghz->gps->fix_second) > 15) { @@ -18,81 +15,20 @@ void subghz_scene_show_gps_draw_satellites(void* context) { subghz->gps->fix_second = 0; } - subghz_history_get_time_item_menu(subghz->history, time_text, subghz->idx_menu_chosen); - - double distance = subghz_gps_calc_distance( - (double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen), - (double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen), - (double)subghz->gps->latitude, - (double)subghz->gps->longitude); - - float angle = subghz_gps_calc_angle( - (double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen), - (double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen), - (double)subghz->gps->latitude, - (double)subghz->gps->longitude); - - char* angle_str = "?"; - if(angle > -22.5 && angle <= 22.5) { - angle_str = "E"; - } else if(angle > 22.5 && angle <= 67.5) { - angle_str = "NE"; - } else if(angle > 67.5 && angle <= 112.5) { - angle_str = "N"; - } else if(angle > 112.5 && angle <= 157.5) { - angle_str = "NW"; - } else if(angle < -22.5 && angle >= -67.5) { - angle_str = "SE"; - } else if(angle < -67.5 && angle >= -112.5) { - angle_str = "S"; - } else if(angle < -112.5 && angle >= -157.5) { - angle_str = "SW"; - } else if(angle < -157.5 || angle >= 157.5) { - angle_str = "W"; - } - - FuriString* lat_str = furi_string_alloc(); - FuriString* lon_str = furi_string_alloc(); - - if(isnan(subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen))) { - furi_string_printf(lat_str, "N/A"); + float latitude, longitude; + // Get from saved file or from history + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowGps)) { + latitude = subghz_txrx_get_latitude(subghz->txrx); + longitude = subghz_txrx_get_longitude(subghz->txrx); } else { - furi_string_printf( - lat_str, - "%f", - (double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen)); + latitude = subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen); + longitude = subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen); } - if(isnan(subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen))) { - furi_string_printf(lon_str, "N/A"); - } else { - furi_string_printf( - lon_str, - "%f", - (double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen)); - } - - furi_string_printf( - text, - "Captured at: %s,\r\n%s Time: %s\r\n\r\nRealtime: Sats: %d\r\nDistance: %.2f%s Dir: %s\r\nGPS time: %02d:%02d:%02d UTC", - furi_string_get_cstr(lat_str), - furi_string_get_cstr(lon_str), - furi_string_get_cstr(time_text), - subghz->gps->satellites, - subghz->gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0, - distance > 1 ? "km" : "m", - angle_str, - subghz->gps->fix_hour, - subghz->gps->fix_minute, - subghz->gps->fix_second); - - widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text)); - - furi_string_free(lat_str); - furi_string_free(lon_str); - - furi_string_free(text); - furi_string_free(time_text); + FuriString* text_str = furi_string_alloc(); + subghz->gps->get_descr(subghz->gps, text_str, latitude, longitude); + widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text_str)); + furi_string_free(text_str); } void subghz_scene_show_gps_refresh_screen(void* context) { @@ -106,18 +42,24 @@ void subghz_scene_show_gps_on_enter(void* context) { subghz_scene_show_gps_draw_satellites(subghz); - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { subghz->gps->timer = furi_timer_alloc(subghz_scene_show_gps_refresh_screen, FuriTimerTypePeriodic, subghz); furi_timer_start(subghz->gps->timer, 1000); } + + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget); } bool subghz_scene_show_gps_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; + + // No rx blink if opened from saved file + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowGps)) return false; + if(event.type == SceneManagerEventTypeTick) { if(subghz->state_notifications == SubGhzNotificationStateRx) { - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { if(subghz->gps->satellites > 0) { notification_message(subghz->notifications, &sequence_blink_green_10); } else { @@ -134,7 +76,7 @@ bool subghz_scene_show_gps_on_event(void* context, SceneManagerEvent event) { void subghz_scene_show_gps_on_exit(void* context) { SubGhz* subghz = context; - if(subghz->last_settings->gps_baudrate != 0) { + if(subghz->gps) { furi_timer_stop(subghz->gps->timer); furi_timer_free(subghz->gps->timer); } diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 1f4910e1d..a884759dd 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -251,10 +251,8 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { //Init Error_str subghz->error_str = furi_string_alloc(); - subghz->gps = subghz_gps_init(); if(subghz->last_settings->gps_baudrate != 0) { - subghz_gps_set_baudrate(subghz->gps, subghz->last_settings->gps_baudrate); - subghz_gps_start(subghz->gps); + subghz->gps = subghz_gps_plugin_init(subghz->last_settings->gps_baudrate); } return subghz; @@ -352,10 +350,9 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { furi_string_free(subghz->file_path_tmp); // GPS - if(subghz->last_settings->gps_baudrate != 0) { - subghz_gps_stop(subghz->gps); + if(subghz->gps) { + subghz_gps_plugin_deinit(subghz->gps); } - subghz_gps_deinit(subghz->gps); subghz_last_settings_free(subghz->last_settings);