SubGHz: Rework GPS as plugin, fix VGM (#5)

- Streamlined atomic init and deinit
- Load from plugin into RAM dynamically
- Don't attempt load if VGM / Expansion is connected
- Deduplicated some code, cleaned up some other bits
This commit is contained in:
Willy-JL
2024-03-30 03:38:59 +00:00
parent dcb5c50351
commit ef2c955995
15 changed files with 309 additions and 369 deletions

View File

@@ -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"],

View File

@@ -1,6 +1,18 @@
#include "subghz_gps.h"
#include "minmea.h"
#include <expansion/expansion.h>
#include <momentum/momentum.h>
#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 <flipper_application/flipper_application.h>
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;
}

View File

@@ -1,25 +1,18 @@
#include <furi_hal.h>
#include <momentum/momentum.h>
#include <expansion/expansion.h>
#pragma once
#define UART_CH (momentum_settings.uart_nmea_channel)
#include <furi_hal.h>
#include <flipper_application/flipper_application.h>
#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);

View File

@@ -0,0 +1,71 @@
#include "subghz_gps.h"
#include <expansion/expansion.h>
#include <loader/firmware_api/firmware_api.h>
#include <inttypes.h>
#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);
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)
ADD_SCENE(subghz, show_gps, ShowGps)

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);