diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 6ace221d2..1942d40d8 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -803,6 +803,13 @@ MU_TEST(subghz_encoder_dooya_test) { "Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); } +MU_TEST(subghz_decoder_acurite_592txr_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/acurite_592txr.sub"), WS_PROTOCOL_ACURITE_592TXR_NAME), + "Test decoder " WS_PROTOCOL_ACURITE_592TXR_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -879,6 +886,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_smc5326_test); MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); MU_RUN_TEST(subghz_encoder_dooya_test); + MU_RUN_TEST(subghz_decoder_acurite_592txr_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/applications/external/pocsag_pager/application.fam b/applications/external/pocsag_pager/application.fam deleted file mode 100644 index 04634c81f..000000000 --- a/applications/external/pocsag_pager/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="pocsag_pager", - name="POCSAG Pager", - apptype=FlipperAppType.EXTERNAL, - entry_point="pocsag_pager_app", - requires=["gui"], - stack_size=4 * 1024, - fap_icon="pocsag_pager_10px.png", - fap_category="Sub-GHz", - fap_icon_assets="images", - fap_author="@xMasterX & @Shmuma", - fap_version="1.0", - fap_description="App can capture POCSAG 1200 messages on CC1101 supported frequencies.", -) diff --git a/applications/external/pocsag_pager/helpers/pocsag_pager_event.h b/applications/external/pocsag_pager/helpers/pocsag_pager_event.h deleted file mode 100644 index 8bcf64a30..000000000 --- a/applications/external/pocsag_pager/helpers/pocsag_pager_event.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef enum { - //PCSGCustomEvent - PCSGCustomEventStartId = 100, - - PCSGCustomEventSceneSettingLock, - - PCSGCustomEventViewReceiverOK, - PCSGCustomEventViewReceiverConfig, - PCSGCustomEventViewReceiverBack, - PCSGCustomEventViewReceiverOffDisplay, - PCSGCustomEventViewReceiverUnlock, -} PCSGCustomEvent; diff --git a/applications/external/pocsag_pager/helpers/pocsag_pager_types.h b/applications/external/pocsag_pager/helpers/pocsag_pager_types.h deleted file mode 100644 index fabd7f321..000000000 --- a/applications/external/pocsag_pager/helpers/pocsag_pager_types.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#define PCSG_VERSION_APP "0.1" -#define PCSG_DEVELOPED "@xMasterX & @Shmuma" -#define PCSG_GITHUB "https://github.com/xMasterX/flipper-pager" - -#define PCSG_KEY_FILE_VERSION 1 -#define PCSG_KEY_FILE_TYPE "Flipper POCSAG Pager Key File" - -/** PCSGRxKeyState state */ -typedef enum { - PCSGRxKeyStateIDLE, - PCSGRxKeyStateBack, - PCSGRxKeyStateStart, - PCSGRxKeyStateAddKey, -} PCSGRxKeyState; - -/** PCSGHopperState state */ -typedef enum { - PCSGHopperStateOFF, - PCSGHopperStateRunnig, - PCSGHopperStatePause, - PCSGHopperStateRSSITimeOut, -} PCSGHopperState; - -/** PCSGLock */ -typedef enum { - PCSGLockOff, - PCSGLockOn, -} PCSGLock; - -typedef enum { - POCSAGPagerViewVariableItemList, - POCSAGPagerViewSubmenu, - POCSAGPagerViewReceiver, - POCSAGPagerViewReceiverInfo, - POCSAGPagerViewWidget, -} POCSAGPagerView; - -/** POCSAGPagerTxRx state */ -typedef enum { - PCSGTxRxStateIDLE, - PCSGTxRxStateRx, - PCSGTxRxStateTx, - PCSGTxRxStateSleep, -} PCSGTxRxState; diff --git a/applications/external/pocsag_pager/helpers/radio_device_loader.c b/applications/external/pocsag_pager/helpers/radio_device_loader.c deleted file mode 100644 index ce0920755..000000000 --- a/applications/external/pocsag_pager/helpers/radio_device_loader.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - is_connect = subghz_devices_is_connect(subghz_devices_get_by_name(name)); - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)); -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/pocsag_pager/helpers/radio_device_loader.h b/applications/external/pocsag_pager/helpers/radio_device_loader.h deleted file mode 100644 index bae4bacf2..000000000 --- a/applications/external/pocsag_pager/helpers/radio_device_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/pocsag_pager/images/Message_8x7.png b/applications/external/pocsag_pager/images/Message_8x7.png deleted file mode 100644 index 642688cd5..000000000 Binary files a/applications/external/pocsag_pager/images/Message_8x7.png and /dev/null differ diff --git a/applications/external/pocsag_pager/pocsag_pager_10px.png b/applications/external/pocsag_pager/pocsag_pager_10px.png deleted file mode 100644 index a5686c1c0..000000000 Binary files a/applications/external/pocsag_pager/pocsag_pager_10px.png and /dev/null differ diff --git a/applications/external/pocsag_pager/pocsag_pager_app.c b/applications/external/pocsag_pager/pocsag_pager_app.c deleted file mode 100644 index 70ff49f1a..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "pocsag_pager_app_i.h" - -#include -#include -#include -#include "protocols/protocol_items.h" - -static bool pocsag_pager_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - POCSAGPagerApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool pocsag_pager_app_back_event_callback(void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void pocsag_pager_app_tick_event_callback(void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -POCSAGPagerApp* pocsag_pager_app_alloc() { - POCSAGPagerApp* app = malloc(sizeof(POCSAGPagerApp)); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&pocsag_pager_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, pocsag_pager_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, pocsag_pager_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, pocsag_pager_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Variable Item List - app->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewVariableItemList, - variable_item_list_get_view(app->variable_item_list)); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, POCSAGPagerViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, POCSAGPagerViewWidget, widget_get_view(app->widget)); - - // Receiver - app->pcsg_receiver = pcsg_view_receiver_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewReceiver, - pcsg_view_receiver_get_view(app->pcsg_receiver)); - - // Receiver Info - app->pcsg_receiver_info = pcsg_view_receiver_info_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - POCSAGPagerViewReceiverInfo, - pcsg_view_receiver_info_get_view(app->pcsg_receiver_info)); - - //init setting - app->setting = subghz_setting_alloc(); - - //ToDo FIX file name setting - - subghz_setting_load(app->setting, EXT_PATH("pocsag/settings.txt")); - - //init Worker & Protocol & History - app->lock = PCSGLockOff; - app->txrx = malloc(sizeof(POCSAGPagerTxRx)); - app->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); - app->txrx->preset->name = furi_string_alloc(); - - furi_hal_power_suppress_charge_enter(); - - // Radio Devices init & load - subghz_devices_init(); - app->txrx->radio_device = - radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - - // Custom Presets load without using config file - - FlipperFormat* temp_fm_preset = flipper_format_string_alloc(); - flipper_format_write_string_cstr( - temp_fm_preset, - (const char*)"Custom_preset_data", - (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 83 10 67 15 24 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); - flipper_format_rewind(temp_fm_preset); - subghz_setting_load_custom_preset(app->setting, (const char*)"FM95", temp_fm_preset); - - flipper_format_free(temp_fm_preset); - - // custom presets loading - end - - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - - app->txrx->hopper_state = PCSGHopperStateOFF; - app->txrx->history = pcsg_history_alloc(); - app->txrx->worker = subghz_worker_alloc(); - app->txrx->environment = subghz_environment_alloc(); - subghz_environment_set_protocol_registry( - app->txrx->environment, (void*)&pocsag_pager_protocol_registry); - app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); - - subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); - subghz_worker_set_overrun_callback( - app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); - subghz_worker_set_pair_callback( - app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); - subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneStart); - - return app; -} - -void pocsag_pager_app_free(POCSAGPagerApp* app) { - furi_assert(app); - - // Radio Devices sleep & off - pcsg_sleep(app); - radio_device_loader_end(app->txrx->radio_device); - - subghz_devices_deinit(); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewSubmenu); - submenu_free(app->submenu); - - // Variable Item List - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewVariableItemList); - variable_item_list_free(app->variable_item_list); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewWidget); - widget_free(app->widget); - - // Receiver - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewReceiver); - pcsg_view_receiver_free(app->pcsg_receiver); - - // Receiver Info - view_dispatcher_remove_view(app->view_dispatcher, POCSAGPagerViewReceiverInfo); - pcsg_view_receiver_info_free(app->pcsg_receiver_info); - - //setting - subghz_setting_free(app->setting); - - //Worker & Protocol & History - subghz_receiver_free(app->txrx->receiver); - subghz_environment_free(app->txrx->environment); - pcsg_history_free(app->txrx->history); - subghz_worker_free(app->txrx->worker); - furi_string_free(app->txrx->preset->name); - free(app->txrx->preset); - free(app->txrx); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - furi_hal_power_suppress_charge_exit(); - - free(app); -} - -int32_t pocsag_pager_app(void* p) { - UNUSED(p); - POCSAGPagerApp* pocsag_pager_app = pocsag_pager_app_alloc(); - - view_dispatcher_run(pocsag_pager_app->view_dispatcher); - - pocsag_pager_app_free(pocsag_pager_app); - - return 0; -} diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.c b/applications/external/pocsag_pager/pocsag_pager_app_i.c deleted file mode 100644 index 8dda1d8b6..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "pocsag_pager_app_i.h" - -#define TAG "POCSAGPager" -#include - -void pcsg_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(context); - POCSAGPagerApp* app = context; - furi_string_set(app->txrx->preset->name, preset_name); - app->txrx->preset->frequency = frequency; - app->txrx->preset->data = preset_data; - app->txrx->preset->data_size = preset_data_size; -} - -void pcsg_get_frequency_modulation( - POCSAGPagerApp* app, - FuriString* frequency, - FuriString* modulation) { - furi_assert(app); - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - app->txrx->preset->frequency / 1000000 % 1000, - app->txrx->preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(app->txrx->preset->name)); - } -} - -void pcsg_begin(POCSAGPagerApp* app, uint8_t* preset_data) { - furi_assert(app); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data); - - // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency) { - furi_assert(app); - if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) { - furi_crash("POCSAGPager: Incorrect RX frequency."); - } - furi_assert( - app->txrx->txrx_state != PCSGTxRxStateRx && app->txrx->txrx_state != PCSGTxRxStateSleep); - - subghz_devices_idle(app->txrx->radio_device); - uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency); - - // Not need. init in subghz_devices_start_async_tx - // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - subghz_devices_flush_rx(app->txrx->radio_device); - subghz_devices_set_rx(app->txrx->radio_device); - - subghz_devices_start_async_rx( - app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker); - subghz_worker_start(app->txrx->worker); - app->txrx->txrx_state = PCSGTxRxStateRx; - return value; -} - -void pcsg_idle(POCSAGPagerApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state != PCSGTxRxStateSleep); - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -void pcsg_rx_end(POCSAGPagerApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state == PCSGTxRxStateRx); - if(subghz_worker_is_running(app->txrx->worker)) { - subghz_worker_stop(app->txrx->worker); - subghz_devices_stop_async_rx(app->txrx->radio_device); - } - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateIDLE; -} - -void pcsg_sleep(POCSAGPagerApp* app) { - furi_assert(app); - subghz_devices_sleep(app->txrx->radio_device); - app->txrx->txrx_state = PCSGTxRxStateSleep; -} - -void pcsg_hopper_update(POCSAGPagerApp* app) { - furi_assert(app); - - switch(app->txrx->hopper_state) { - case PCSGHopperStateOFF: - return; - break; - case PCSGHopperStatePause: - return; - break; - case PCSGHopperStateRSSITimeOut: - if(app->txrx->hopper_timeout != 0) { - app->txrx->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(app->txrx->hopper_state != PCSGHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = subghz_devices_get_rssi(app->txrx->radio_device); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - app->txrx->hopper_timeout = 10; - app->txrx->hopper_state = PCSGHopperStateRSSITimeOut; - return; - } - } else { - app->txrx->hopper_state = PCSGHopperStateRunnig; - } - // Select next frequency - if(app->txrx->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(app->setting) - 1) { - app->txrx->hopper_idx_frequency++; - } else { - app->txrx->hopper_idx_frequency = 0; - } - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - }; - if(app->txrx->txrx_state == PCSGTxRxStateIDLE) { - subghz_receiver_reset(app->txrx->receiver); - app->txrx->preset->frequency = - subghz_setting_get_hopper_frequency(app->setting, app->txrx->hopper_idx_frequency); - pcsg_rx(app, app->txrx->preset->frequency); - } -} diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.h b/applications/external/pocsag_pager/pocsag_pager_app_i.h deleted file mode 100644 index c31e5ae1a..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "helpers/pocsag_pager_types.h" -#include "helpers/radio_device_loader.h" - -#include "scenes/pocsag_pager_scene.h" -#include -#include -#include -#include -#include -#include -#include -#include "views/pocsag_pager_receiver.h" -#include "views/pocsag_pager_receiver_info.h" -#include "pocsag_pager_history.h" - -#include -#include -#include -#include -#include -#include - -typedef struct POCSAGPagerApp POCSAGPagerApp; - -struct POCSAGPagerTxRx { - SubGhzWorker* worker; - - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzRadioPreset* preset; - PCSGHistory* history; - uint16_t idx_menu_chosen; - PCSGTxRxState txrx_state; - PCSGHopperState hopper_state; - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - PCSGRxKeyState rx_key_state; - - const SubGhzDevice* radio_device; -}; - -typedef struct POCSAGPagerTxRx POCSAGPagerTxRx; - -struct POCSAGPagerApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - POCSAGPagerTxRx* txrx; - SceneManager* scene_manager; - NotificationApp* notifications; - VariableItemList* variable_item_list; - Submenu* submenu; - Widget* widget; - PCSGReceiver* pcsg_receiver; - PCSGReceiverInfo* pcsg_receiver_info; - PCSGLock lock; - SubGhzSetting* setting; -}; - -void pcsg_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); -void pcsg_get_frequency_modulation( - POCSAGPagerApp* app, - FuriString* frequency, - FuriString* modulation); -void pcsg_begin(POCSAGPagerApp* app, uint8_t* preset_data); -uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency); -void pcsg_idle(POCSAGPagerApp* app); -void pcsg_rx_end(POCSAGPagerApp* app); -void pcsg_sleep(POCSAGPagerApp* app); -void pcsg_hopper_update(POCSAGPagerApp* app); diff --git a/applications/external/pocsag_pager/pocsag_pager_history.c b/applications/external/pocsag_pager/pocsag_pager_history.c deleted file mode 100644 index d5f97b571..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_history.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "pocsag_pager_history.h" -#include -#include -#include -#include "protocols/pcsg_generic.h" - -#include - -#define PCSG_HISTORY_MAX 50 -#define TAG "PCSGHistory" - -typedef struct { - FuriString* item_str; - FlipperFormat* flipper_string; - uint8_t type; - SubGhzRadioPreset* preset; -} PCSGHistoryItem; - -ARRAY_DEF(PCSGHistoryItemArray, PCSGHistoryItem, M_POD_OPLIST) - -#define M_OPL_PCSGHistoryItemArray_t() ARRAY_OPLIST(PCSGHistoryItemArray, M_POD_OPLIST) - -typedef struct { - PCSGHistoryItemArray_t data; -} PCSGHistoryStruct; - -struct PCSGHistory { - uint32_t last_update_timestamp; - uint16_t last_index_write; - uint8_t code_last_hash_data; - FuriString* tmp_string; - PCSGHistoryStruct* history; -}; - -PCSGHistory* pcsg_history_alloc(void) { - PCSGHistory* instance = malloc(sizeof(PCSGHistory)); - instance->tmp_string = furi_string_alloc(); - instance->history = malloc(sizeof(PCSGHistoryStruct)); - PCSGHistoryItemArray_init(instance->history->data); - return instance; -} - -void pcsg_history_free(PCSGHistory* instance) { - furi_assert(instance); - furi_string_free(instance->tmp_string); - for - M_EACH(item, instance->history->data, PCSGHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - PCSGHistoryItemArray_clear(instance->history->data); - free(instance->history); - free(instance); -} - -uint32_t pcsg_history_get_frequency(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->preset->frequency; -} - -SubGhzRadioPreset* pcsg_history_get_radio_preset(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->preset; -} - -const char* pcsg_history_get_preset(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return furi_string_get_cstr(item->preset->name); -} - -void pcsg_history_reset(PCSGHistory* instance) { - furi_assert(instance); - furi_string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, PCSGHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - PCSGHistoryItemArray_reset(instance->history->data); - instance->last_index_write = 0; - instance->code_last_hash_data = 0; -} - -uint16_t pcsg_history_get_item(PCSGHistory* instance) { - furi_assert(instance); - return instance->last_index_write; -} - -uint8_t pcsg_history_get_type_protocol(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - return item->type; -} - -const char* pcsg_history_get_protocol_name(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - furi_string_reset(instance->tmp_string); - } - return furi_string_get_cstr(instance->tmp_string); -} - -FlipperFormat* pcsg_history_get_raw_data(PCSGHistory* instance, uint16_t idx) { - furi_assert(instance); - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - if(item->flipper_string) { - return item->flipper_string; - } else { - return NULL; - } -} -bool pcsg_history_get_text_space_left(PCSGHistory* instance, FuriString* output) { - furi_assert(instance); - if(instance->last_index_write == PCSG_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); - return true; - } - if(output != NULL) - furi_string_printf(output, "%02u/%02u", instance->last_index_write, PCSG_HISTORY_MAX); - return false; -} - -void pcsg_history_get_text_item_menu(PCSGHistory* instance, FuriString* output, uint16_t idx) { - PCSGHistoryItem* item = PCSGHistoryItemArray_get(instance->history->data, idx); - furi_string_set(output, item->item_str); -} - -PCSGHistoryStateAddKey - pcsg_history_add_to_history(PCSGHistory* instance, void* context, SubGhzRadioPreset* preset) { - furi_assert(instance); - furi_assert(context); - - if(instance->last_index_write >= PCSG_HISTORY_MAX) return PCSGHistoryStateAddKeyOverflow; - - SubGhzProtocolDecoderBase* decoder_base = context; - if((instance->code_last_hash_data == - subghz_protocol_decoder_base_get_hash_data(decoder_base)) && - ((furi_get_tick() - instance->last_update_timestamp) < 500)) { - instance->last_update_timestamp = furi_get_tick(); - return PCSGHistoryStateAddKeyTimeOut; - } - - instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); - instance->last_update_timestamp = furi_get_tick(); - - FlipperFormat* fff = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, fff, preset); - - do { - if(!flipper_format_rewind(fff)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - - } while(false); - flipper_format_free(fff); - - PCSGHistoryItem* item = PCSGHistoryItemArray_push_raw(instance->history->data); - item->preset = malloc(sizeof(SubGhzRadioPreset)); - item->type = decoder_base->protocol->type; - item->preset->frequency = preset->frequency; - item->preset->name = furi_string_alloc(); - furi_string_set(item->preset->name, preset->name); - item->preset->data = preset->data; - item->preset->data_size = preset->data_size; - - item->item_str = furi_string_alloc(); - item->flipper_string = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - - do { - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - FuriString* temp_ric = furi_string_alloc(); - if(!flipper_format_read_string(item->flipper_string, "Ric", temp_ric)) { - FURI_LOG_E(TAG, "Missing Ric"); - break; - } - - FuriString* temp_message = furi_string_alloc(); - if(!flipper_format_read_string(item->flipper_string, "Message", temp_message)) { - FURI_LOG_E(TAG, "Missing Message"); - break; - } - - furi_string_printf( - item->item_str, - "%s%s", - furi_string_get_cstr(temp_ric), - furi_string_get_cstr(temp_message)); - - furi_string_free(temp_message); - furi_string_free(temp_ric); - - } while(false); - instance->last_index_write++; - return PCSGHistoryStateAddKeyNewDada; - - return PCSGHistoryStateAddKeyUnknown; -} diff --git a/applications/external/pocsag_pager/pocsag_pager_history.h b/applications/external/pocsag_pager/pocsag_pager_history.h deleted file mode 100644 index 7528fcc29..000000000 --- a/applications/external/pocsag_pager/pocsag_pager_history.h +++ /dev/null @@ -1,112 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include - -typedef struct PCSGHistory PCSGHistory; - -/** History state add key */ -typedef enum { - PCSGHistoryStateAddKeyUnknown, - PCSGHistoryStateAddKeyTimeOut, - PCSGHistoryStateAddKeyNewDada, - PCSGHistoryStateAddKeyUpdateData, - PCSGHistoryStateAddKeyOverflow, -} PCSGHistoryStateAddKey; - -/** Allocate PCSGHistory - * - * @return PCSGHistory* - */ -PCSGHistory* pcsg_history_alloc(void); - -/** Free PCSGHistory - * - * @param instance - PCSGHistory instance - */ -void pcsg_history_free(PCSGHistory* instance); - -/** Clear history - * - * @param instance - PCSGHistory instance - */ -void pcsg_history_reset(PCSGHistory* instance); - -/** Get frequency to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return frequency - frequency Hz - */ -uint32_t pcsg_history_get_frequency(PCSGHistory* instance, uint16_t idx); - -SubGhzRadioPreset* pcsg_history_get_radio_preset(PCSGHistory* instance, uint16_t idx); - -/** Get preset to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return preset - preset name - */ -const char* pcsg_history_get_preset(PCSGHistory* instance, uint16_t idx); - -/** Get history index write - * - * @param instance - PCSGHistory instance - * @return idx - current record index - */ -uint16_t pcsg_history_get_item(PCSGHistory* instance); - -/** Get type protocol to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return type - type protocol - */ -uint8_t pcsg_history_get_type_protocol(PCSGHistory* instance, uint16_t idx); - -/** Get name protocol to history[idx] - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return name - const char* name protocol - */ -const char* pcsg_history_get_protocol_name(PCSGHistory* instance, uint16_t idx); - -/** Get string item menu to history[idx] - * - * @param instance - PCSGHistory instance - * @param output - FuriString* output - * @param idx - record index - */ -void pcsg_history_get_text_item_menu(PCSGHistory* instance, FuriString* output, uint16_t idx); - -/** Get string the remaining number of records to history - * - * @param instance - PCSGHistory instance - * @param output - FuriString* output - * @return bool - is FUUL - */ -bool pcsg_history_get_text_space_left(PCSGHistory* instance, FuriString* output); - -/** Add protocol to history - * - * @param instance - PCSGHistory instance - * @param context - SubGhzProtocolCommon context - * @param preset - SubGhzRadioPreset preset - * @return PCSGHistoryStateAddKey; - */ -PCSGHistoryStateAddKey - pcsg_history_add_to_history(PCSGHistory* instance, void* context, SubGhzRadioPreset* preset); - -/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data - * - * @param instance - PCSGHistory instance - * @param idx - record index - * @return SubGhzProtocolCommonLoad* - */ -FlipperFormat* pcsg_history_get_raw_data(PCSGHistory* instance, uint16_t idx); diff --git a/applications/external/pocsag_pager/protocols/protocol_items.c b/applications/external/pocsag_pager/protocols/protocol_items.c deleted file mode 100644 index 7e6ebebbd..000000000 --- a/applications/external/pocsag_pager/protocols/protocol_items.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "protocol_items.h" - -const SubGhzProtocol* pocsag_pager_protocol_registry_items[] = { - &subghz_protocol_pocsag, -}; - -const SubGhzProtocolRegistry pocsag_pager_protocol_registry = { - .items = pocsag_pager_protocol_registry_items, - .size = COUNT_OF(pocsag_pager_protocol_registry_items)}; \ No newline at end of file diff --git a/applications/external/pocsag_pager/protocols/protocol_items.h b/applications/external/pocsag_pager/protocols/protocol_items.h deleted file mode 100644 index 3981cd2e3..000000000 --- a/applications/external/pocsag_pager/protocols/protocol_items.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "../pocsag_pager_app_i.h" - -#include "pocsag.h" - -extern const SubGhzProtocolRegistry pocsag_pager_protocol_registry; diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c deleted file mode 100644 index cc2abd7e0..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../views/pocsag_pager_receiver.h" - -static const NotificationSequence subghs_sequence_rx = { - &message_green_255, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_50, - NULL, -}; - -static const NotificationSequence subghs_sequence_rx_locked = { - &message_green_255, - - &message_display_backlight_on, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_500, - - &message_display_backlight_off, - NULL, -}; - -static void pocsag_pager_scene_receiver_update_statusbar(void* context) { - POCSAGPagerApp* app = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!pcsg_history_get_text_space_left(app->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - - pcsg_get_frequency_modulation(app, frequency_str, modulation_str); - - pcsg_view_receiver_add_data_statusbar( - app->pcsg_receiver, - furi_string_get_cstr(frequency_str), - furi_string_get_cstr(modulation_str), - furi_string_get_cstr(history_stat_str)); - - furi_string_free(frequency_str); - furi_string_free(modulation_str); - } else { - pcsg_view_receiver_add_data_statusbar( - app->pcsg_receiver, furi_string_get_cstr(history_stat_str), "", ""); - } - furi_string_free(history_stat_str); -} - -void pocsag_pager_scene_receiver_callback(PCSGCustomEvent event, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void pocsag_pager_scene_receiver_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(pcsg_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - PCSGHistoryStateAddKeyNewDada) { - furi_string_reset(str_buff); - - pcsg_history_get_text_item_menu( - app->txrx->history, str_buff, pcsg_history_get_item(app->txrx->history) - 1); - pcsg_view_receiver_add_item_to_menu( - app->pcsg_receiver, - furi_string_get_cstr(str_buff), - pcsg_history_get_type_protocol( - app->txrx->history, pcsg_history_get_item(app->txrx->history) - 1)); - - pocsag_pager_scene_receiver_update_statusbar(app); - notification_message(app->notifications, &sequence_blink_green_10); - if(app->lock != PCSGLockOn) { - notification_message(app->notifications, &subghs_sequence_rx); - } else { - notification_message(app->notifications, &subghs_sequence_rx_locked); - } - } - subghz_receiver_reset(receiver); - furi_string_free(str_buff); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; -} - -void pocsag_pager_scene_receiver_on_enter(void* context) { - POCSAGPagerApp* app = context; - - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(app->txrx->rx_key_state == PCSGRxKeyStateIDLE) { - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - pcsg_history_reset(app->txrx->history); - app->txrx->rx_key_state = PCSGRxKeyStateStart; - } - - pcsg_view_receiver_set_lock(app->pcsg_receiver, app->lock); - pcsg_view_receiver_set_ext_module_state( - app->pcsg_receiver, radio_device_loader_is_external(app->txrx->radio_device)); - - //Load history to receiver - pcsg_view_receiver_exit(app->pcsg_receiver); - for(uint8_t i = 0; i < pcsg_history_get_item(app->txrx->history); i++) { - furi_string_reset(str_buff); - pcsg_history_get_text_item_menu(app->txrx->history, str_buff, i); - pcsg_view_receiver_add_item_to_menu( - app->pcsg_receiver, - furi_string_get_cstr(str_buff), - pcsg_history_get_type_protocol(app->txrx->history, i)); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; - } - furi_string_free(str_buff); - pocsag_pager_scene_receiver_update_statusbar(app); - - pcsg_view_receiver_set_callback(app->pcsg_receiver, pocsag_pager_scene_receiver_callback, app); - subghz_receiver_set_rx_callback( - app->txrx->receiver, pocsag_pager_scene_receiver_add_to_history_callback, app); - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - }; - if((app->txrx->txrx_state == PCSGTxRxStateIDLE) || - (app->txrx->txrx_state == PCSGTxRxStateSleep)) { - // Start RX - pcsg_begin( - app, - subghz_setting_get_preset_data_by_name( - app->setting, furi_string_get_cstr(app->txrx->preset->name))); - - pcsg_rx(app, app->txrx->preset->frequency); - } - - pcsg_view_receiver_set_idx_menu(app->pcsg_receiver, app->txrx->idx_menu_chosen); - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewReceiver); -} - -bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case PCSGCustomEventViewReceiverBack: - // Stop CC1101 Rx - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - pcsg_rx_end(app); - pcsg_idle(app); - }; - app->txrx->hopper_state = PCSGHopperStateOFF; - app->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); - - app->txrx->rx_key_state = PCSGRxKeyStateIDLE; - pcsg_preset_init(app, "FM95", 439987500, NULL, 0); - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, POCSAGPagerSceneStart); - consumed = true; - break; - case PCSGCustomEventViewReceiverOK: - app->txrx->idx_menu_chosen = pcsg_view_receiver_get_idx_menu(app->pcsg_receiver); - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiverInfo); - consumed = true; - break; - case PCSGCustomEventViewReceiverConfig: - app->txrx->idx_menu_chosen = pcsg_view_receiver_get_idx_menu(app->pcsg_receiver); - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiverConfig); - consumed = true; - break; - case PCSGCustomEventViewReceiverOffDisplay: - notification_message(app->notifications, &sequence_display_backlight_off); - consumed = true; - break; - case PCSGCustomEventViewReceiverUnlock: - app->lock = PCSGLockOff; - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - if(app->txrx->hopper_state != PCSGHopperStateOFF) { - pcsg_hopper_update(app); - pocsag_pager_scene_receiver_update_statusbar(app); - } - // Get current RSSI - float rssi = subghz_devices_get_rssi(app->txrx->radio_device); - pcsg_receiver_rssi(app->pcsg_receiver, rssi); - - if(app->txrx->txrx_state == PCSGTxRxStateRx) { - notification_message(app->notifications, &sequence_blink_cyan_10); - } - } - return consumed; -} - -void pocsag_pager_scene_receiver_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c deleted file mode 100644 index 4644d99c0..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const pocsag_pager_scene_on_enter_handlers[])(void*) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const pocsag_pager_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const pocsag_pager_scene_on_exit_handlers[])(void* context) = { -#include "pocsag_pager_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers pocsag_pager_scene_handlers = { - .on_enter_handlers = pocsag_pager_scene_on_enter_handlers, - .on_event_handlers = pocsag_pager_scene_on_event_handlers, - .on_exit_handlers = pocsag_pager_scene_on_exit_handlers, - .scene_num = POCSAGPagerSceneNum, -}; diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h b/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h deleted file mode 100644 index d5c64f9d9..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) POCSAGPagerScene##id, -typedef enum { -#include "pocsag_pager_scene_config.h" - POCSAGPagerSceneNum, -} POCSAGPagerScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers pocsag_pager_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "pocsag_pager_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c deleted file mode 100644 index 2af33c8bf..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_about.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../helpers/pocsag_pager_types.h" - -void pocsag_pager_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { - POCSAGPagerApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void pocsag_pager_scene_about_on_enter(void* context) { - POCSAGPagerApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", PCSG_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by:\n%s\n\n", PCSG_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", PCSG_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf(temp_str, "Receiving POCSAG Pager \nmessages\n\n"); - - furi_string_cat_printf(temp_str, "Supported protocols:\n"); - size_t i = 0; - const char* protocol_name = - subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - do { - furi_string_cat_printf(temp_str, "%s\n", protocol_name); - protocol_name = subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - } while(protocol_name != NULL); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! POCSAG Pager \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewWidget); -} - -bool pocsag_pager_scene_about_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void pocsag_pager_scene_about_on_exit(void* context) { - POCSAGPagerApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h deleted file mode 100644 index 8136af14f..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_config.h +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SCENE(pocsag_pager, start, Start) -ADD_SCENE(pocsag_pager, about, About) -ADD_SCENE(pocsag_pager, receiver, Receiver) -ADD_SCENE(pocsag_pager, receiver_config, ReceiverConfig) -ADD_SCENE(pocsag_pager, receiver_info, ReceiverInfo) diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c deleted file mode 100644 index 154e7d270..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_config.c +++ /dev/null @@ -1,221 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -enum PCSGSettingIndex { - PCSGSettingIndexFrequency, - PCSGSettingIndexHopping, - PCSGSettingIndexModulation, - PCSGSettingIndexLock, -}; - -#define HOPPING_COUNT 2 -const char* const hopping_text[HOPPING_COUNT] = { - "OFF", - "ON", -}; -const uint32_t hopping_value[HOPPING_COUNT] = { - PCSGHopperStateOFF, - PCSGHopperStateRunnig, -}; - -uint8_t pocsag_pager_scene_receiver_config_next_frequency(const uint32_t value, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_frequency_count(app->setting); i++) { - if(value == subghz_setting_get_frequency(app->setting, i)) { - index = i; - break; - } else { - index = subghz_setting_get_frequency_default_index(app->setting); - } - } - return index; -} - -uint8_t pocsag_pager_scene_receiver_config_next_preset(const char* preset_name, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_preset_count(app->setting); i++) { - if(!strcmp(subghz_setting_get_preset_name(app->setting, i), preset_name)) { - index = i; - break; - } else { - // index = subghz_setting_get_frequency_default_index(app ->setting); - } - } - return index; -} - -uint8_t pocsag_pager_scene_receiver_config_hopper_value_index( - const uint32_t value, - const uint32_t values[], - uint8_t values_count, - void* context) { - furi_assert(context); - UNUSED(values_count); - POCSAGPagerApp* app = context; - - if(value == values[0]) { - return 0; - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - " -----"); - return 1; - } -} - -static void pocsag_pager_scene_receiver_config_set_frequency(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - if(app->txrx->hopper_state == PCSGHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, index) / 1000000, - (subghz_setting_get_frequency(app->setting, index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - app->txrx->preset->frequency = subghz_setting_get_frequency(app->setting, index); - } else { - variable_item_set_current_value_index( - item, subghz_setting_get_frequency_default_index(app->setting)); - } -} - -static void pocsag_pager_scene_receiver_config_set_preset(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, index)); - pcsg_preset_init( - app, - subghz_setting_get_preset_name(app->setting, index), - app->txrx->preset->frequency, - subghz_setting_get_preset_data(app->setting, index), - subghz_setting_get_preset_data_size(app->setting, index)); -} - -static void pocsag_pager_scene_receiver_config_set_hopping_running(VariableItem* item) { - POCSAGPagerApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hopping_text[index]); - if(hopping_value[index] == PCSGHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_default_frequency(app->setting) / 1000000, - (subghz_setting_get_default_frequency(app->setting) % 1000000) / 10000); - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - text_buf); - app->txrx->preset->frequency = subghz_setting_get_default_frequency(app->setting); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - " -----"); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } - - app->txrx->hopper_state = hopping_value[index]; -} - -static void - pocsag_pager_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - POCSAGPagerApp* app = context; - if(index == PCSGSettingIndexLock) { - view_dispatcher_send_custom_event(app->view_dispatcher, PCSGCustomEventSceneSettingLock); - } -} - -void pocsag_pager_scene_receiver_config_on_enter(void* context) { - POCSAGPagerApp* app = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - app->variable_item_list, - "Frequency:", - subghz_setting_get_frequency_count(app->setting), - pocsag_pager_scene_receiver_config_set_frequency, - app); - value_index = - pocsag_pager_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app); - scene_manager_set_scene_state( - app->scene_manager, POCSAGPagerSceneReceiverConfig, (uint32_t)item); - variable_item_set_current_value_index(item, value_index); - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, value_index) / 1000000, - (subghz_setting_get_frequency(app->setting, value_index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - - item = variable_item_list_add( - app->variable_item_list, - "Hopping:", - HOPPING_COUNT, - pocsag_pager_scene_receiver_config_set_hopping_running, - app); - value_index = pocsag_pager_scene_receiver_config_hopper_value_index( - app->txrx->hopper_state, hopping_value, HOPPING_COUNT, app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hopping_text[value_index]); - - item = variable_item_list_add( - app->variable_item_list, - "Modulation:", - subghz_setting_get_preset_count(app->setting), - pocsag_pager_scene_receiver_config_set_preset, - app); - value_index = pocsag_pager_scene_receiver_config_next_preset( - furi_string_get_cstr(app->txrx->preset->name), app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, value_index)); - - variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL); - variable_item_list_set_enter_callback( - app->variable_item_list, pocsag_pager_scene_receiver_config_var_list_enter_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewVariableItemList); -} - -bool pocsag_pager_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == PCSGCustomEventSceneSettingLock) { - app->lock = PCSGLockOn; - scene_manager_previous_scene(app->scene_manager); - consumed = true; - } - } - return consumed; -} - -void pocsag_pager_scene_receiver_config_on_exit(void* context) { - POCSAGPagerApp* app = context; - variable_item_list_set_selected_item(app->variable_item_list, 0); - variable_item_list_reset(app->variable_item_list); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c deleted file mode 100644 index 5f17d9fb7..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_receiver_info.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../pocsag_pager_app_i.h" -#include "../views/pocsag_pager_receiver.h" - -void pocsag_pager_scene_receiver_info_callback(PCSGCustomEvent event, void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void pocsag_pager_scene_receiver_info_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - POCSAGPagerApp* app = context; - - if(pcsg_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - PCSGHistoryStateAddKeyUpdateData) { - pcsg_view_receiver_info_update( - app->pcsg_receiver_info, - pcsg_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - subghz_receiver_reset(receiver); - - notification_message(app->notifications, &sequence_blink_green_10); - app->txrx->rx_key_state = PCSGRxKeyStateAddKey; - } -} - -void pocsag_pager_scene_receiver_info_on_enter(void* context) { - POCSAGPagerApp* app = context; - - subghz_receiver_set_rx_callback( - app->txrx->receiver, pocsag_pager_scene_receiver_info_add_to_history_callback, app); - pcsg_view_receiver_info_update( - app->pcsg_receiver_info, - pcsg_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewReceiverInfo); -} - -bool pocsag_pager_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - return consumed; -} - -void pocsag_pager_scene_receiver_info_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c b/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c deleted file mode 100644 index d2a94facb..000000000 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_scene_start.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../pocsag_pager_app_i.h" - -typedef enum { - SubmenuIndexPOCSAGPagerReceiver, - SubmenuIndexPOCSAGPagerAbout, -} SubmenuIndex; - -void pocsag_pager_scene_start_submenu_callback(void* context, uint32_t index) { - POCSAGPagerApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void pocsag_pager_scene_start_on_enter(void* context) { - UNUSED(context); - POCSAGPagerApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, - "Receive messages", - SubmenuIndexPOCSAGPagerReceiver, - pocsag_pager_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "About", - SubmenuIndexPOCSAGPagerAbout, - pocsag_pager_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, POCSAGPagerSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, POCSAGPagerViewSubmenu); -} - -bool pocsag_pager_scene_start_on_event(void* context, SceneManagerEvent event) { - POCSAGPagerApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexPOCSAGPagerAbout) { - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexPOCSAGPagerReceiver) { - scene_manager_next_scene(app->scene_manager, POCSAGPagerSceneReceiver); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, POCSAGPagerSceneStart, event.event); - } - - return consumed; -} - -void pocsag_pager_scene_start_on_exit(void* context) { - POCSAGPagerApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c deleted file mode 100644 index 629c3894e..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c +++ /dev/null @@ -1,479 +0,0 @@ -#include "pocsag_pager_receiver.h" -#include "../pocsag_pager_app_i.h" -#include "pocsag_pager_icons.h" -#include -#include - -#include -#include -#include - -#define FRAME_HEIGHT 12 -#define MAX_LEN_PX 112 -#define MENU_ITEMS 4u -#define UNLOCK_CNT 3 - -#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f - -typedef struct { - FuriString* item_str; - uint8_t type; -} PCSGReceiverMenuItem; - -ARRAY_DEF(PCSGReceiverMenuItemArray, PCSGReceiverMenuItem, M_POD_OPLIST) - -#define M_OPL_PCSGReceiverMenuItemArray_t() ARRAY_OPLIST(PCSGReceiverMenuItemArray, M_POD_OPLIST) - -struct PCSGReceiverHistory { - PCSGReceiverMenuItemArray_t data; -}; - -typedef struct PCSGReceiverHistory PCSGReceiverHistory; - -static const Icon* ReceiverItemIcons[] = { - [SubGhzProtocolTypeUnknown] = &I_Quest_7x8, - [SubGhzProtocolTypeStatic] = &I_Message_8x7, - [SubGhzProtocolTypeDynamic] = &I_Lock_7x8, -}; - -typedef enum { - PCSGReceiverBarShowDefault, - PCSGReceiverBarShowLock, - PCSGReceiverBarShowToUnlockPress, - PCSGReceiverBarShowUnlock, -} PCSGReceiverBarShow; - -struct PCSGReceiver { - PCSGLock lock; - uint8_t lock_count; - FuriTimer* timer; - View* view; - PCSGReceiverCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* history_stat_str; - PCSGReceiverHistory* history; - uint16_t idx; - uint16_t list_offset; - uint16_t history_item; - PCSGReceiverBarShow bar_show; - uint8_t u_rssi; - bool ext_module; -} PCSGReceiverModel; - -void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) { - furi_assert(instance); - with_view_model( - instance->view, - PCSGReceiverModel * model, - { - if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { - model->u_rssi = 0; - } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); - } - }, - true); -} - -void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock lock) { - furi_assert(pcsg_receiver); - pcsg_receiver->lock_count = 0; - if(lock == PCSGLockOn) { - pcsg_receiver->lock = lock; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowLock; }, - true); - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(1000)); - } else { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowDefault; }, - true); - } -} - -void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, PCSGReceiverModel * model, { model->ext_module = is_external; }, true); -} - -void pcsg_view_receiver_set_callback( - PCSGReceiver* pcsg_receiver, - PCSGReceiverCallback callback, - void* context) { - furi_assert(pcsg_receiver); - furi_assert(callback); - pcsg_receiver->callback = callback; - pcsg_receiver->context = context; -} - -static void pcsg_view_receiver_update_offset(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - size_t history_item = model->history_item; - uint16_t bounds = history_item > 3 ? 2 : history_item; - - if(history_item > 3 && model->idx >= (int16_t)(history_item - 1)) { - model->list_offset = model->idx - 3; - } else if(model->list_offset < model->idx - bounds) { - model->list_offset = - CLAMP(model->list_offset + 1, (int16_t)(history_item - bounds), 0); - } else if(model->list_offset > model->idx - bounds) { - model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); - } - }, - true); -} - -void pcsg_view_receiver_add_item_to_menu( - PCSGReceiver* pcsg_receiver, - const char* name, - uint8_t type) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - PCSGReceiverMenuItem* item_menu = - PCSGReceiverMenuItemArray_push_raw(model->history->data); - item_menu->item_str = furi_string_alloc_set(name); - item_menu->type = type; - if((model->idx == model->history_item - 1)) { - model->history_item++; - model->idx++; - } else { - model->history_item++; - } - }, - true); - pcsg_view_receiver_update_offset(pcsg_receiver); -} - -void pcsg_view_receiver_add_data_statusbar( - PCSGReceiver* pcsg_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_set_str(model->frequency_str, frequency_str); - furi_string_set_str(model->preset_str, preset_str); - furi_string_set_str(model->history_stat_str, history_stat_str); - }, - true); -} - -static void pcsg_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); - - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); -} - -static void pcsg_view_rssi_draw(Canvas* canvas, PCSGReceiverModel* model) { - for(uint8_t i = 1; i < model->u_rssi; i++) { - if(i % 5) { - canvas_draw_dot(canvas, 46 + i, 50); - canvas_draw_dot(canvas, 47 + i, 51); - canvas_draw_dot(canvas, 46 + i, 52); - } - } -} - -void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - elements_button_left(canvas, "Config"); - //canvas_draw_line(canvas, 46, 51, 125, 51); - - bool scrollbar = model->history_item > 4; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - PCSGReceiverMenuItem* item_menu; - - for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); - item_menu = PCSGReceiverMenuItemArray_get(model->history->data, idx); - furi_string_set(str_buff, item_menu->item_str); - furi_string_replace_all(str_buff, "#", ""); - elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 7 : MAX_LEN_PX); - if(model->idx == idx) { - pcsg_view_receiver_draw_frame(canvas, i, scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); - canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff)); - furi_string_reset(str_buff); - } - if(scrollbar) { - elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); - } - furi_string_free(str_buff); - - canvas_set_color(canvas, ColorBlack); - - if(model->history_item == 0) { - canvas_draw_icon(canvas, 0, 0, model->ext_module ? &I_Fishing_123x52 : &I_Scanning_123x52); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 44, 10, model->ext_module ? "Ext" : "Int"); - } - - // Draw RSSI - pcsg_view_rssi_draw(canvas, model); - - switch(model->bar_show) { - case PCSGReceiverBarShowLock: - canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); - canvas_draw_str(canvas, 74, 62, "Locked"); - break; - case PCSGReceiverBarShowToUnlockPress: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - canvas_set_font(canvas, FontSecondary); - elements_bold_rounded_frame(canvas, 14, 8, 99, 48); - elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); - canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); - canvas_draw_dot(canvas, 17, 61); - break; - case PCSGReceiverBarShowUnlock: - canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8); - canvas_draw_str(canvas, 74, 62, "Unlocked"); - break; - default: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - break; - } -} - -static void pcsg_view_receiver_timer_callback(void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowDefault; }, - true); - if(pcsg_receiver->lock_count < UNLOCK_CNT) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverOffDisplay, pcsg_receiver->context); - } else { - pcsg_receiver->lock = PCSGLockOff; - pcsg_receiver->callback(PCSGCustomEventViewReceiverUnlock, pcsg_receiver->context); - } - pcsg_receiver->lock_count = 0; -} - -bool pcsg_view_receiver_input(InputEvent* event, void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - - if(pcsg_receiver->lock == PCSGLockOn) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowToUnlockPress; }, - true); - if(pcsg_receiver->lock_count == 0) { - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(1000)); - } - if(event->key == InputKeyBack && event->type == InputTypeShort) { - pcsg_receiver->lock_count++; - } - if(pcsg_receiver->lock_count >= UNLOCK_CNT) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverUnlock, pcsg_receiver->context); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { model->bar_show = PCSGReceiverBarShowUnlock; }, - true); - pcsg_receiver->lock = PCSGLockOff; - furi_timer_start(pcsg_receiver->timer, pdMS_TO_TICKS(650)); - } - - return true; - } - - if(event->key == InputKeyBack && event->type == InputTypeShort) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverBack, pcsg_receiver->context); - } else if( - event->key == InputKeyUp && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->idx != 0) model->idx--; - }, - true); - } else if( - event->key == InputKeyDown && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->history_item && model->idx != model->history_item - 1) model->idx++; - }, - true); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverConfig, pcsg_receiver->context); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - if(model->history_item != 0) { - pcsg_receiver->callback(PCSGCustomEventViewReceiverOK, pcsg_receiver->context); - } - }, - false); - } - - pcsg_view_receiver_update_offset(pcsg_receiver); - - return true; -} - -void pcsg_view_receiver_enter(void* context) { - furi_assert(context); -} - -void pcsg_view_receiver_exit(void* context) { - furi_assert(context); - PCSGReceiver* pcsg_receiver = context; - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_reset(model->frequency_str); - furi_string_reset(model->preset_str); - furi_string_reset(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, PCSGReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - PCSGReceiverMenuItemArray_reset(model->history->data); - model->idx = 0; - model->list_offset = 0; - model->history_item = 0; - }, - false); - furi_timer_stop(pcsg_receiver->timer); -} - -PCSGReceiver* pcsg_view_receiver_alloc() { - PCSGReceiver* pcsg_receiver = malloc(sizeof(PCSGReceiver)); - - // View allocation and configuration - pcsg_receiver->view = view_alloc(); - - pcsg_receiver->lock = PCSGLockOff; - pcsg_receiver->lock_count = 0; - view_allocate_model(pcsg_receiver->view, ViewModelTypeLocking, sizeof(PCSGReceiverModel)); - view_set_context(pcsg_receiver->view, pcsg_receiver); - view_set_draw_callback(pcsg_receiver->view, (ViewDrawCallback)pcsg_view_receiver_draw); - view_set_input_callback(pcsg_receiver->view, pcsg_view_receiver_input); - view_set_enter_callback(pcsg_receiver->view, pcsg_view_receiver_enter); - view_set_exit_callback(pcsg_receiver->view, pcsg_view_receiver_exit); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - model->frequency_str = furi_string_alloc(); - model->preset_str = furi_string_alloc(); - model->history_stat_str = furi_string_alloc(); - model->bar_show = PCSGReceiverBarShowDefault; - model->history = malloc(sizeof(PCSGReceiverHistory)); - PCSGReceiverMenuItemArray_init(model->history->data); - }, - true); - pcsg_receiver->timer = - furi_timer_alloc(pcsg_view_receiver_timer_callback, FuriTimerTypeOnce, pcsg_receiver); - return pcsg_receiver; -} - -void pcsg_view_receiver_free(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - furi_string_free(model->frequency_str); - furi_string_free(model->preset_str); - furi_string_free(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, PCSGReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - PCSGReceiverMenuItemArray_clear(model->history->data); - free(model->history); - }, - false); - furi_timer_free(pcsg_receiver->timer); - view_free(pcsg_receiver->view); - free(pcsg_receiver); -} - -View* pcsg_view_receiver_get_view(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - return pcsg_receiver->view; -} - -uint16_t pcsg_view_receiver_get_idx_menu(PCSGReceiver* pcsg_receiver) { - furi_assert(pcsg_receiver); - uint32_t idx = 0; - with_view_model( - pcsg_receiver->view, PCSGReceiverModel * model, { idx = model->idx; }, false); - return idx; -} - -void pcsg_view_receiver_set_idx_menu(PCSGReceiver* pcsg_receiver, uint16_t idx) { - furi_assert(pcsg_receiver); - with_view_model( - pcsg_receiver->view, - PCSGReceiverModel * model, - { - model->idx = idx; - if(model->idx > 2) model->list_offset = idx - 2; - }, - true); - pcsg_view_receiver_update_offset(pcsg_receiver); -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h b/applications/external/pocsag_pager/views/pocsag_pager_receiver.h deleted file mode 100644 index 87900748f..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include "../helpers/pocsag_pager_types.h" -#include "../helpers/pocsag_pager_event.h" - -typedef struct PCSGReceiver PCSGReceiver; - -typedef void (*PCSGReceiverCallback)(PCSGCustomEvent event, void* context); - -void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi); - -void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock keyboard); - -void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external); - -void pcsg_view_receiver_set_callback( - PCSGReceiver* pcsg_receiver, - PCSGReceiverCallback callback, - void* context); - -PCSGReceiver* pcsg_view_receiver_alloc(); - -void pcsg_view_receiver_free(PCSGReceiver* pcsg_receiver); - -View* pcsg_view_receiver_get_view(PCSGReceiver* pcsg_receiver); - -void pcsg_view_receiver_add_data_statusbar( - PCSGReceiver* pcsg_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str); - -void pcsg_view_receiver_add_item_to_menu( - PCSGReceiver* pcsg_receiver, - const char* name, - uint8_t type); - -uint16_t pcsg_view_receiver_get_idx_menu(PCSGReceiver* pcsg_receiver); - -void pcsg_view_receiver_set_idx_menu(PCSGReceiver* pcsg_receiver, uint16_t idx); - -void pcsg_view_receiver_exit(void* context); diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c deleted file mode 100644 index 91ee69ab5..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "pocsag_pager_receiver.h" -#include "../pocsag_pager_app_i.h" -#include "pocsag_pager_icons.h" -#include -#include "../protocols/pcsg_generic.h" -#include -#include - -#define abs(x) ((x) > 0 ? (x) : -(x)) - -struct PCSGReceiverInfo { - View* view; -}; - -typedef struct { - FuriString* protocol_name; - PCSGBlockGeneric* generic; -} PCSGReceiverInfoModel; - -void pcsg_view_receiver_info_update(PCSGReceiverInfo* pcsg_receiver_info, FlipperFormat* fff) { - furi_assert(pcsg_receiver_info); - furi_assert(fff); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - flipper_format_rewind(fff); - flipper_format_read_string(fff, "Protocol", model->protocol_name); - - pcsg_block_generic_deserialize(model->generic, fff); - }, - true); -} - -void pcsg_view_receiver_info_draw(Canvas* canvas, PCSGReceiverInfoModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - if(model->generic->result_ric != NULL) { - elements_text_box( - canvas, - 0, - 0, - 128, - 64, - AlignLeft, - AlignTop, - furi_string_get_cstr(model->generic->result_ric), - false); - } - if(model->generic->result_msg != NULL) { - elements_text_box( - canvas, - 0, - 12, - 128, - 64, - AlignLeft, - AlignTop, - furi_string_get_cstr(model->generic->result_msg), - false); - } -} - -bool pcsg_view_receiver_info_input(InputEvent* event, void* context) { - furi_assert(context); - //PCSGReceiverInfo* pcsg_receiver_info = context; - - if(event->key == InputKeyBack) { - return false; - } - - return true; -} - -void pcsg_view_receiver_info_enter(void* context) { - furi_assert(context); -} - -void pcsg_view_receiver_info_exit(void* context) { - furi_assert(context); - PCSGReceiverInfo* pcsg_receiver_info = context; - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { furi_string_reset(model->protocol_name); }, - false); -} - -PCSGReceiverInfo* pcsg_view_receiver_info_alloc() { - PCSGReceiverInfo* pcsg_receiver_info = malloc(sizeof(PCSGReceiverInfo)); - - // View allocation and configuration - pcsg_receiver_info->view = view_alloc(); - - view_allocate_model( - pcsg_receiver_info->view, ViewModelTypeLocking, sizeof(PCSGReceiverInfoModel)); - view_set_context(pcsg_receiver_info->view, pcsg_receiver_info); - view_set_draw_callback( - pcsg_receiver_info->view, (ViewDrawCallback)pcsg_view_receiver_info_draw); - view_set_input_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_input); - view_set_enter_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_enter); - view_set_exit_callback(pcsg_receiver_info->view, pcsg_view_receiver_info_exit); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - model->generic = malloc(sizeof(PCSGBlockGeneric)); - model->protocol_name = furi_string_alloc(); - }, - true); - - return pcsg_receiver_info; -} - -void pcsg_view_receiver_info_free(PCSGReceiverInfo* pcsg_receiver_info) { - furi_assert(pcsg_receiver_info); - - with_view_model( - pcsg_receiver_info->view, - PCSGReceiverInfoModel * model, - { - furi_string_free(model->protocol_name); - free(model->generic); - }, - false); - - view_free(pcsg_receiver_info->view); - free(pcsg_receiver_info); -} - -View* pcsg_view_receiver_info_get_view(PCSGReceiverInfo* pcsg_receiver_info) { - furi_assert(pcsg_receiver_info); - return pcsg_receiver_info->view; -} diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h b/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h deleted file mode 100644 index dfc85ec88..000000000 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver_info.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "../helpers/pocsag_pager_types.h" -#include "../helpers/pocsag_pager_event.h" -#include - -typedef struct PCSGReceiverInfo PCSGReceiverInfo; - -void pcsg_view_receiver_info_update(PCSGReceiverInfo* pcsg_receiver_info, FlipperFormat* fff); - -PCSGReceiverInfo* pcsg_view_receiver_info_alloc(); - -void pcsg_view_receiver_info_free(PCSGReceiverInfo* pcsg_receiver_info); - -View* pcsg_view_receiver_info_get_view(PCSGReceiverInfo* pcsg_receiver_info); diff --git a/applications/external/weather_station/application.fam b/applications/external/weather_station/application.fam deleted file mode 100644 index 0221130a3..000000000 --- a/applications/external/weather_station/application.fam +++ /dev/null @@ -1,14 +0,0 @@ -App( - appid="weather_station", - name="Weather Station", - apptype=FlipperAppType.EXTERNAL, - targets=["f7"], - entry_point="weather_station_app", - requires=["gui"], - stack_size=4 * 1024, - fap_description="Receive weather data from a wide range of supported Sub-1GHz remote sensor", - fap_version="1.1", - fap_icon="weather_station_10px.png", - fap_category="Sub-GHz", - fap_icon_assets="images", -) diff --git a/applications/external/weather_station/helpers/radio_device_loader.c b/applications/external/weather_station/helpers/radio_device_loader.c deleted file mode 100644 index 0d99549eb..000000000 --- a/applications/external/weather_station/helpers/radio_device_loader.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "radio_device_loader.h" - -#include -#include - -static void radio_device_loader_power_on() { - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void radio_device_loader_power_off() { - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -bool radio_device_loader_is_connect_external(const char* name) { - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - radio_device_loader_power_on(); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - radio_device_loader_power_off(); - } - return is_connect; -} - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type) { - const SubGhzDevice* radio_device; - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - radio_device_loader_power_on(); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(radio_device); - } else if(current_radio_device == NULL) { - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } else { - radio_device_loader_end(current_radio_device); - radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - } - - return radio_device; -} - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)); -} - -void radio_device_loader_end(const SubGhzDevice* radio_device) { - furi_assert(radio_device); - radio_device_loader_power_off(); - if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { - subghz_devices_end(radio_device); - } -} \ No newline at end of file diff --git a/applications/external/weather_station/helpers/radio_device_loader.h b/applications/external/weather_station/helpers/radio_device_loader.h deleted file mode 100644 index bae4bacf2..000000000 --- a/applications/external/weather_station/helpers/radio_device_loader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -const SubGhzDevice* radio_device_loader_set( - const SubGhzDevice* current_radio_device, - SubGhzRadioDeviceType radio_device_type); - -bool radio_device_loader_is_external(const SubGhzDevice* radio_device); - -void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/weather_station/helpers/weather_station_event.h b/applications/external/weather_station/helpers/weather_station_event.h deleted file mode 100644 index b0486183d..000000000 --- a/applications/external/weather_station/helpers/weather_station_event.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -typedef enum { - //WSCustomEvent - WSCustomEventStartId = 100, - - WSCustomEventSceneSettingLock, - - WSCustomEventViewReceiverOK, - WSCustomEventViewReceiverConfig, - WSCustomEventViewReceiverBack, - WSCustomEventViewReceiverOffDisplay, - WSCustomEventViewReceiverUnlock, -} WSCustomEvent; diff --git a/applications/external/weather_station/helpers/weather_station_types.h b/applications/external/weather_station/helpers/weather_station_types.h deleted file mode 100644 index e6c696bf8..000000000 --- a/applications/external/weather_station/helpers/weather_station_types.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#define WS_VERSION_APP "1.1" -#define WS_DEVELOPED "SkorP" -#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" - -#define WS_KEY_FILE_VERSION 1 -#define WS_KEY_FILE_TYPE "Flipper Weather Station Key File" - -/** WSRxKeyState state */ -typedef enum { - WSRxKeyStateIDLE, - WSRxKeyStateBack, - WSRxKeyStateStart, - WSRxKeyStateAddKey, -} WSRxKeyState; - -/** WSHopperState state */ -typedef enum { - WSHopperStateOFF, - WSHopperStateRunnig, - WSHopperStatePause, - WSHopperStateRSSITimeOut, -} WSHopperState; - -/** WSLock */ -typedef enum { - WSLockOff, - WSLockOn, -} WSLock; - -typedef enum { - WeatherStationViewVariableItemList, - WeatherStationViewSubmenu, - WeatherStationViewReceiver, - WeatherStationViewReceiverInfo, - WeatherStationViewWidget, -} WeatherStationView; - -/** WeatherStationTxRx state */ -typedef enum { - WSTxRxStateIDLE, - WSTxRxStateRx, - WSTxRxStateTx, - WSTxRxStateSleep, -} WSTxRxState; diff --git a/applications/external/weather_station/images/Humid_10x15.png b/applications/external/weather_station/images/Humid_10x15.png deleted file mode 100644 index 34b074e5f..000000000 Binary files a/applications/external/weather_station/images/Humid_10x15.png and /dev/null differ diff --git a/applications/external/weather_station/images/Humid_8x13.png b/applications/external/weather_station/images/Humid_8x13.png deleted file mode 100644 index 6d8c71b00..000000000 Binary files a/applications/external/weather_station/images/Humid_8x13.png and /dev/null differ diff --git a/applications/external/weather_station/images/Therm_7x16.png b/applications/external/weather_station/images/Therm_7x16.png deleted file mode 100644 index 7c55500b7..000000000 Binary files a/applications/external/weather_station/images/Therm_7x16.png and /dev/null differ diff --git a/applications/external/weather_station/images/Timer_11x11.png b/applications/external/weather_station/images/Timer_11x11.png deleted file mode 100644 index 21ad47f4b..000000000 Binary files a/applications/external/weather_station/images/Timer_11x11.png and /dev/null differ diff --git a/applications/external/weather_station/images/station_icon.png b/applications/external/weather_station/images/station_icon.png deleted file mode 100644 index b839eeb7a..000000000 Binary files a/applications/external/weather_station/images/station_icon.png and /dev/null differ diff --git a/applications/external/weather_station/protocols/protocol_items.c b/applications/external/weather_station/protocols/protocol_items.c deleted file mode 100644 index e0ec86068..000000000 --- a/applications/external/weather_station/protocols/protocol_items.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "protocol_items.h" - -const SubGhzProtocol* weather_station_protocol_registry_items[] = { - &ws_protocol_infactory, - &ws_protocol_thermopro_tx4, - &ws_protocol_nexus_th, - &ws_protocol_gt_wt_02, - &ws_protocol_gt_wt_03, - &ws_protocol_acurite_606tx, - &ws_protocol_acurite_609txc, - &ws_protocol_lacrosse_tx, - &ws_protocol_lacrosse_tx141thbv2, - &ws_protocol_oregon2, - &ws_protocol_oregon3, - &ws_protocol_acurite_592txr, - &ws_protocol_ambient_weather, - &ws_protocol_auriol_th, - &ws_protocol_oregon_v1, - &ws_protocol_tx_8300, - &ws_protocol_wendox_w6726, - &ws_protocol_auriol_ahfl, -}; - -const SubGhzProtocolRegistry weather_station_protocol_registry = { - .items = weather_station_protocol_registry_items, - .size = COUNT_OF(weather_station_protocol_registry_items)}; diff --git a/applications/external/weather_station/protocols/protocol_items.h b/applications/external/weather_station/protocols/protocol_items.h deleted file mode 100644 index 7d9bda243..000000000 --- a/applications/external/weather_station/protocols/protocol_items.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "../weather_station_app_i.h" - -#include "infactory.h" -#include "thermopro_tx4.h" -#include "nexus_th.h" -#include "gt_wt_02.h" -#include "gt_wt_03.h" -#include "acurite_606tx.h" -#include "acurite_609txc.h" -#include "lacrosse_tx.h" -#include "lacrosse_tx141thbv2.h" -#include "oregon2.h" -#include "oregon3.h" -#include "acurite_592txr.h" -#include "ambient_weather.h" -#include "auriol_hg0601a.h" -#include "oregon_v1.h" -#include "tx_8300.h" -#include "wendox_w6726.h" -#include "auriol_ahfl.h" - -extern const SubGhzProtocolRegistry weather_station_protocol_registry; diff --git a/applications/external/weather_station/scenes/weather_station_receiver.c b/applications/external/weather_station/scenes/weather_station_receiver.c deleted file mode 100644 index 76d808e7e..000000000 --- a/applications/external/weather_station/scenes/weather_station_receiver.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../views/weather_station_receiver.h" - -static const NotificationSequence subghs_sequence_rx = { - &message_green_255, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_50, - NULL, -}; - -static const NotificationSequence subghs_sequence_rx_locked = { - &message_green_255, - - &message_display_backlight_on, - - &message_vibro_on, - &message_note_c6, - &message_delay_50, - &message_sound_off, - &message_vibro_off, - - &message_delay_500, - - &message_display_backlight_off, - NULL, -}; - -static void weather_station_scene_receiver_update_statusbar(void* context) { - WeatherStationApp* app = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!ws_history_get_text_space_left(app->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - - ws_get_frequency_modulation(app, frequency_str, modulation_str); - - ws_view_receiver_add_data_statusbar( - app->ws_receiver, - furi_string_get_cstr(frequency_str), - furi_string_get_cstr(modulation_str), - furi_string_get_cstr(history_stat_str), - radio_device_loader_is_external(app->txrx->radio_device)); - - furi_string_free(frequency_str); - furi_string_free(modulation_str); - } else { - ws_view_receiver_add_data_statusbar( - app->ws_receiver, - furi_string_get_cstr(history_stat_str), - "", - "", - radio_device_loader_is_external(app->txrx->radio_device)); - } - furi_string_free(history_stat_str); -} - -void weather_station_scene_receiver_callback(WSCustomEvent event, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void weather_station_scene_receiver_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - WeatherStationApp* app = context; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(ws_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - WSHistoryStateAddKeyNewDada) { - furi_string_reset(str_buff); - - ws_history_get_text_item_menu( - app->txrx->history, str_buff, ws_history_get_item(app->txrx->history) - 1); - ws_view_receiver_add_item_to_menu( - app->ws_receiver, - furi_string_get_cstr(str_buff), - ws_history_get_type_protocol( - app->txrx->history, ws_history_get_item(app->txrx->history) - 1)); - - weather_station_scene_receiver_update_statusbar(app); - notification_message(app->notifications, &sequence_blink_green_10); - if(app->lock != WSLockOn) { - notification_message(app->notifications, &subghs_sequence_rx); - } else { - notification_message(app->notifications, &subghs_sequence_rx_locked); - } - } - subghz_receiver_reset(receiver); - furi_string_free(str_buff); - app->txrx->rx_key_state = WSRxKeyStateAddKey; -} - -void weather_station_scene_receiver_on_enter(void* context) { - WeatherStationApp* app = context; - - FuriString* str_buff; - str_buff = furi_string_alloc(); - - if(app->txrx->rx_key_state == WSRxKeyStateIDLE) { - ws_preset_init(app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - ws_history_reset(app->txrx->history); - app->txrx->rx_key_state = WSRxKeyStateStart; - } - - ws_view_receiver_set_lock(app->ws_receiver, app->lock); - - //Load history to receiver - ws_view_receiver_exit(app->ws_receiver); - for(uint8_t i = 0; i < ws_history_get_item(app->txrx->history); i++) { - furi_string_reset(str_buff); - ws_history_get_text_item_menu(app->txrx->history, str_buff, i); - ws_view_receiver_add_item_to_menu( - app->ws_receiver, - furi_string_get_cstr(str_buff), - ws_history_get_type_protocol(app->txrx->history, i)); - app->txrx->rx_key_state = WSRxKeyStateAddKey; - } - furi_string_free(str_buff); - weather_station_scene_receiver_update_statusbar(app); - - ws_view_receiver_set_callback(app->ws_receiver, weather_station_scene_receiver_callback, app); - subghz_receiver_set_rx_callback( - app->txrx->receiver, weather_station_scene_receiver_add_to_history_callback, app); - - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - }; - if((app->txrx->txrx_state == WSTxRxStateIDLE) || (app->txrx->txrx_state == WSTxRxStateSleep)) { - ws_begin( - app, - subghz_setting_get_preset_data_by_name( - app->setting, furi_string_get_cstr(app->txrx->preset->name))); - - ws_rx(app, app->txrx->preset->frequency); - } - - ws_view_receiver_set_idx_menu(app->ws_receiver, app->txrx->idx_menu_chosen); - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewReceiver); -} - -bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case WSCustomEventViewReceiverBack: - // Stop CC1101 Rx - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - ws_sleep(app); - }; - app->txrx->hopper_state = WSHopperStateOFF; - app->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); - - app->txrx->rx_key_state = WSRxKeyStateIDLE; - ws_preset_init( - app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, WeatherStationSceneStart); - consumed = true; - break; - case WSCustomEventViewReceiverOK: - app->txrx->idx_menu_chosen = ws_view_receiver_get_idx_menu(app->ws_receiver); - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiverInfo); - consumed = true; - break; - case WSCustomEventViewReceiverConfig: - app->txrx->idx_menu_chosen = ws_view_receiver_get_idx_menu(app->ws_receiver); - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiverConfig); - consumed = true; - break; - case WSCustomEventViewReceiverOffDisplay: - notification_message(app->notifications, &sequence_display_backlight_off); - consumed = true; - break; - case WSCustomEventViewReceiverUnlock: - app->lock = WSLockOff; - consumed = true; - break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - if(app->txrx->hopper_state != WSHopperStateOFF) { - ws_hopper_update(app); - weather_station_scene_receiver_update_statusbar(app); - } - // Get current RSSI - float rssi = subghz_devices_get_rssi(app->txrx->radio_device); - ws_view_receiver_set_rssi(app->ws_receiver, rssi); - - if(app->txrx->txrx_state == WSTxRxStateRx) { - notification_message(app->notifications, &sequence_blink_cyan_10); - } - } - return consumed; -} - -void weather_station_scene_receiver_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene.c b/applications/external/weather_station/scenes/weather_station_scene.c deleted file mode 100644 index f9306e5f4..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../weather_station_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const weather_station_scene_on_enter_handlers[])(void*) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const weather_station_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const weather_station_scene_on_exit_handlers[])(void* context) = { -#include "weather_station_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers weather_station_scene_handlers = { - .on_enter_handlers = weather_station_scene_on_enter_handlers, - .on_event_handlers = weather_station_scene_on_event_handlers, - .on_exit_handlers = weather_station_scene_on_exit_handlers, - .scene_num = WeatherStationSceneNum, -}; diff --git a/applications/external/weather_station/scenes/weather_station_scene.h b/applications/external/weather_station/scenes/weather_station_scene.h deleted file mode 100644 index 8cee4ee60..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) WeatherStationScene##id, -typedef enum { -#include "weather_station_scene_config.h" - WeatherStationSceneNum, -} WeatherStationScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers weather_station_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "weather_station_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "weather_station_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "weather_station_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/weather_station/scenes/weather_station_scene_about.c b/applications/external/weather_station/scenes/weather_station_scene_about.c deleted file mode 100644 index d916dc76f..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_about.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../helpers/weather_station_types.h" - -void weather_station_scene_about_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - WeatherStationApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, result); - } -} - -void weather_station_scene_about_on_enter(void* context) { - WeatherStationApp* app = context; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - furi_string_printf(temp_str, "\e#%s\n", "Information"); - - furi_string_cat_printf(temp_str, "Version: %s\n", WS_VERSION_APP); - furi_string_cat_printf(temp_str, "Developed by: %s\n", WS_DEVELOPED); - furi_string_cat_printf(temp_str, "Github: %s\n\n", WS_GITHUB); - - furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf( - temp_str, "Reading messages from\nweather stations that work\nwith SubGhz sensors\n\n"); - - furi_string_cat_printf(temp_str, "Supported protocols:\n"); - size_t i = 0; - const char* protocol_name = - subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - do { - furi_string_cat_printf(temp_str, "%s\n", protocol_name); - protocol_name = subghz_environment_get_protocol_name_registry(app->txrx->environment, i++); - } while(protocol_name != NULL); - - widget_add_text_box_element( - app->widget, - 0, - 0, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! \e!\n", - false); - widget_add_text_box_element( - app->widget, - 0, - 2, - 128, - 14, - AlignCenter, - AlignBottom, - "\e#\e! Weather station \e!\n", - false); - widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); - furi_string_free(temp_str); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewWidget); -} - -bool weather_station_scene_about_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - - return consumed; -} - -void weather_station_scene_about_on_exit(void* context) { - WeatherStationApp* app = context; - - // Clear views - widget_reset(app->widget); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_config.h b/applications/external/weather_station/scenes/weather_station_scene_config.h deleted file mode 100644 index 0ba8ec013..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_config.h +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SCENE(weather_station, start, Start) -ADD_SCENE(weather_station, about, About) -ADD_SCENE(weather_station, receiver, Receiver) -ADD_SCENE(weather_station, receiver_config, ReceiverConfig) -ADD_SCENE(weather_station, receiver_info, ReceiverInfo) diff --git a/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c b/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c deleted file mode 100644 index fcd8f6d3e..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_receiver_config.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "../weather_station_app_i.h" - -enum WSSettingIndex { - WSSettingIndexFrequency, - WSSettingIndexHopping, - WSSettingIndexModulation, - WSSettingIndexLock, -}; - -#define HOPPING_COUNT 2 -const char* const hopping_text[HOPPING_COUNT] = { - "OFF", - "ON", -}; -const uint32_t hopping_value[HOPPING_COUNT] = { - WSHopperStateOFF, - WSHopperStateRunnig, -}; - -uint8_t weather_station_scene_receiver_config_next_frequency(const uint32_t value, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_frequency_count(app->setting); i++) { - if(value == subghz_setting_get_frequency(app->setting, i)) { - index = i; - break; - } else { - index = subghz_setting_get_frequency_default_index(app->setting); - } - } - return index; -} - -uint8_t weather_station_scene_receiver_config_next_preset(const char* preset_name, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_preset_count(app->setting); i++) { - if(!strcmp(subghz_setting_get_preset_name(app->setting, i), preset_name)) { - index = i; - break; - } else { - // index = subghz_setting_get_frequency_default_index(app ->setting); - } - } - return index; -} - -uint8_t weather_station_scene_receiver_config_hopper_value_index( - const uint32_t value, - const uint32_t values[], - uint8_t values_count, - void* context) { - furi_assert(context); - UNUSED(values_count); - WeatherStationApp* app = context; - - if(value == values[0]) { - return 0; - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - " -----"); - return 1; - } -} - -static void weather_station_scene_receiver_config_set_frequency(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - if(app->txrx->hopper_state == WSHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, index) / 1000000, - (subghz_setting_get_frequency(app->setting, index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - app->txrx->preset->frequency = subghz_setting_get_frequency(app->setting, index); - } else { - variable_item_set_current_value_index( - item, subghz_setting_get_frequency_default_index(app->setting)); - } -} - -static void weather_station_scene_receiver_config_set_preset(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, index)); - ws_preset_init( - app, - subghz_setting_get_preset_name(app->setting, index), - app->txrx->preset->frequency, - subghz_setting_get_preset_data(app->setting, index), - subghz_setting_get_preset_data_size(app->setting, index)); -} - -static void weather_station_scene_receiver_config_set_hopping_running(VariableItem* item) { - WeatherStationApp* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - variable_item_set_current_value_text(item, hopping_text[index]); - if(hopping_value[index] == WSHopperStateOFF) { - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_default_frequency(app->setting) / 1000000, - (subghz_setting_get_default_frequency(app->setting) % 1000000) / 10000); - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - text_buf); - app->txrx->preset->frequency = subghz_setting_get_default_frequency(app->setting); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - " -----"); - variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig), - subghz_setting_get_frequency_default_index(app->setting)); - } - - app->txrx->hopper_state = hopping_value[index]; -} - -static void - weather_station_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { - furi_assert(context); - WeatherStationApp* app = context; - if(index == WSSettingIndexLock) { - view_dispatcher_send_custom_event(app->view_dispatcher, WSCustomEventSceneSettingLock); - } -} - -void weather_station_scene_receiver_config_on_enter(void* context) { - WeatherStationApp* app = context; - VariableItem* item; - uint8_t value_index; - - item = variable_item_list_add( - app->variable_item_list, - "Frequency:", - subghz_setting_get_frequency_count(app->setting), - weather_station_scene_receiver_config_set_frequency, - app); - value_index = - weather_station_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app); - scene_manager_set_scene_state( - app->scene_manager, WeatherStationSceneReceiverConfig, (uint32_t)item); - variable_item_set_current_value_index(item, value_index); - char text_buf[10] = {0}; - snprintf( - text_buf, - sizeof(text_buf), - "%lu.%02lu", - subghz_setting_get_frequency(app->setting, value_index) / 1000000, - (subghz_setting_get_frequency(app->setting, value_index) % 1000000) / 10000); - variable_item_set_current_value_text(item, text_buf); - - item = variable_item_list_add( - app->variable_item_list, - "Hopping:", - HOPPING_COUNT, - weather_station_scene_receiver_config_set_hopping_running, - app); - value_index = weather_station_scene_receiver_config_hopper_value_index( - app->txrx->hopper_state, hopping_value, HOPPING_COUNT, app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, hopping_text[value_index]); - - item = variable_item_list_add( - app->variable_item_list, - "Modulation:", - subghz_setting_get_preset_count(app->setting), - weather_station_scene_receiver_config_set_preset, - app); - value_index = weather_station_scene_receiver_config_next_preset( - furi_string_get_cstr(app->txrx->preset->name), app); - variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(app->setting, value_index)); - - variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL); - variable_item_list_set_enter_callback( - app->variable_item_list, - weather_station_scene_receiver_config_var_list_enter_callback, - app); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewVariableItemList); -} - -bool weather_station_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == WSCustomEventSceneSettingLock) { - app->lock = WSLockOn; - scene_manager_previous_scene(app->scene_manager); - consumed = true; - } - } - return consumed; -} - -void weather_station_scene_receiver_config_on_exit(void* context) { - WeatherStationApp* app = context; - variable_item_list_set_selected_item(app->variable_item_list, 0); - variable_item_list_reset(app->variable_item_list); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c b/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c deleted file mode 100644 index b26661be3..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_receiver_info.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../weather_station_app_i.h" -#include "../views/weather_station_receiver.h" - -void weather_station_scene_receiver_info_callback(WSCustomEvent event, void* context) { - furi_assert(context); - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -static void weather_station_scene_receiver_info_add_to_history_callback( - SubGhzReceiver* receiver, - SubGhzProtocolDecoderBase* decoder_base, - void* context) { - furi_assert(context); - WeatherStationApp* app = context; - - if(ws_history_add_to_history(app->txrx->history, decoder_base, app->txrx->preset) == - WSHistoryStateAddKeyUpdateData) { - ws_view_receiver_info_update( - app->ws_receiver_info, - ws_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - subghz_receiver_reset(receiver); - - notification_message(app->notifications, &sequence_blink_green_10); - app->txrx->rx_key_state = WSRxKeyStateAddKey; - } -} - -void weather_station_scene_receiver_info_on_enter(void* context) { - WeatherStationApp* app = context; - - subghz_receiver_set_rx_callback( - app->txrx->receiver, weather_station_scene_receiver_info_add_to_history_callback, app); - ws_view_receiver_info_update( - app->ws_receiver_info, - ws_history_get_raw_data(app->txrx->history, app->txrx->idx_menu_chosen)); - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewReceiverInfo); -} - -bool weather_station_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - UNUSED(app); - UNUSED(event); - return consumed; -} - -void weather_station_scene_receiver_info_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/weather_station/scenes/weather_station_scene_start.c b/applications/external/weather_station/scenes/weather_station_scene_start.c deleted file mode 100644 index 56dd6fa86..000000000 --- a/applications/external/weather_station/scenes/weather_station_scene_start.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../weather_station_app_i.h" - -typedef enum { - SubmenuIndexWeatherStationReceiver, - SubmenuIndexWeatherStationAbout, -} SubmenuIndex; - -void weather_station_scene_start_submenu_callback(void* context, uint32_t index) { - WeatherStationApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void weather_station_scene_start_on_enter(void* context) { - UNUSED(context); - WeatherStationApp* app = context; - Submenu* submenu = app->submenu; - - submenu_add_item( - submenu, - "Read Weather Station", - SubmenuIndexWeatherStationReceiver, - weather_station_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "About", - SubmenuIndexWeatherStationAbout, - weather_station_scene_start_submenu_callback, - app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, WeatherStationSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, WeatherStationViewSubmenu); -} - -bool weather_station_scene_start_on_event(void* context, SceneManagerEvent event) { - WeatherStationApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexWeatherStationAbout) { - scene_manager_next_scene(app->scene_manager, WeatherStationSceneAbout); - consumed = true; - } else if(event.event == SubmenuIndexWeatherStationReceiver) { - scene_manager_next_scene(app->scene_manager, WeatherStationSceneReceiver); - consumed = true; - } - scene_manager_set_scene_state(app->scene_manager, WeatherStationSceneStart, event.event); - } - - return consumed; -} - -void weather_station_scene_start_on_exit(void* context) { - WeatherStationApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/weather_station/views/weather_station_receiver.c b/applications/external/weather_station/views/weather_station_receiver.c deleted file mode 100644 index 488ef022f..000000000 --- a/applications/external/weather_station/views/weather_station_receiver.c +++ /dev/null @@ -1,473 +0,0 @@ -#include "weather_station_receiver.h" -#include "../weather_station_app_i.h" -#include "weather_station_icons.h" -#include -#include - -#include -#include -#include - -#define FRAME_HEIGHT 12 -#define MAX_LEN_PX 112 -#define MENU_ITEMS 4u -#define UNLOCK_CNT 3 - -#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f -typedef struct { - FuriString* item_str; - uint8_t type; -} WSReceiverMenuItem; - -ARRAY_DEF(WSReceiverMenuItemArray, WSReceiverMenuItem, M_POD_OPLIST) - -#define M_OPL_WSReceiverMenuItemArray_t() ARRAY_OPLIST(WSReceiverMenuItemArray, M_POD_OPLIST) - -struct WSReceiverHistory { - WSReceiverMenuItemArray_t data; -}; - -typedef struct WSReceiverHistory WSReceiverHistory; - -static const Icon* ReceiverItemIcons[] = { - [SubGhzProtocolTypeUnknown] = &I_Quest_7x8, - [SubGhzProtocolTypeStatic] = &I_Unlock_7x8, - [SubGhzProtocolTypeDynamic] = &I_Lock_7x8, - [SubGhzProtocolWeatherStation] = &I_station_icon, -}; - -typedef enum { - WSReceiverBarShowDefault, - WSReceiverBarShowLock, - WSReceiverBarShowToUnlockPress, - WSReceiverBarShowUnlock, -} WSReceiverBarShow; - -struct WSReceiver { - WSLock lock; - uint8_t lock_count; - FuriTimer* timer; - View* view; - WSReceiverCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* history_stat_str; - WSReceiverHistory* history; - uint16_t idx; - uint16_t list_offset; - uint16_t history_item; - WSReceiverBarShow bar_show; - uint8_t u_rssi; - bool external_redio; -} WSReceiverModel; - -void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi) { - furi_assert(instance); - with_view_model( - instance->view, - WSReceiverModel * model, - { - if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { - model->u_rssi = 0; - } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); - } - }, - true); -} - -void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock lock) { - furi_assert(ws_receiver); - ws_receiver->lock_count = 0; - if(lock == WSLockOn) { - ws_receiver->lock = lock; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowLock; }, - true); - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(1000)); - } else { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowDefault; }, - true); - } -} - -void ws_view_receiver_set_callback( - WSReceiver* ws_receiver, - WSReceiverCallback callback, - void* context) { - furi_assert(ws_receiver); - furi_assert(callback); - ws_receiver->callback = callback; - ws_receiver->context = context; -} - -static void ws_view_receiver_update_offset(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - size_t history_item = model->history_item; - uint16_t bounds = history_item > 3 ? 2 : history_item; - - if(history_item > 3 && model->idx >= (int16_t)(history_item - 1)) { - model->list_offset = model->idx - 3; - } else if(model->list_offset < model->idx - bounds) { - model->list_offset = - CLAMP(model->list_offset + 1, (int16_t)(history_item - bounds), 0); - } else if(model->list_offset > model->idx - bounds) { - model->list_offset = CLAMP(model->idx - 1, (int16_t)(history_item - bounds), 0); - } - }, - true); -} - -void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - WSReceiverMenuItem* item_menu = WSReceiverMenuItemArray_push_raw(model->history->data); - item_menu->item_str = furi_string_alloc_set(name); - item_menu->type = type; - if((model->idx == model->history_item - 1)) { - model->history_item++; - model->idx++; - } else { - model->history_item++; - } - }, - true); - ws_view_receiver_update_offset(ws_receiver); -} - -void ws_view_receiver_add_data_statusbar( - WSReceiver* ws_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str, - bool external) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_set_str(model->frequency_str, frequency_str); - furi_string_set_str(model->preset_str, preset_str); - furi_string_set_str(model->history_stat_str, history_stat_str); - model->external_redio = external; - }, - true); -} - -static void ws_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); - - canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); -} - -static void ws_view_rssi_draw(Canvas* canvas, WSReceiverModel* model) { - for(uint8_t i = 1; i < model->u_rssi; i++) { - if(i % 5) { - canvas_draw_dot(canvas, 46 + i, 50); - canvas_draw_dot(canvas, 47 + i, 51); - canvas_draw_dot(canvas, 46 + i, 52); - } - } -} - -void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - elements_button_left(canvas, "Config"); - - bool scrollbar = model->history_item > 4; - FuriString* str_buff; - str_buff = furi_string_alloc(); - - // bool ext_module = furi_hal_subghz_get_radio_type(); - - WSReceiverMenuItem* item_menu; - - for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0); - item_menu = WSReceiverMenuItemArray_get(model->history->data, idx); - furi_string_set(str_buff, item_menu->item_str); - elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); - if(model->idx == idx) { - ws_view_receiver_draw_frame(canvas, i, scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); - canvas_draw_str(canvas, 14, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff)); - furi_string_reset(str_buff); - } - if(scrollbar) { - elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); - } - furi_string_free(str_buff); - - canvas_set_color(canvas, ColorBlack); - - if(model->history_item == 0) { - canvas_draw_icon( - canvas, 0, 0, model->external_redio ? &I_Fishing_123x52 : &I_Scanning_123x52); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 44, 10, model->external_redio ? "Ext" : "Int"); - } - - // Draw RSSI - ws_view_rssi_draw(canvas, model); - - switch(model->bar_show) { - case WSReceiverBarShowLock: - canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); - canvas_draw_str(canvas, 74, 62, "Locked"); - break; - case WSReceiverBarShowToUnlockPress: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - canvas_set_font(canvas, FontSecondary); - elements_bold_rounded_frame(canvas, 14, 8, 99, 48); - elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); - canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); - canvas_draw_dot(canvas, 17, 61); - break; - case WSReceiverBarShowUnlock: - canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8); - canvas_draw_str(canvas, 74, 62, "Unlocked"); - break; - default: - canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); - break; - } -} - -static void ws_view_receiver_timer_callback(void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowDefault; }, - true); - if(ws_receiver->lock_count < UNLOCK_CNT) { - ws_receiver->callback(WSCustomEventViewReceiverOffDisplay, ws_receiver->context); - } else { - ws_receiver->lock = WSLockOff; - ws_receiver->callback(WSCustomEventViewReceiverUnlock, ws_receiver->context); - } - ws_receiver->lock_count = 0; -} - -bool ws_view_receiver_input(InputEvent* event, void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - - if(ws_receiver->lock == WSLockOn) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowToUnlockPress; }, - true); - if(ws_receiver->lock_count == 0) { - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(1000)); - } - if(event->key == InputKeyBack && event->type == InputTypeShort) { - ws_receiver->lock_count++; - } - if(ws_receiver->lock_count >= UNLOCK_CNT) { - ws_receiver->callback(WSCustomEventViewReceiverUnlock, ws_receiver->context); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { model->bar_show = WSReceiverBarShowUnlock; }, - true); - ws_receiver->lock = WSLockOff; - furi_timer_start(ws_receiver->timer, pdMS_TO_TICKS(650)); - } - - return true; - } - - if(event->key == InputKeyBack && event->type == InputTypeShort) { - ws_receiver->callback(WSCustomEventViewReceiverBack, ws_receiver->context); - } else if( - event->key == InputKeyUp && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->idx != 0) model->idx--; - }, - true); - } else if( - event->key == InputKeyDown && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->history_item && model->idx != model->history_item - 1) model->idx++; - }, - true); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - ws_receiver->callback(WSCustomEventViewReceiverConfig, ws_receiver->context); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - if(model->history_item != 0) { - ws_receiver->callback(WSCustomEventViewReceiverOK, ws_receiver->context); - } - }, - false); - } - - ws_view_receiver_update_offset(ws_receiver); - - return true; -} - -void ws_view_receiver_enter(void* context) { - furi_assert(context); -} - -void ws_view_receiver_exit(void* context) { - furi_assert(context); - WSReceiver* ws_receiver = context; - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_reset(model->frequency_str); - furi_string_reset(model->preset_str); - furi_string_reset(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, WSReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - WSReceiverMenuItemArray_reset(model->history->data); - model->idx = 0; - model->list_offset = 0; - model->history_item = 0; - }, - false); - furi_timer_stop(ws_receiver->timer); -} - -WSReceiver* ws_view_receiver_alloc() { - WSReceiver* ws_receiver = malloc(sizeof(WSReceiver)); - - // View allocation and configuration - ws_receiver->view = view_alloc(); - - ws_receiver->lock = WSLockOff; - ws_receiver->lock_count = 0; - view_allocate_model(ws_receiver->view, ViewModelTypeLocking, sizeof(WSReceiverModel)); - view_set_context(ws_receiver->view, ws_receiver); - view_set_draw_callback(ws_receiver->view, (ViewDrawCallback)ws_view_receiver_draw); - view_set_input_callback(ws_receiver->view, ws_view_receiver_input); - view_set_enter_callback(ws_receiver->view, ws_view_receiver_enter); - view_set_exit_callback(ws_receiver->view, ws_view_receiver_exit); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - model->frequency_str = furi_string_alloc(); - model->preset_str = furi_string_alloc(); - model->history_stat_str = furi_string_alloc(); - model->bar_show = WSReceiverBarShowDefault; - model->history = malloc(sizeof(WSReceiverHistory)); - model->external_redio = false; - WSReceiverMenuItemArray_init(model->history->data); - }, - true); - ws_receiver->timer = - furi_timer_alloc(ws_view_receiver_timer_callback, FuriTimerTypeOnce, ws_receiver); - return ws_receiver; -} - -void ws_view_receiver_free(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - furi_string_free(model->frequency_str); - furi_string_free(model->preset_str); - furi_string_free(model->history_stat_str); - for - M_EACH(item_menu, model->history->data, WSReceiverMenuItemArray_t) { - furi_string_free(item_menu->item_str); - item_menu->type = 0; - } - WSReceiverMenuItemArray_clear(model->history->data); - free(model->history); - }, - false); - furi_timer_free(ws_receiver->timer); - view_free(ws_receiver->view); - free(ws_receiver); -} - -View* ws_view_receiver_get_view(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - return ws_receiver->view; -} - -uint16_t ws_view_receiver_get_idx_menu(WSReceiver* ws_receiver) { - furi_assert(ws_receiver); - uint32_t idx = 0; - with_view_model( - ws_receiver->view, WSReceiverModel * model, { idx = model->idx; }, false); - return idx; -} - -void ws_view_receiver_set_idx_menu(WSReceiver* ws_receiver, uint16_t idx) { - furi_assert(ws_receiver); - with_view_model( - ws_receiver->view, - WSReceiverModel * model, - { - model->idx = idx; - if(model->idx > 2) model->list_offset = idx - 2; - }, - true); - ws_view_receiver_update_offset(ws_receiver); -} diff --git a/applications/external/weather_station/views/weather_station_receiver.h b/applications/external/weather_station/views/weather_station_receiver.h deleted file mode 100644 index ade61e2dc..000000000 --- a/applications/external/weather_station/views/weather_station_receiver.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include "../helpers/weather_station_types.h" -#include "../helpers/weather_station_event.h" - -typedef struct WSReceiver WSReceiver; - -typedef void (*WSReceiverCallback)(WSCustomEvent event, void* context); - -void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi); - -void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock keyboard); - -void ws_view_receiver_set_callback( - WSReceiver* ws_receiver, - WSReceiverCallback callback, - void* context); - -WSReceiver* ws_view_receiver_alloc(); - -void ws_view_receiver_free(WSReceiver* ws_receiver); - -View* ws_view_receiver_get_view(WSReceiver* ws_receiver); - -void ws_view_receiver_add_data_statusbar( - WSReceiver* ws_receiver, - const char* frequency_str, - const char* preset_str, - const char* history_stat_str, - bool external); - -void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type); - -uint16_t ws_view_receiver_get_idx_menu(WSReceiver* ws_receiver); - -void ws_view_receiver_set_idx_menu(WSReceiver* ws_receiver, uint16_t idx); - -void ws_view_receiver_exit(void* context); diff --git a/applications/external/weather_station/views/weather_station_receiver_info.c b/applications/external/weather_station/views/weather_station_receiver_info.c deleted file mode 100644 index c58993a98..000000000 --- a/applications/external/weather_station/views/weather_station_receiver_info.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "weather_station_receiver.h" -#include "../weather_station_app_i.h" -#include "weather_station_icons.h" -#include -#include "../protocols/ws_generic.h" -#include -#include -#include - -struct WSReceiverInfo { - View* view; - FuriTimer* timer; -}; - -typedef struct { - uint32_t curr_ts; - FuriString* protocol_name; - WSBlockGeneric* generic; -} WSReceiverInfoModel; - -void ws_view_receiver_info_update(WSReceiverInfo* ws_receiver_info, FlipperFormat* fff) { - furi_assert(ws_receiver_info); - furi_assert(fff); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - flipper_format_rewind(fff); - flipper_format_read_string(fff, "Protocol", model->protocol_name); - - ws_block_generic_deserialize(model->generic, fff); - - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - }, - true); -} - -void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) { - char buffer[64]; - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - - snprintf( - buffer, - sizeof(buffer), - "%s %db", - furi_string_get_cstr(model->protocol_name), - model->generic->data_count_bit); - canvas_draw_str(canvas, 0, 8, buffer); - - if(model->generic->channel != WS_NO_CHANNEL) { - snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel); - canvas_draw_str(canvas, 106, 8, buffer); - } - - if(model->generic->id != WS_NO_ID) { - snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id); - canvas_draw_str(canvas, 0, 20, buffer); - } - - if(model->generic->btn != WS_NO_BTN) { - snprintf(buffer, sizeof(buffer), "Btn: %01d", model->generic->btn); - canvas_draw_str(canvas, 57, 20, buffer); - } - - if(model->generic->battery_low != WS_NO_BATT) { - snprintf( - buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low")); - canvas_draw_str_aligned(canvas, 126, 17, AlignRight, AlignCenter, buffer); - } - - snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data); - canvas_draw_str(canvas, 0, 32, buffer); - - elements_bold_rounded_frame(canvas, 0, 38, 127, 25); - canvas_set_font(canvas, FontPrimary); - - if(!float_is_equal(model->generic->temp, WS_NO_TEMPERATURE)) { - canvas_draw_icon(canvas, 6, 43, &I_Therm_7x16); - - uint8_t temp_x1 = 0; - uint8_t temp_x2 = 0; - if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) { - snprintf(buffer, sizeof(buffer), "%3.1f C", (double)model->generic->temp); - if(model->generic->temp < -9.0f) { - temp_x1 = 49; - temp_x2 = 40; - } else { - temp_x1 = 47; - temp_x2 = 38; - } - } else { - snprintf( - buffer, - sizeof(buffer), - "%3.1f F", - (double)locale_celsius_to_fahrenheit(model->generic->temp)); - if((model->generic->temp < -27.77f) || (model->generic->temp > 37.77f)) { - temp_x1 = 50; - temp_x2 = 42; - } else { - temp_x1 = 48; - temp_x2 = 40; - } - } - - canvas_draw_str_aligned(canvas, temp_x1, 47, AlignRight, AlignTop, buffer); - canvas_draw_circle(canvas, temp_x2, 46, 1); - } - - if(model->generic->humidity != WS_NO_HUMIDITY) { - canvas_draw_icon(canvas, 53, 44, &I_Humid_8x13); - snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity); - canvas_draw_str(canvas, 64, 55, buffer); - } - - if((int)model->generic->timestamp > 0 && model->curr_ts) { - int ts_diff = (int)model->curr_ts - (int)model->generic->timestamp; - - canvas_draw_icon(canvas, 91, 46, &I_Timer_11x11); - - if(ts_diff > 60) { - int tmp_sec = ts_diff; - int cnt_min = 1; - for(int i = 1; tmp_sec > 60; i++) { - tmp_sec = tmp_sec - 60; - cnt_min = i; - } - - if(model->curr_ts % 2 == 0) { - canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old"); - } else { - if(cnt_min >= 59) { - canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old"); - } else { - snprintf(buffer, sizeof(buffer), "%dm", cnt_min); - canvas_draw_str_aligned(canvas, 114, 51, AlignCenter, AlignCenter, buffer); - } - } - - } else { - snprintf(buffer, sizeof(buffer), "%d", ts_diff); - canvas_draw_str_aligned(canvas, 112, 51, AlignCenter, AlignCenter, buffer); - } - } -} - -bool ws_view_receiver_info_input(InputEvent* event, void* context) { - furi_assert(context); - //WSReceiverInfo* ws_receiver_info = context; - - if(event->key == InputKeyBack) { - return false; - } - - return true; -} - -static void ws_view_receiver_info_enter(void* context) { - furi_assert(context); - WSReceiverInfo* ws_receiver_info = context; - - furi_timer_start(ws_receiver_info->timer, 1000); -} - -static void ws_view_receiver_info_exit(void* context) { - furi_assert(context); - WSReceiverInfo* ws_receiver_info = context; - - furi_timer_stop(ws_receiver_info->timer); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { furi_string_reset(model->protocol_name); }, - false); -} - -static void ws_view_receiver_info_timer(void* context) { - WSReceiverInfo* ws_receiver_info = context; - // Force redraw - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); - }, - true); -} - -WSReceiverInfo* ws_view_receiver_info_alloc() { - WSReceiverInfo* ws_receiver_info = malloc(sizeof(WSReceiverInfo)); - - // View allocation and configuration - ws_receiver_info->view = view_alloc(); - - view_allocate_model(ws_receiver_info->view, ViewModelTypeLocking, sizeof(WSReceiverInfoModel)); - view_set_context(ws_receiver_info->view, ws_receiver_info); - view_set_draw_callback(ws_receiver_info->view, (ViewDrawCallback)ws_view_receiver_info_draw); - view_set_input_callback(ws_receiver_info->view, ws_view_receiver_info_input); - view_set_enter_callback(ws_receiver_info->view, ws_view_receiver_info_enter); - view_set_exit_callback(ws_receiver_info->view, ws_view_receiver_info_exit); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - model->generic = malloc(sizeof(WSBlockGeneric)); - model->protocol_name = furi_string_alloc(); - }, - true); - - ws_receiver_info->timer = - furi_timer_alloc(ws_view_receiver_info_timer, FuriTimerTypePeriodic, ws_receiver_info); - - return ws_receiver_info; -} - -void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info) { - furi_assert(ws_receiver_info); - - furi_timer_free(ws_receiver_info->timer); - - with_view_model( - ws_receiver_info->view, - WSReceiverInfoModel * model, - { - furi_string_free(model->protocol_name); - free(model->generic); - }, - false); - - view_free(ws_receiver_info->view); - free(ws_receiver_info); -} - -View* ws_view_receiver_info_get_view(WSReceiverInfo* ws_receiver_info) { - furi_assert(ws_receiver_info); - return ws_receiver_info->view; -} diff --git a/applications/external/weather_station/views/weather_station_receiver_info.h b/applications/external/weather_station/views/weather_station_receiver_info.h deleted file mode 100644 index 705434a23..000000000 --- a/applications/external/weather_station/views/weather_station_receiver_info.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "../helpers/weather_station_types.h" -#include "../helpers/weather_station_event.h" -#include - -typedef struct WSReceiverInfo WSReceiverInfo; - -void ws_view_receiver_info_update(WSReceiverInfo* ws_receiver_info, FlipperFormat* fff); - -WSReceiverInfo* ws_view_receiver_info_alloc(); - -void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info); - -View* ws_view_receiver_info_get_view(WSReceiverInfo* ws_receiver_info); diff --git a/applications/external/weather_station/weather_station_10px.png b/applications/external/weather_station/weather_station_10px.png deleted file mode 100644 index 7d5cc318c..000000000 Binary files a/applications/external/weather_station/weather_station_10px.png and /dev/null differ diff --git a/applications/external/weather_station/weather_station_app.c b/applications/external/weather_station/weather_station_app.c deleted file mode 100644 index 2305fa77b..000000000 --- a/applications/external/weather_station/weather_station_app.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "weather_station_app_i.h" - -#include -#include -#include "protocols/protocol_items.h" - -static bool weather_station_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - WeatherStationApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool weather_station_app_back_event_callback(void* context) { - furi_assert(context); - WeatherStationApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void weather_station_app_tick_event_callback(void* context) { - furi_assert(context); - WeatherStationApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -WeatherStationApp* weather_station_app_alloc() { - WeatherStationApp* app = malloc(sizeof(WeatherStationApp)); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&weather_station_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, weather_station_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, weather_station_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, weather_station_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // Variable Item List - app->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewVariableItemList, - variable_item_list_get_view(app->variable_item_list)); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WeatherStationViewSubmenu, submenu_get_view(app->submenu)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, WeatherStationViewWidget, widget_get_view(app->widget)); - - // Receiver - app->ws_receiver = ws_view_receiver_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewReceiver, - ws_view_receiver_get_view(app->ws_receiver)); - - // Receiver Info - app->ws_receiver_info = ws_view_receiver_info_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - WeatherStationViewReceiverInfo, - ws_view_receiver_info_get_view(app->ws_receiver_info)); - - //init setting - app->setting = subghz_setting_alloc(); - - //ToDo FIX file name setting - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); - - //init Worker & Protocol & History - app->lock = WSLockOff; - app->txrx = malloc(sizeof(WeatherStationTxRx)); - app->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); - app->txrx->preset->name = furi_string_alloc(); - ws_preset_init(app, "AM650", subghz_setting_get_default_frequency(app->setting), NULL, 0); - - app->txrx->hopper_state = WSHopperStateOFF; - app->txrx->history = ws_history_alloc(); - app->txrx->worker = subghz_worker_alloc(); - app->txrx->environment = subghz_environment_alloc(); - subghz_environment_set_protocol_registry( - app->txrx->environment, (void*)&weather_station_protocol_registry); - app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); - - subghz_devices_init(); - - app->txrx->radio_device = - radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101); - - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - - subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); - subghz_worker_set_overrun_callback( - app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); - subghz_worker_set_pair_callback( - app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); - subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - - furi_hal_power_suppress_charge_enter(); - - scene_manager_next_scene(app->scene_manager, WeatherStationSceneStart); - - return app; -} - -void weather_station_app_free(WeatherStationApp* app) { - furi_assert(app); - - subghz_devices_sleep(app->txrx->radio_device); - radio_device_loader_end(app->txrx->radio_device); - - subghz_devices_deinit(); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewSubmenu); - submenu_free(app->submenu); - - // Variable Item List - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewVariableItemList); - variable_item_list_free(app->variable_item_list); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewWidget); - widget_free(app->widget); - - // Receiver - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewReceiver); - ws_view_receiver_free(app->ws_receiver); - - // Receiver Info - view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewReceiverInfo); - ws_view_receiver_info_free(app->ws_receiver_info); - - //setting - subghz_setting_free(app->setting); - - //Worker & Protocol & History - subghz_receiver_free(app->txrx->receiver); - subghz_environment_free(app->txrx->environment); - ws_history_free(app->txrx->history); - subghz_worker_free(app->txrx->worker); - furi_string_free(app->txrx->preset->name); - free(app->txrx->preset); - free(app->txrx); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - furi_hal_power_suppress_charge_exit(); - - free(app); -} - -int32_t weather_station_app(void* p) { - UNUSED(p); - WeatherStationApp* weather_station_app = weather_station_app_alloc(); - - view_dispatcher_run(weather_station_app->view_dispatcher); - - weather_station_app_free(weather_station_app); - - return 0; -} diff --git a/applications/external/weather_station/weather_station_app_i.c b/applications/external/weather_station/weather_station_app_i.c deleted file mode 100644 index e98c61ee5..000000000 --- a/applications/external/weather_station/weather_station_app_i.c +++ /dev/null @@ -1,155 +0,0 @@ -#include "weather_station_app_i.h" - -#define TAG "WeatherStation" -#include - -void ws_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(context); - WeatherStationApp* app = context; - furi_string_set(app->txrx->preset->name, preset_name); - app->txrx->preset->frequency = frequency; - app->txrx->preset->data = preset_data; - app->txrx->preset->data_size = preset_data_size; -} - -bool ws_set_preset(WeatherStationApp* app, const char* preset) { - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - furi_string_set(app->txrx->preset->name, "AM270"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - furi_string_set(app->txrx->preset->name, "AM650"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - furi_string_set(app->txrx->preset->name, "FM238"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - furi_string_set(app->txrx->preset->name, "FM476"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - furi_string_set(app->txrx->preset->name, "CUSTOM"); - } else { - FURI_LOG_E(TAG, "Unknown preset"); - return false; - } - return true; -} - -void ws_get_frequency_modulation( - WeatherStationApp* app, - FuriString* frequency, - FuriString* modulation) { - furi_assert(app); - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - app->txrx->preset->frequency / 1000000 % 1000, - app->txrx->preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(app->txrx->preset->name)); - } -} - -void ws_begin(WeatherStationApp* app, uint8_t* preset_data) { - furi_assert(app); - subghz_devices_reset(app->txrx->radio_device); - subghz_devices_idle(app->txrx->radio_device); - subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) { - furi_assert(app); - if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) { - furi_crash("WeatherStation: Incorrect RX frequency."); - } - furi_assert( - app->txrx->txrx_state != WSTxRxStateRx && app->txrx->txrx_state != WSTxRxStateSleep); - - subghz_devices_idle(app->txrx->radio_device); - uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency); - subghz_devices_flush_rx(app->txrx->radio_device); - subghz_devices_set_rx(app->txrx->radio_device); - - subghz_devices_start_async_rx( - app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker); - - subghz_worker_start(app->txrx->worker); - app->txrx->txrx_state = WSTxRxStateRx; - return value; -} - -void ws_idle(WeatherStationApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state != WSTxRxStateSleep); - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -void ws_rx_end(WeatherStationApp* app) { - furi_assert(app); - furi_assert(app->txrx->txrx_state == WSTxRxStateRx); - if(subghz_worker_is_running(app->txrx->worker)) { - subghz_worker_stop(app->txrx->worker); - subghz_devices_stop_async_rx(app->txrx->radio_device); - } - subghz_devices_idle(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateIDLE; -} - -void ws_sleep(WeatherStationApp* app) { - furi_assert(app); - subghz_devices_sleep(app->txrx->radio_device); - app->txrx->txrx_state = WSTxRxStateSleep; -} - -void ws_hopper_update(WeatherStationApp* app) { - furi_assert(app); - - switch(app->txrx->hopper_state) { - case WSHopperStateOFF: - case WSHopperStatePause: - return; - case WSHopperStateRSSITimeOut: - if(app->txrx->hopper_timeout != 0) { - app->txrx->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(app->txrx->hopper_state != WSHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = subghz_devices_get_rssi(app->txrx->radio_device); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - app->txrx->hopper_timeout = 10; - app->txrx->hopper_state = WSHopperStateRSSITimeOut; - return; - } - } else { - app->txrx->hopper_state = WSHopperStateRunnig; - } - // Select next frequency - if(app->txrx->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(app->setting) - 1) { - app->txrx->hopper_idx_frequency++; - } else { - app->txrx->hopper_idx_frequency = 0; - } - - if(app->txrx->txrx_state == WSTxRxStateRx) { - ws_rx_end(app); - }; - if(app->txrx->txrx_state == WSTxRxStateIDLE) { - subghz_receiver_reset(app->txrx->receiver); - app->txrx->preset->frequency = - subghz_setting_get_hopper_frequency(app->setting, app->txrx->hopper_idx_frequency); - ws_rx(app, app->txrx->preset->frequency); - } -} diff --git a/applications/external/weather_station/weather_station_app_i.h b/applications/external/weather_station/weather_station_app_i.h deleted file mode 100644 index 0950f5975..000000000 --- a/applications/external/weather_station/weather_station_app_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "helpers/weather_station_types.h" - -#include "scenes/weather_station_scene.h" -#include -#include -#include -#include -#include -#include -#include -#include "views/weather_station_receiver.h" -#include "views/weather_station_receiver_info.h" -#include "weather_station_history.h" - -#include -#include -#include -#include -#include - -#include "helpers/radio_device_loader.h" - -typedef struct WeatherStationApp WeatherStationApp; - -struct WeatherStationTxRx { - SubGhzWorker* worker; - - const SubGhzDevice* radio_device; - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzRadioPreset* preset; - WSHistory* history; - uint16_t idx_menu_chosen; - WSTxRxState txrx_state; - WSHopperState hopper_state; - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - WSRxKeyState rx_key_state; -}; - -typedef struct WeatherStationTxRx WeatherStationTxRx; - -struct WeatherStationApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - WeatherStationTxRx* txrx; - SceneManager* scene_manager; - NotificationApp* notifications; - VariableItemList* variable_item_list; - Submenu* submenu; - Widget* widget; - WSReceiver* ws_receiver; - WSReceiverInfo* ws_receiver_info; - WSLock lock; - SubGhzSetting* setting; -}; - -void ws_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); -bool ws_set_preset(WeatherStationApp* app, const char* preset); -void ws_get_frequency_modulation( - WeatherStationApp* app, - FuriString* frequency, - FuriString* modulation); -void ws_begin(WeatherStationApp* app, uint8_t* preset_data); -uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency); -void ws_idle(WeatherStationApp* app); -void ws_rx_end(WeatherStationApp* app); -void ws_sleep(WeatherStationApp* app); -void ws_hopper_update(WeatherStationApp* app); diff --git a/applications/external/weather_station/weather_station_history.c b/applications/external/weather_station/weather_station_history.c deleted file mode 100644 index 9adff39c6..000000000 --- a/applications/external/weather_station/weather_station_history.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "weather_station_history.h" -#include -#include -#include -#include "protocols/ws_generic.h" - -#include - -#define WS_HISTORY_MAX 50 -#define TAG "WSHistory" - -typedef struct { - FuriString* item_str; - FlipperFormat* flipper_string; - uint8_t type; - uint32_t id; - SubGhzRadioPreset* preset; -} WSHistoryItem; - -ARRAY_DEF(WSHistoryItemArray, WSHistoryItem, M_POD_OPLIST) - -#define M_OPL_WSHistoryItemArray_t() ARRAY_OPLIST(WSHistoryItemArray, M_POD_OPLIST) - -typedef struct { - WSHistoryItemArray_t data; -} WSHistoryStruct; - -struct WSHistory { - uint32_t last_update_timestamp; - uint16_t last_index_write; - uint8_t code_last_hash_data; - FuriString* tmp_string; - WSHistoryStruct* history; -}; - -WSHistory* ws_history_alloc(void) { - WSHistory* instance = malloc(sizeof(WSHistory)); - instance->tmp_string = furi_string_alloc(); - instance->history = malloc(sizeof(WSHistoryStruct)); - WSHistoryItemArray_init(instance->history->data); - return instance; -} - -void ws_history_free(WSHistory* instance) { - furi_assert(instance); - furi_string_free(instance->tmp_string); - for - M_EACH(item, instance->history->data, WSHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - WSHistoryItemArray_clear(instance->history->data); - free(instance->history); - free(instance); -} - -uint32_t ws_history_get_frequency(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->preset->frequency; -} - -SubGhzRadioPreset* ws_history_get_radio_preset(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->preset; -} - -const char* ws_history_get_preset(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return furi_string_get_cstr(item->preset->name); -} - -void ws_history_reset(WSHistory* instance) { - furi_assert(instance); - furi_string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, WSHistoryItemArray_t) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } - WSHistoryItemArray_reset(instance->history->data); - instance->last_index_write = 0; - instance->code_last_hash_data = 0; -} - -uint16_t ws_history_get_item(WSHistory* instance) { - furi_assert(instance); - return instance->last_index_write; -} - -uint8_t ws_history_get_type_protocol(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - return item->type; -} - -const char* ws_history_get_protocol_name(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - furi_string_reset(instance->tmp_string); - } - return furi_string_get_cstr(instance->tmp_string); -} - -FlipperFormat* ws_history_get_raw_data(WSHistory* instance, uint16_t idx) { - furi_assert(instance); - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - if(item->flipper_string) { - return item->flipper_string; - } else { - return NULL; - } -} -bool ws_history_get_text_space_left(WSHistory* instance, FuriString* output) { - furi_assert(instance); - if(instance->last_index_write == WS_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); - return true; - } - if(output != NULL) - furi_string_printf(output, "%02u/%02u", instance->last_index_write, WS_HISTORY_MAX); - return false; -} - -void ws_history_get_text_item_menu(WSHistory* instance, FuriString* output, uint16_t idx) { - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, idx); - furi_string_set(output, item->item_str); -} - -WSHistoryStateAddKey - ws_history_add_to_history(WSHistory* instance, void* context, SubGhzRadioPreset* preset) { - furi_assert(instance); - furi_assert(context); - - if(instance->last_index_write >= WS_HISTORY_MAX) return WSHistoryStateAddKeyOverflow; - - SubGhzProtocolDecoderBase* decoder_base = context; - if((instance->code_last_hash_data == - subghz_protocol_decoder_base_get_hash_data(decoder_base)) && - ((furi_get_tick() - instance->last_update_timestamp) < 500)) { - instance->last_update_timestamp = furi_get_tick(); - return WSHistoryStateAddKeyTimeOut; - } - - instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); - instance->last_update_timestamp = furi_get_tick(); - - FlipperFormat* fff = flipper_format_string_alloc(); - uint32_t id = 0; - subghz_protocol_decoder_base_serialize(decoder_base, fff, preset); - - do { - if(!flipper_format_rewind(fff)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_uint32(fff, "Id", (uint32_t*)&id, 1)) { - FURI_LOG_E(TAG, "Missing Id"); - break; - } - } while(false); - flipper_format_free(fff); - - //Update record if found - bool sensor_found = false; - for(size_t i = 0; i < WSHistoryItemArray_size(instance->history->data); i++) { - WSHistoryItem* item = WSHistoryItemArray_get(instance->history->data, i); - if(item->id == id) { - sensor_found = true; - Stream* flipper_string_stream = flipper_format_get_raw_stream(item->flipper_string); - stream_clean(flipper_string_stream); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - return WSHistoryStateAddKeyUpdateData; - } - } - - // or add new record - if(!sensor_found) { //-V547 - WSHistoryItem* item = WSHistoryItemArray_push_raw(instance->history->data); - item->preset = malloc(sizeof(SubGhzRadioPreset)); - item->type = decoder_base->protocol->type; - item->preset->frequency = preset->frequency; - item->preset->name = furi_string_alloc(); - furi_string_set(item->preset->name, preset->name); - item->preset->data = preset->data; - item->preset->data_size = preset->data_size; - item->id = id; - - item->item_str = furi_string_alloc(); - item->flipper_string = flipper_format_string_alloc(); - subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); - - do { - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string( - item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - if(!flipper_format_rewind(item->flipper_string)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - uint8_t key_data[sizeof(uint64_t)] = {0}; - if(!flipper_format_read_hex(item->flipper_string, "Data", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Missing Data"); - break; - } - uint64_t data = 0; - for(uint8_t i = 0; i < sizeof(uint64_t); i++) { - data = (data << 8) | key_data[i]; - } - uint32_t temp_data = 0; - if(!flipper_format_read_uint32(item->flipper_string, "Ch", (uint32_t*)&temp_data, 1)) { - FURI_LOG_E(TAG, "Missing Channel"); - break; - } - if(temp_data != WS_NO_CHANNEL) { - furi_string_cat_printf(instance->tmp_string, " Ch:%X", (uint8_t)temp_data); - } - - furi_string_printf( - item->item_str, "%s %llX", furi_string_get_cstr(instance->tmp_string), data); - - } while(false); - instance->last_index_write++; - return WSHistoryStateAddKeyNewDada; - } - return WSHistoryStateAddKeyUnknown; -} diff --git a/applications/external/weather_station/weather_station_history.h b/applications/external/weather_station/weather_station_history.h deleted file mode 100644 index 11601fe79..000000000 --- a/applications/external/weather_station/weather_station_history.h +++ /dev/null @@ -1,112 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include - -typedef struct WSHistory WSHistory; - -/** History state add key */ -typedef enum { - WSHistoryStateAddKeyUnknown, - WSHistoryStateAddKeyTimeOut, - WSHistoryStateAddKeyNewDada, - WSHistoryStateAddKeyUpdateData, - WSHistoryStateAddKeyOverflow, -} WSHistoryStateAddKey; - -/** Allocate WSHistory - * - * @return WSHistory* - */ -WSHistory* ws_history_alloc(void); - -/** Free WSHistory - * - * @param instance - WSHistory instance - */ -void ws_history_free(WSHistory* instance); - -/** Clear history - * - * @param instance - WSHistory instance - */ -void ws_history_reset(WSHistory* instance); - -/** Get frequency to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return frequency - frequency Hz - */ -uint32_t ws_history_get_frequency(WSHistory* instance, uint16_t idx); - -SubGhzRadioPreset* ws_history_get_radio_preset(WSHistory* instance, uint16_t idx); - -/** Get preset to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return preset - preset name - */ -const char* ws_history_get_preset(WSHistory* instance, uint16_t idx); - -/** Get history index write - * - * @param instance - WSHistory instance - * @return idx - current record index - */ -uint16_t ws_history_get_item(WSHistory* instance); - -/** Get type protocol to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return type - type protocol - */ -uint8_t ws_history_get_type_protocol(WSHistory* instance, uint16_t idx); - -/** Get name protocol to history[idx] - * - * @param instance - WSHistory instance - * @param idx - record index - * @return name - const char* name protocol - */ -const char* ws_history_get_protocol_name(WSHistory* instance, uint16_t idx); - -/** Get string item menu to history[idx] - * - * @param instance - WSHistory instance - * @param output - FuriString* output - * @param idx - record index - */ -void ws_history_get_text_item_menu(WSHistory* instance, FuriString* output, uint16_t idx); - -/** Get string the remaining number of records to history - * - * @param instance - WSHistory instance - * @param output - FuriString* output - * @return bool - is FUUL - */ -bool ws_history_get_text_space_left(WSHistory* instance, FuriString* output); - -/** Add protocol to history - * - * @param instance - WSHistory instance - * @param context - SubGhzProtocolCommon context - * @param preset - SubGhzRadioPreset preset - * @return WSHistoryStateAddKey; - */ -WSHistoryStateAddKey - ws_history_add_to_history(WSHistory* instance, void* context, SubGhzRadioPreset* preset); - -/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data - * - * @param instance - WSHistory instance - * @param idx - record index - * @return SubGhzProtocolCommonLoad* - */ -FlipperFormat* ws_history_get_raw_data(WSHistory* instance, uint16_t idx); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index d09b63c4e..a5d9b1449 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -11,6 +11,8 @@ enum SubGhzSettingIndex { SubGhzSettingIndexIgnoreStarline, SubGhzSettingIndexIgnoreCars, SubGhzSettingIndexIgnoreMagellan, + SubGhzSettingIndexIgnoreWeather, + SubGhzSettingIndexIgnoreTPMS, SubGhzSettingIndexIgnorePrinceton, SubGhzSettingIndexSound, SubGhzSettingIndexResetToDefault, @@ -274,6 +276,13 @@ static void subghz_scene_receiver_config_set_magellan(VariableItem* item) { subghz_scene_receiver_config_set_ignore_filter(item, SubGhzProtocolFlag_Magellan); } +static void subghz_scene_receiver_config_set_weather(VariableItem* item) { + subghz_scene_receiver_config_set_ignore_filter(item, SubGhzProtocolFlag_Weather); +} +static void subghz_scene_receiver_config_set_tpms(VariableItem* item) { + subghz_scene_receiver_config_set_ignore_filter(item, SubGhzProtocolFlag_TPMS); +} + static void subghz_scene_receiver_config_set_princeton(VariableItem* item) { subghz_scene_receiver_config_set_ignore_filter(item, SubGhzProtocolFlag_Princeton); } @@ -433,6 +442,30 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, combobox_text[value_index]); + item = variable_item_list_add( + subghz->variable_item_list, + "Ignore Weather:", + COMBO_BOX_COUNT, + subghz_scene_receiver_config_set_weather, + subghz); + + value_index = subghz_scene_receiver_config_ignore_filter_get_index( + subghz->ignore_filter, SubGhzProtocolFlag_Weather); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, combobox_text[value_index]); + + item = variable_item_list_add( + subghz->variable_item_list, + "Ignore TPMS:", + COMBO_BOX_COUNT, + subghz_scene_receiver_config_set_tpms, + subghz); + + value_index = subghz_scene_receiver_config_ignore_filter_get_index( + subghz->ignore_filter, SubGhzProtocolFlag_TPMS); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, combobox_text[value_index]); + item = variable_item_list_add( subghz->variable_item_list, "Ignore Princeton:", diff --git a/assets/unit_tests/subghz/acurite_592txr.sub b/assets/unit_tests/subghz/acurite_592txr.sub new file mode 100644 index 000000000..379d11f7b --- /dev/null +++ b/assets/unit_tests/subghz/acurite_592txr.sub @@ -0,0 +1,6 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok270Async +Protocol: RAW +RAW_Data: 24683 -68 97699 -66 49329 -68 77683 -66 369085 -100 59281 -68 29331 -64 357017 -68 284193 -66 128025 -64 198459 -64 522601 -66 111101 -70 132215 -64 288735 -68 747835 -102 26103 -70 25451 -68 349459 -66 166857 -66 68137 -66 595143 -128 59929 -66 17225 -66 16705 -66 105655 -66 10015 -38916 101 -2318 493 -708 395 -716 505 -734 487 -694 343 -274 339 -260 163 -440 343 -306 319 -268 159 -436 201 -432 157 -438 387 -244 179 -410 379 -234 187 -430 397 -218 183 -436 387 -236 371 -244 179 -414 409 -190 223 -410 193 -416 213 -396 393 -228 199 -406 209 -422 207 -392 387 -240 207 -384 419 -204 219 -394 203 -418 379 -244 395 -202 395 -208 251 -392 205 -380 221 -378 417 -242 215 -392 205 -396 203 -408 417 -204 217 -396 203 -394 389 -246 393 -206 393 -240 217 -396 203 -394 205 -410 191 -418 411 -190 401 -246 389 -206 393 -240 379 -222 187 -400 239 -2198 615 -592 615 -612 605 -614 597 -620 367 -224 411 -214 215 -402 387 -206 407 -226 197 -404 209 -422 205 -394 387 -238 207 -384 417 -204 219 -394 389 -238 205 -388 415 -206 379 -222 227 -400 417 -204 217 -396 203 -394 231 -370 413 -240 217 -394 203 -394 207 -408 393 -240 217 -392 367 -222 225 -400 209 -418 367 -224 413 -214 393 -204 215 -428 207 -394 201 -394 391 -246 213 -368 245 -394 203 -394 385 -240 209 -392 243 -390 395 -226 385 -212 395 -238 219 -392 205 -394 203 -418 223 -412 387 -242 369 -226 393 -210 395 -238 393 -208 217 -394 203 -59252 317 -277080 99 -1690 201 -634 469 -270 1393 -300 97817 -66 55659 -64 628165 -64 110139 -100 61425 -66 59611 -66 6621 -68 18847 -66 468225 -64 99275 diff --git a/applications/external/weather_station/protocols/acurite_592txr.c b/lib/subghz/protocols/acurite_592txr.c similarity index 68% rename from applications/external/weather_station/protocols/acurite_592txr.c rename to lib/subghz/protocols/acurite_592txr.c index 874f6dd33..02cd7052d 100644 --- a/applications/external/weather_station/protocols/acurite_592txr.c +++ b/lib/subghz/protocols/acurite_592txr.c @@ -26,6 +26,8 @@ * - However 14 bits available for temperature, giving possible range of -100 C to 1538.4 C * - @todo - check if high 3 bits ever used for anything else * + * SUB file generator: https://htotoo.github.io/FlipperSUBGenerator/acurite_592txr-generator/index.html + * */ static const SubGhzBlockConst ws_protocol_acurite_592txr_const = { @@ -72,19 +74,20 @@ const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder = { }; const SubGhzProtocolEncoder ws_protocol_acurite_592txr_encoder = { - .alloc = NULL, - .free = NULL, + .alloc = ws_protocol_encoder_acurite_592txr_alloc, + .free = ws_protocol_encoder_acurite_592txr_free, - .deserialize = NULL, - .stop = NULL, - .yield = NULL, + .deserialize = ws_protocol_encoder_acurite_592txr_deserialize, + .stop = ws_protocol_encoder_acurite_592txr_stop, + .yield = ws_protocol_encoder_acurite_592txr_yield, }; const SubGhzProtocol ws_protocol_acurite_592txr = { .name = WS_PROTOCOL_ACURITE_592TXR_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, .decoder = &ws_protocol_acurite_592txr_decoder, .encoder = &ws_protocol_acurite_592txr_encoder, @@ -280,9 +283,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAcurite_592TXR* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", @@ -296,3 +299,120 @@ void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* ou (double)instance->generic.temp, instance->generic.humidity); } + +void* ws_protocol_encoder_acurite_592txr_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolEncoderAcurite_592TXR* instance = malloc(sizeof(WSProtocolEncoderAcurite_592TXR)); + + instance->base.protocol = &ws_protocol_acurite_592txr; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 6; + instance->encoder.size_upload = + ws_protocol_acurite_592txr_const.min_count_bit_for_found * 2 + 8; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void ws_protocol_encoder_acurite_592txr_free(void* context) { + furi_assert(context); + WSProtocolEncoderAcurite_592TXR* instance = context; + free(instance->encoder.upload); + free(instance); +} + +bool ws_protocol_encoder_acurite_592txr_get_upload(WSProtocolEncoderAcurite_592TXR* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 8; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_short * 3); + + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(!bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_long); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_acurite_592txr_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_acurite_592txr_const.te_short); + } + } + + return true; +} + +SubGhzProtocolStatus + ws_protocol_encoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolEncoderAcurite_592TXR* instance = context; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = ws_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + if((instance->generic.data_count_bit > + ws_protocol_acurite_592txr_const.min_count_bit_for_found)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 6); + + if(!ws_protocol_encoder_acurite_592txr_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } + instance->encoder.is_running = true; + } while(false); + + return ret; +} + +LevelDuration ws_protocol_encoder_acurite_592txr_yield(void* context) { + WSProtocolEncoderAcurite_592TXR* instance = context; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + return ret; +} + +void ws_protocol_encoder_acurite_592txr_stop(void* context) { + WSProtocolEncoderAcurite_592TXR* instance = context; + instance->encoder.is_running = false; +} \ No newline at end of file diff --git a/applications/external/weather_station/protocols/acurite_592txr.h b/lib/subghz/protocols/acurite_592txr.h similarity index 85% rename from applications/external/weather_station/protocols/acurite_592txr.h rename to lib/subghz/protocols/acurite_592txr.h index 1071d1cf7..6489ec9fe 100644 --- a/applications/external/weather_station/protocols/acurite_592txr.h +++ b/lib/subghz/protocols/acurite_592txr.h @@ -78,3 +78,11 @@ SubGhzProtocolStatus * @param output Resulting text */ void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output); + +void* ws_protocol_encoder_acurite_592txr_alloc(SubGhzEnvironment* environment); +void ws_protocol_encoder_acurite_592txr_free(void* context); +bool ws_protocol_encoder_acurite_592txr_get_upload(WSProtocolEncoderAcurite_592TXR* instance); +SubGhzProtocolStatus + ws_protocol_encoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format); +LevelDuration ws_protocol_encoder_acurite_592txr_yield(void* context); +void ws_protocol_encoder_acurite_592txr_stop(void* context); \ No newline at end of file diff --git a/applications/external/weather_station/protocols/acurite_606tx.c b/lib/subghz/protocols/acurite_606tx.c similarity index 97% rename from applications/external/weather_station/protocols/acurite_606tx.c rename to lib/subghz/protocols/acurite_606tx.c index e0d405c66..b324fae6c 100644 --- a/applications/external/weather_station/protocols/acurite_606tx.c +++ b/lib/subghz/protocols/acurite_606tx.c @@ -67,9 +67,10 @@ const SubGhzProtocolEncoder ws_protocol_acurite_606tx_encoder = { const SubGhzProtocol ws_protocol_acurite_606tx = { .name = WS_PROTOCOL_ACURITE_606TX_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_acurite_606tx_decoder, .encoder = &ws_protocol_acurite_606tx_encoder, @@ -221,9 +222,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAcurite_606TX* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/acurite_606tx.h b/lib/subghz/protocols/acurite_606tx.h similarity index 100% rename from applications/external/weather_station/protocols/acurite_606tx.h rename to lib/subghz/protocols/acurite_606tx.h diff --git a/applications/external/weather_station/protocols/acurite_609txc.c b/lib/subghz/protocols/acurite_609txc.c similarity index 98% rename from applications/external/weather_station/protocols/acurite_609txc.c rename to lib/subghz/protocols/acurite_609txc.c index 853b78446..8ae82b62b 100644 --- a/applications/external/weather_station/protocols/acurite_609txc.c +++ b/lib/subghz/protocols/acurite_609txc.c @@ -68,9 +68,10 @@ const SubGhzProtocolEncoder ws_protocol_acurite_609txc_encoder = { const SubGhzProtocol ws_protocol_acurite_609txc = { .name = WS_PROTOCOL_ACURITE_609TXC_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_acurite_609txc_decoder, .encoder = &ws_protocol_acurite_609txc_encoder, @@ -221,9 +222,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAcurite_609TXC* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/acurite_609txc.h b/lib/subghz/protocols/acurite_609txc.h similarity index 100% rename from applications/external/weather_station/protocols/acurite_609txc.h rename to lib/subghz/protocols/acurite_609txc.h diff --git a/applications/external/weather_station/protocols/ambient_weather.c b/lib/subghz/protocols/ambient_weather.c similarity index 98% rename from applications/external/weather_station/protocols/ambient_weather.c rename to lib/subghz/protocols/ambient_weather.c index 588a7f82a..793ad615b 100644 --- a/applications/external/weather_station/protocols/ambient_weather.c +++ b/lib/subghz/protocols/ambient_weather.c @@ -82,9 +82,10 @@ const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder = { const SubGhzProtocol ws_protocol_ambient_weather = { .name = WS_PROTOCOL_AMBIENT_WEATHER_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_ambient_weather_decoder, .encoder = &ws_protocol_ambient_weather_encoder, @@ -250,9 +251,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAmbient_Weather* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/ambient_weather.h b/lib/subghz/protocols/ambient_weather.h similarity index 100% rename from applications/external/weather_station/protocols/ambient_weather.h rename to lib/subghz/protocols/ambient_weather.h diff --git a/applications/external/weather_station/protocols/auriol_ahfl.c b/lib/subghz/protocols/auriol_ahfl.c similarity index 98% rename from applications/external/weather_station/protocols/auriol_ahfl.c rename to lib/subghz/protocols/auriol_ahfl.c index 80b89e380..d6246bec6 100644 --- a/applications/external/weather_station/protocols/auriol_ahfl.c +++ b/lib/subghz/protocols/auriol_ahfl.c @@ -79,9 +79,10 @@ const SubGhzProtocolEncoder ws_protocol_auriol_ahfl_encoder = { const SubGhzProtocol ws_protocol_auriol_ahfl = { .name = WS_PROTOCOL_AURIOL_AHFL_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_auriol_ahfl_decoder, .encoder = &ws_protocol_auriol_ahfl_encoder, @@ -236,9 +237,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_auriol_ahfl_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAuriol_AHFL* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/auriol_ahfl.h b/lib/subghz/protocols/auriol_ahfl.h similarity index 100% rename from applications/external/weather_station/protocols/auriol_ahfl.h rename to lib/subghz/protocols/auriol_ahfl.h diff --git a/applications/external/weather_station/protocols/auriol_hg0601a.c b/lib/subghz/protocols/auriol_hg0601a.c similarity index 97% rename from applications/external/weather_station/protocols/auriol_hg0601a.c rename to lib/subghz/protocols/auriol_hg0601a.c index 813fe1526..b7fd97bfd 100644 --- a/applications/external/weather_station/protocols/auriol_hg0601a.c +++ b/lib/subghz/protocols/auriol_hg0601a.c @@ -78,9 +78,10 @@ const SubGhzProtocolEncoder ws_protocol_auriol_th_encoder = { const SubGhzProtocol ws_protocol_auriol_th = { .name = WS_PROTOCOL_AURIOL_TH_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_auriol_th_decoder, .encoder = &ws_protocol_auriol_th_encoder, @@ -230,9 +231,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderAuriol_TH* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/auriol_hg0601a.h b/lib/subghz/protocols/auriol_hg0601a.h similarity index 100% rename from applications/external/weather_station/protocols/auriol_hg0601a.h rename to lib/subghz/protocols/auriol_hg0601a.h diff --git a/applications/external/weather_station/protocols/gt_wt_02.c b/lib/subghz/protocols/gt_wt_02.c similarity index 96% rename from applications/external/weather_station/protocols/gt_wt_02.c rename to lib/subghz/protocols/gt_wt_02.c index d333164b4..88f9ed2a7 100644 --- a/applications/external/weather_station/protocols/gt_wt_02.c +++ b/lib/subghz/protocols/gt_wt_02.c @@ -9,9 +9,9 @@ * GT-WT-02 sensor on 433.92MHz. * Example and frame description provided by https://github.com/ludwich66 * [01] {37} 34 00 ed 47 60 : 00110100 00000000 11101101 01000111 01100000 - * code, BatOK,not-man-send, Channel1, +23,7°C, 35% + * code, BatOK,not-man-send, Channel1, +23,7�C, 35% * [01] {37} 34 8f 87 15 90 : 00110100 10001111 10000111 00010101 10010000 - * code, BatOK,not-man-send, Channel1,-12,1°C, 10% + * code, BatOK,not-man-send, Channel1,-12,1�C, 10% * Humidity: * - the working range is 20-90 % * - if "LL" in display view it sends 10 % @@ -81,9 +81,10 @@ const SubGhzProtocolEncoder ws_protocol_gt_wt_02_encoder = { const SubGhzProtocol ws_protocol_gt_wt_02 = { .name = WS_PROTOCOL_GT_WT_02_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_gt_wt_02_decoder, .encoder = &ws_protocol_gt_wt_02_encoder, @@ -237,9 +238,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderGT_WT02* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/gt_wt_02.h b/lib/subghz/protocols/gt_wt_02.h similarity index 100% rename from applications/external/weather_station/protocols/gt_wt_02.h rename to lib/subghz/protocols/gt_wt_02.h diff --git a/applications/external/weather_station/protocols/gt_wt_03.c b/lib/subghz/protocols/gt_wt_03.c similarity index 98% rename from applications/external/weather_station/protocols/gt_wt_03.c rename to lib/subghz/protocols/gt_wt_03.c index 30430b839..8359f5b32 100644 --- a/applications/external/weather_station/protocols/gt_wt_03.c +++ b/lib/subghz/protocols/gt_wt_03.c @@ -107,9 +107,10 @@ const SubGhzProtocolEncoder ws_protocol_gt_wt_03_encoder = { const SubGhzProtocol ws_protocol_gt_wt_03 = { .name = WS_PROTOCOL_GT_WT_03_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_gt_wt_03_decoder, .encoder = &ws_protocol_gt_wt_03_encoder, @@ -312,9 +313,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderGT_WT03* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/gt_wt_03.h b/lib/subghz/protocols/gt_wt_03.h similarity index 100% rename from applications/external/weather_station/protocols/gt_wt_03.h rename to lib/subghz/protocols/gt_wt_03.h diff --git a/applications/external/weather_station/protocols/infactory.c b/lib/subghz/protocols/infactory.c similarity index 98% rename from applications/external/weather_station/protocols/infactory.c rename to lib/subghz/protocols/infactory.c index 4b0e6602a..7722b772c 100644 --- a/applications/external/weather_station/protocols/infactory.c +++ b/lib/subghz/protocols/infactory.c @@ -92,9 +92,10 @@ const SubGhzProtocolEncoder ws_protocol_infactory_encoder = { const SubGhzProtocol ws_protocol_infactory = { .name = WS_PROTOCOL_INFACTORY_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_infactory_decoder, .encoder = &ws_protocol_infactory_encoder, @@ -268,9 +269,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderInfactory* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/infactory.h b/lib/subghz/protocols/infactory.h similarity index 100% rename from applications/external/weather_station/protocols/infactory.h rename to lib/subghz/protocols/infactory.h diff --git a/applications/external/weather_station/protocols/lacrosse_tx.c b/lib/subghz/protocols/lacrosse_tx.c similarity index 99% rename from applications/external/weather_station/protocols/lacrosse_tx.c rename to lib/subghz/protocols/lacrosse_tx.c index f4b850d76..316ed7aaf 100644 --- a/applications/external/weather_station/protocols/lacrosse_tx.c +++ b/lib/subghz/protocols/lacrosse_tx.c @@ -96,9 +96,9 @@ const SubGhzProtocolEncoder ws_protocol_lacrosse_tx_encoder = { const SubGhzProtocol ws_protocol_lacrosse_tx = { .name = WS_PROTOCOL_LACROSSE_TX_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather, .decoder = &ws_protocol_lacrosse_tx_decoder, .encoder = &ws_protocol_lacrosse_tx_encoder, @@ -301,9 +301,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderLaCrosse_TX* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/lacrosse_tx.h b/lib/subghz/protocols/lacrosse_tx.h similarity index 100% rename from applications/external/weather_station/protocols/lacrosse_tx.h rename to lib/subghz/protocols/lacrosse_tx.h diff --git a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.c b/lib/subghz/protocols/lacrosse_tx141thbv2.c similarity index 98% rename from applications/external/weather_station/protocols/lacrosse_tx141thbv2.c rename to lib/subghz/protocols/lacrosse_tx141thbv2.c index f2fddd40c..98f7d6343 100644 --- a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.c +++ b/lib/subghz/protocols/lacrosse_tx141thbv2.c @@ -74,9 +74,10 @@ const SubGhzProtocolEncoder ws_protocol_lacrosse_tx141thbv2_encoder = { const SubGhzProtocol ws_protocol_lacrosse_tx141thbv2 = { .name = WS_PROTOCOL_LACROSSE_TX141THBV2_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_lacrosse_tx141thbv2_decoder, .encoder = &ws_protocol_lacrosse_tx141thbv2_encoder, @@ -276,9 +277,9 @@ SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/lacrosse_tx141thbv2.h b/lib/subghz/protocols/lacrosse_tx141thbv2.h similarity index 100% rename from applications/external/weather_station/protocols/lacrosse_tx141thbv2.h rename to lib/subghz/protocols/lacrosse_tx141thbv2.h diff --git a/applications/external/weather_station/protocols/nexus_th.c b/lib/subghz/protocols/nexus_th.c similarity index 66% rename from applications/external/weather_station/protocols/nexus_th.c rename to lib/subghz/protocols/nexus_th.c index 14ba8b273..4ff687ecb 100644 --- a/applications/external/weather_station/protocols/nexus_th.c +++ b/lib/subghz/protocols/nexus_th.c @@ -25,13 +25,14 @@ * - humidity is 8 bits * The sensors can be bought at Clas Ohlsen (Nexus) and Pearl (infactory/FreeTec). * + * Generate test files: https://htotoo.github.io/FlipperSUBGenerator/nexus-th-generator/index.html */ #define NEXUS_TH_CONST_DATA 0b1111 static const SubGhzBlockConst ws_protocol_nexus_th_const = { - .te_short = 500, - .te_long = 2000, + .te_short = 490, + .te_long = 1980, .te_delta = 150, .min_count_bit_for_found = 36, }; @@ -56,37 +57,26 @@ typedef enum { Nexus_THDecoderStepCheckDuration, } Nexus_THDecoderStep; -const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder = { - .alloc = ws_protocol_decoder_nexus_th_alloc, - .free = ws_protocol_decoder_nexus_th_free, +void* ws_protocol_encoder_nexus_th_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolEncoderNexus_TH* instance = malloc(sizeof(WSProtocolEncoderNexus_TH)); - .feed = ws_protocol_decoder_nexus_th_feed, - .reset = ws_protocol_decoder_nexus_th_reset, + instance->base.protocol = &ws_protocol_nexus_th; + instance->generic.protocol_name = instance->base.protocol->name; - .get_hash_data = ws_protocol_decoder_nexus_th_get_hash_data, - .serialize = ws_protocol_decoder_nexus_th_serialize, - .deserialize = ws_protocol_decoder_nexus_th_deserialize, - .get_string = ws_protocol_decoder_nexus_th_get_string, -}; + instance->encoder.repeat = 12; + instance->encoder.size_upload = ws_protocol_nexus_th_const.min_count_bit_for_found * 2 + 2; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} -const SubGhzProtocolEncoder ws_protocol_nexus_th_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - -const SubGhzProtocol ws_protocol_nexus_th = { - .name = WS_PROTOCOL_NEXUS_TH_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, - - .decoder = &ws_protocol_nexus_th_decoder, - .encoder = &ws_protocol_nexus_th_encoder, -}; +void ws_protocol_encoder_nexus_th_free(void* context) { + furi_assert(context); + WSProtocolEncoderNexus_TH* instance = context; + free(instance->encoder.upload); + free(instance); +} void* ws_protocol_decoder_nexus_th_alloc(SubGhzEnvironment* environment) { UNUSED(environment); @@ -119,6 +109,93 @@ static bool ws_protocol_nexus_th_check(WSProtocolDecoderNexus_TH* instance) { return true; } +static bool ws_protocol_encoder_nexus_th_get_upload(WSProtocolEncoderNexus_TH* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(!bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_nexus_th_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_nexus_th_const.te_short * 2); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_nexus_th_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_nexus_th_const.te_short * 4); + } + } + + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)ws_protocol_nexus_th_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)ws_protocol_nexus_th_const.te_short * 8); + + return true; +} + +SubGhzProtocolStatus + ws_protocol_encoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolEncoderNexus_TH* instance = context; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = ws_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + if((instance->generic.data_count_bit > + ws_protocol_nexus_th_const.min_count_bit_for_found + 1)) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 12); + + if(!ws_protocol_encoder_nexus_th_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } + instance->encoder.is_running = true; + } while(false); + + return ret; +} + +LevelDuration ws_protocol_encoder_nexus_th_yield(void* context) { + WSProtocolEncoderNexus_TH* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + return ret; +} + +void ws_protocol_encoder_nexus_th_stop(void* context) { + WSProtocolEncoderNexus_TH* instance = context; + instance->encoder.is_running = false; +} + /** * Analysis of received data * @param instance Pointer to a WSBlockGeneric* instance @@ -236,9 +313,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderNexus_TH* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", @@ -252,3 +329,36 @@ void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) (double)instance->generic.temp, instance->generic.humidity); } + +const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder = { + .alloc = ws_protocol_decoder_nexus_th_alloc, + .free = ws_protocol_decoder_nexus_th_free, + + .feed = ws_protocol_decoder_nexus_th_feed, + .reset = ws_protocol_decoder_nexus_th_reset, + + .get_hash_data = ws_protocol_decoder_nexus_th_get_hash_data, + .serialize = ws_protocol_decoder_nexus_th_serialize, + .deserialize = ws_protocol_decoder_nexus_th_deserialize, + .get_string = ws_protocol_decoder_nexus_th_get_string, +}; + +const SubGhzProtocolEncoder ws_protocol_nexus_th_encoder = { + .alloc = ws_protocol_encoder_nexus_th_alloc, + .free = ws_protocol_encoder_nexus_th_free, + + .deserialize = ws_protocol_encoder_nexus_th_deserialize, + .stop = ws_protocol_encoder_nexus_th_stop, + .yield = ws_protocol_encoder_nexus_th_yield, +}; + +const SubGhzProtocol ws_protocol_nexus_th = { + .name = WS_PROTOCOL_NEXUS_TH_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &ws_protocol_nexus_th_decoder, + .encoder = &ws_protocol_nexus_th_encoder, +}; diff --git a/applications/external/weather_station/protocols/nexus_th.h b/lib/subghz/protocols/nexus_th.h similarity index 100% rename from applications/external/weather_station/protocols/nexus_th.h rename to lib/subghz/protocols/nexus_th.h diff --git a/applications/external/weather_station/protocols/oregon2.c b/lib/subghz/protocols/oregon2.c similarity index 98% rename from applications/external/weather_station/protocols/oregon2.c rename to lib/subghz/protocols/oregon2.c index 313748ccf..ebba869f1 100644 --- a/applications/external/weather_station/protocols/oregon2.c +++ b/lib/subghz/protocols/oregon2.c @@ -387,7 +387,7 @@ void ws_protocol_decoder_oregon2_get_string(void* context, FuriString* output) { furi_string_cat_printf( output, "%s\r\n" - "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n", + "ID: 0x%04lX, ch: %d,\r\nbat: %d, rc: 0x%02lX\r\n", instance->generic.protocol_name, instance->generic.id, instance->generic.channel, @@ -422,8 +422,9 @@ const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = { const SubGhzProtocol ws_protocol_oregon2 = { .name = WS_PROTOCOL_OREGON2_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Weather | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_oregon2_decoder, }; diff --git a/applications/external/weather_station/protocols/oregon2.h b/lib/subghz/protocols/oregon2.h similarity index 100% rename from applications/external/weather_station/protocols/oregon2.h rename to lib/subghz/protocols/oregon2.h diff --git a/applications/external/weather_station/protocols/oregon3.c b/lib/subghz/protocols/oregon3.c similarity index 98% rename from applications/external/weather_station/protocols/oregon3.c rename to lib/subghz/protocols/oregon3.c index bd35c2fd5..67ddec252 100644 --- a/applications/external/weather_station/protocols/oregon3.c +++ b/lib/subghz/protocols/oregon3.c @@ -323,7 +323,7 @@ void ws_protocol_decoder_oregon3_get_string(void* context, FuriString* output) { furi_string_cat_printf( output, "%s\r\n" - "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n", + "ID: 0x%04lX, ch: %d,\r\nbat: %d, rc: 0x%02lX\r\n", instance->generic.protocol_name, instance->generic.id, instance->generic.channel, @@ -358,8 +358,9 @@ const SubGhzProtocolDecoder ws_protocol_oregon3_decoder = { const SubGhzProtocol ws_protocol_oregon3 = { .name = WS_PROTOCOL_OREGON3_NAME, - .type = SubGhzProtocolWeatherStation, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Weather | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_oregon3_decoder, }; diff --git a/applications/external/weather_station/protocols/oregon3.h b/lib/subghz/protocols/oregon3.h similarity index 100% rename from applications/external/weather_station/protocols/oregon3.h rename to lib/subghz/protocols/oregon3.h diff --git a/applications/external/weather_station/protocols/oregon_v1.c b/lib/subghz/protocols/oregon_v1.c similarity index 97% rename from applications/external/weather_station/protocols/oregon_v1.c rename to lib/subghz/protocols/oregon_v1.c index 03215bbf5..b68cdf170 100644 --- a/applications/external/weather_station/protocols/oregon_v1.c +++ b/lib/subghz/protocols/oregon_v1.c @@ -30,9 +30,9 @@ * - u: unknown; * - b: battery low; flag to indicate low battery voltage * - s: temperature sign - * - T: BCD, Temperature; in °C * 10 - * - t: BCD, Temperature; in °C * 1 - * - z: BCD, Temperature; in °C * 0.1 + * - T: BCD, Temperature; in �C * 10 + * - t: BCD, Temperature; in �C * 1 + * - z: BCD, Temperature; in �C * 0.1 * - c: Channel 00=CH1, 01=CH2, 10=CH3 * */ @@ -93,9 +93,10 @@ const SubGhzProtocolEncoder ws_protocol_oregon_v1_encoder = { const SubGhzProtocol ws_protocol_oregon_v1 = { .name = WS_PROTOCOL_OREGON_V1_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_oregon_v1_decoder, .encoder = &ws_protocol_oregon_v1_encoder, @@ -303,9 +304,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderOregon_V1* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/oregon_v1.h b/lib/subghz/protocols/oregon_v1.h similarity index 100% rename from applications/external/weather_station/protocols/oregon_v1.h rename to lib/subghz/protocols/oregon_v1.h diff --git a/applications/external/pocsag_pager/protocols/pcsg_generic.c b/lib/subghz/protocols/pcsg_generic.c similarity index 99% rename from applications/external/pocsag_pager/protocols/pcsg_generic.c rename to lib/subghz/protocols/pcsg_generic.c index 5425fd512..99ff1f665 100644 --- a/applications/external/pocsag_pager/protocols/pcsg_generic.c +++ b/lib/subghz/protocols/pcsg_generic.c @@ -1,7 +1,6 @@ #include "pcsg_generic.h" #include #include -#include "../helpers/pocsag_pager_types.h" #define TAG "PCSGBlockGeneric" diff --git a/applications/external/pocsag_pager/protocols/pcsg_generic.h b/lib/subghz/protocols/pcsg_generic.h similarity index 94% rename from applications/external/pocsag_pager/protocols/pcsg_generic.h rename to lib/subghz/protocols/pcsg_generic.h index 126b54ffe..3578c1d15 100644 --- a/applications/external/pocsag_pager/protocols/pcsg_generic.h +++ b/lib/subghz/protocols/pcsg_generic.h @@ -13,6 +13,9 @@ extern "C" { #endif +#define PCSG_KEY_FILE_VERSION 1 +#define PCSG_KEY_FILE_TYPE "Flipper SubGhz Key File" + typedef struct PCSGBlockGeneric PCSGBlockGeneric; struct PCSGBlockGeneric { diff --git a/applications/external/pocsag_pager/protocols/pocsag.c b/lib/subghz/protocols/pocsag.c similarity index 98% rename from applications/external/pocsag_pager/protocols/pocsag.c rename to lib/subghz/protocols/pocsag.c index 0296a70a7..e5cec9068 100644 --- a/applications/external/pocsag_pager/protocols/pocsag.c +++ b/lib/subghz/protocols/pocsag.c @@ -364,6 +364,14 @@ const SubGhzProtocolDecoder subghz_protocol_pocsag_decoder = { .get_string = subhz_protocol_decoder_pocsag_get_string, }; +const SubGhzProtocolEncoder subghz_protocol_pocsag_encoder = { + .alloc = NULL, + .free = NULL, + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + const SubGhzProtocol subghz_protocol_pocsag = { .name = SUBGHZ_PROTOCOL_POCSAG_NAME, .type = SubGhzProtocolTypeStatic, @@ -371,4 +379,5 @@ const SubGhzProtocol subghz_protocol_pocsag = { SubGhzProtocolFlag_Load, .decoder = &subghz_protocol_pocsag_decoder, + .encoder = &subghz_protocol_pocsag_encoder, }; diff --git a/applications/external/pocsag_pager/protocols/pocsag.h b/lib/subghz/protocols/pocsag.h similarity index 100% rename from applications/external/pocsag_pager/protocols/pocsag.h rename to lib/subghz/protocols/pocsag.h diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 74244c5ff..644f5f68e 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -42,6 +42,26 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_dooya, &subghz_protocol_alutech_at_4n, &subghz_protocol_kinggates_stylo_4k, + &ws_protocol_infactory, + &ws_protocol_thermopro_tx4, + &ws_protocol_nexus_th, + &ws_protocol_gt_wt_02, + &ws_protocol_gt_wt_03, + &ws_protocol_acurite_606tx, + &ws_protocol_acurite_609txc, + &ws_protocol_lacrosse_tx, + &ws_protocol_lacrosse_tx141thbv2, + &ws_protocol_oregon2, + &ws_protocol_oregon3, + &ws_protocol_acurite_592txr, + &ws_protocol_ambient_weather, + &ws_protocol_auriol_th, + &ws_protocol_oregon_v1, + &ws_protocol_tx_8300, + &ws_protocol_wendox_w6726, + &ws_protocol_auriol_ahfl, + &subghz_protocol_pocsag, + &tpms_protocol_schrader_gg4, &subghz_protocol_bin_raw, }; diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index f1a28ac9b..74a4e4d6e 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -43,4 +43,24 @@ #include "dooya.h" #include "alutech_at_4n.h" #include "kinggates_stylo_4k.h" +#include "infactory.h" +#include "thermopro_tx4.h" +#include "nexus_th.h" +#include "gt_wt_02.h" +#include "gt_wt_03.h" +#include "acurite_606tx.h" +#include "acurite_609txc.h" +#include "lacrosse_tx.h" +#include "lacrosse_tx141thbv2.h" +#include "oregon2.h" +#include "oregon3.h" +#include "acurite_592txr.h" +#include "ambient_weather.h" +#include "auriol_hg0601a.h" +#include "oregon_v1.h" +#include "tx_8300.h" +#include "wendox_w6726.h" +#include "auriol_ahfl.h" +#include "pocsag.h" +#include "schrader_gg4.h" #include "bin_raw.h" diff --git a/lib/subghz/protocols/schrader_gg4.c b/lib/subghz/protocols/schrader_gg4.c new file mode 100644 index 000000000..49c2e48a5 --- /dev/null +++ b/lib/subghz/protocols/schrader_gg4.c @@ -0,0 +1,296 @@ +#include "schrader_gg4.h" +#include + +#define TAG "Schrader" + +// https://github.com/merbanan/rtl_433/blob/master/src/devices/schraeder.c +// https://elib.dlr.de/81155/1/TPMS_for_Trafffic_Management_purposes.pdf +// https://github.com/furrtek/portapack-havoc/issues/349 +// https://fccid.io/MRXGG4 +// https://fccid.io/MRXGG4T + +/** + * Schrader 3013/3015 MRX-GG4 + +OEM: +KIA Sportage CGA 11-SPT1504-RA +Mercedes-Benz A0009054100 + +* Frequency: 433.92MHz+-38KHz +* Modulation: ASK +* Working Temperature: -50°C to 125°C +* Tire monitoring range value: 0kPa-350kPa+-7kPa + +Examples in normal environmental conditions: +3000878456094cd0 +3000878456084ecb +3000878456074d01 + +Data layout: + * | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | + * | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | + * | SSSS SSSS | IIII IIII | IIII IIII | IIII IIII | IIII IIII | PPPP PPPP | TTTT TTTT | CCCC CCCC | + * + +- The preamble is 0b000 +- S: always 0x30 in relearn state +- I: 32 bit ID +- P: 8 bit Pressure (multiplyed by 2.5 = PSI) +- T: 8 bit Temperature (deg. C offset by 50) +- C: 8 bit Checksum (CRC8, Poly 0x7, Init 0x0) +*/ + +#define PREAMBLE 0b000 +#define PREAMBLE_BITS_LEN 3 + +static const SubGhzBlockConst tpms_protocol_schrader_gg4_const = { + .te_short = 120, + .te_long = 240, + .te_delta = 55, // 50% of te_short due to poor sensitivity + .min_count_bit_for_found = 64, +}; + +struct TPMSProtocolDecoderSchraderGG4 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + TPMSBlockGeneric generic; + + ManchesterState manchester_saved_state; + uint16_t header_count; +}; + +struct TPMSProtocolEncoderSchraderGG4 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + TPMSBlockGeneric generic; +}; + +typedef enum { + SchraderGG4DecoderStepReset = 0, + SchraderGG4DecoderStepCheckPreamble, + SchraderGG4DecoderStepDecoderData, + SchraderGG4DecoderStepSaveDuration, + SchraderGG4DecoderStepCheckDuration, +} SchraderGG4DecoderStep; + +const SubGhzProtocolDecoder tpms_protocol_schrader_gg4_decoder = { + .alloc = tpms_protocol_decoder_schrader_gg4_alloc, + .free = tpms_protocol_decoder_schrader_gg4_free, + + .feed = tpms_protocol_decoder_schrader_gg4_feed, + .reset = tpms_protocol_decoder_schrader_gg4_reset, + + .get_hash_data = tpms_protocol_decoder_schrader_gg4_get_hash_data, + .serialize = tpms_protocol_decoder_schrader_gg4_serialize, + .deserialize = tpms_protocol_decoder_schrader_gg4_deserialize, + .get_string = tpms_protocol_decoder_schrader_gg4_get_string, +}; + +const SubGhzProtocolEncoder tpms_protocol_schrader_gg4_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol tpms_protocol_schrader_gg4 = { + .name = TPMS_PROTOCOL_SCHRADER_GG4_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_TPMS | SubGhzProtocolFlag_Load | + SubGhzProtocolFlag_Save, + + .decoder = &tpms_protocol_schrader_gg4_decoder, + .encoder = &tpms_protocol_schrader_gg4_encoder, +}; + +void* tpms_protocol_decoder_schrader_gg4_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + TPMSProtocolDecoderSchraderGG4* instance = malloc(sizeof(TPMSProtocolDecoderSchraderGG4)); + instance->base.protocol = &tpms_protocol_schrader_gg4; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void tpms_protocol_decoder_schrader_gg4_free(void* context) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + free(instance); +} + +void tpms_protocol_decoder_schrader_gg4_reset(void* context) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + instance->decoder.parser_step = SchraderGG4DecoderStepReset; +} + +static bool tpms_protocol_schrader_gg4_check_crc(TPMSProtocolDecoderSchraderGG4* instance) { + uint8_t msg[] = { + instance->decoder.decode_data >> 48, + instance->decoder.decode_data >> 40, + instance->decoder.decode_data >> 32, + instance->decoder.decode_data >> 24, + instance->decoder.decode_data >> 16, + instance->decoder.decode_data >> 8}; + + uint8_t crc = subghz_protocol_blocks_crc8(msg, 6, 0x7, 0); + return (crc == (instance->decoder.decode_data & 0xFF)); +} + +/** + * Analysis of received data + * @param instance Pointer to a TPMSBlockGeneric* instance + */ +static void tpms_protocol_schrader_gg4_analyze(TPMSBlockGeneric* instance) { + instance->id = instance->data >> 24; + + // TODO locate and fix + instance->battery_low = TPMS_NO_BATT; + + instance->temperature = ((instance->data >> 8) & 0xFF) - 50; + instance->pressure = ((instance->data >> 16) & 0xFF) * 2.5 * 0.069; +} + +static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) { + bool is_long = false; + + if(DURATION_DIFF(duration, tpms_protocol_schrader_gg4_const.te_long) < + tpms_protocol_schrader_gg4_const.te_delta) { + is_long = true; + } else if( + DURATION_DIFF(duration, tpms_protocol_schrader_gg4_const.te_short) < + tpms_protocol_schrader_gg4_const.te_delta) { + is_long = false; + } else { + return ManchesterEventReset; + } + + if(level) + return is_long ? ManchesterEventLongHigh : ManchesterEventShortHigh; + else + return is_long ? ManchesterEventLongLow : ManchesterEventShortLow; +} + +void tpms_protocol_decoder_schrader_gg4_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + bool bit = false; + bool have_bit = false; + TPMSProtocolDecoderSchraderGG4* instance = context; + + // low-level bit sequence decoding + if(instance->decoder.parser_step != SchraderGG4DecoderStepReset) { + ManchesterEvent event = level_and_duration_to_event(level, duration); + + if(event == ManchesterEventReset) { + if((instance->decoder.parser_step == SchraderGG4DecoderStepDecoderData) && + instance->decoder.decode_count_bit) { + // FURI_LOG_D(TAG, "%d-%ld", level, duration); + FURI_LOG_D( + TAG, + "reset accumulated %d bits: %llx", + instance->decoder.decode_count_bit, + instance->decoder.decode_data); + } + + instance->decoder.parser_step = SchraderGG4DecoderStepReset; + } else { + have_bit = manchester_advance( + instance->manchester_saved_state, event, &instance->manchester_saved_state, &bit); + if(!have_bit) return; + + // Invert value, due to signal is Manchester II and decoder is Manchester I + bit = !bit; + } + } + + switch(instance->decoder.parser_step) { + case SchraderGG4DecoderStepReset: + // wait for start ~480us pulse + if((level) && (DURATION_DIFF(duration, tpms_protocol_schrader_gg4_const.te_long * 2) < + tpms_protocol_schrader_gg4_const.te_delta)) { + instance->decoder.parser_step = SchraderGG4DecoderStepCheckPreamble; + instance->header_count = 0; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + + // First will be short space, so set correct initial state for machine + // https://clearwater.com.au/images/rc5/rc5-state-machine.gif + instance->manchester_saved_state = ManchesterStateStart1; + } + break; + case SchraderGG4DecoderStepCheckPreamble: + if(bit != 0) { + instance->decoder.parser_step = SchraderGG4DecoderStepReset; + break; + } + + instance->header_count++; + if(instance->header_count == PREAMBLE_BITS_LEN) + instance->decoder.parser_step = SchraderGG4DecoderStepDecoderData; + break; + + case SchraderGG4DecoderStepDecoderData: + subghz_protocol_blocks_add_bit(&instance->decoder, bit); + if(instance->decoder.decode_count_bit == + tpms_protocol_schrader_gg4_const.min_count_bit_for_found) { + FURI_LOG_D(TAG, "%016llx", instance->decoder.decode_data); + if(!tpms_protocol_schrader_gg4_check_crc(instance)) { + FURI_LOG_D(TAG, "CRC mismatch drop"); + } else { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + tpms_protocol_schrader_gg4_analyze(&instance->generic); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.parser_step = SchraderGG4DecoderStepReset; + } + break; + } +} + +uint8_t tpms_protocol_decoder_schrader_gg4_get_hash_data(void* context) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +SubGhzProtocolStatus tpms_protocol_decoder_schrader_gg4_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + return tpms_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +SubGhzProtocolStatus + tpms_protocol_decoder_schrader_gg4_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + return tpms_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + tpms_protocol_schrader_gg4_const.min_count_bit_for_found); +} + +void tpms_protocol_decoder_schrader_gg4_get_string(void* context, FuriString* output) { + furi_assert(context); + TPMSProtocolDecoderSchraderGG4* instance = context; + furi_string_cat_printf( + output, + "%s\r\n" + "Id:0x%08lX\r\n" + "Bat:%d\r\n" + "Temp:%2.0f C Bar:%2.1f", + instance->generic.protocol_name, + instance->generic.id, + instance->generic.battery_low, + (double)instance->generic.temperature, + (double)instance->generic.pressure); +} diff --git a/lib/subghz/protocols/schrader_gg4.h b/lib/subghz/protocols/schrader_gg4.h new file mode 100644 index 000000000..29c2c7d00 --- /dev/null +++ b/lib/subghz/protocols/schrader_gg4.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include +#include +#include +#include "tpms_generic.h" +#include + +#define TPMS_PROTOCOL_SCHRADER_GG4_NAME "Schrader GG4" + +typedef struct TPMSProtocolDecoderSchraderGG4 TPMSProtocolDecoderSchraderGG4; +typedef struct TPMSProtocolEncoderSchraderGG4 TPMSProtocolEncoderSchraderGG4; + +extern const SubGhzProtocolDecoder tpms_protocol_schrader_gg4_decoder; +extern const SubGhzProtocolEncoder tpms_protocol_schrader_gg4_encoder; +extern const SubGhzProtocol tpms_protocol_schrader_gg4; + +/** + * Allocate TPMSProtocolDecoderSchraderGG4. + * @param environment Pointer to a SubGhzEnvironment instance + * @return TPMSProtocolDecoderSchraderGG4* pointer to a TPMSProtocolDecoderSchraderGG4 instance + */ +void* tpms_protocol_decoder_schrader_gg4_alloc(SubGhzEnvironment* environment); + +/** + * Free TPMSProtocolDecoderSchraderGG4. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + */ +void tpms_protocol_decoder_schrader_gg4_free(void* context); + +/** + * Reset decoder TPMSProtocolDecoderSchraderGG4. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + */ +void tpms_protocol_decoder_schrader_gg4_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void tpms_protocol_decoder_schrader_gg4_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + * @return hash Hash sum + */ +uint8_t tpms_protocol_decoder_schrader_gg4_get_hash_data(void* context); + +/** + * Serialize data TPMSProtocolDecoderSchraderGG4. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return status + */ +SubGhzProtocolStatus tpms_protocol_decoder_schrader_gg4_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data TPMSProtocolDecoderSchraderGG4. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return status + */ +SubGhzProtocolStatus + tpms_protocol_decoder_schrader_gg4_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a TPMSProtocolDecoderSchraderGG4 instance + * @param output Resulting text + */ +void tpms_protocol_decoder_schrader_gg4_get_string(void* context, FuriString* output); diff --git a/applications/external/weather_station/protocols/thermopro_tx4.c b/lib/subghz/protocols/thermopro_tx4.c similarity index 98% rename from applications/external/weather_station/protocols/thermopro_tx4.c rename to lib/subghz/protocols/thermopro_tx4.c index 24e883e60..351f662f7 100644 --- a/applications/external/weather_station/protocols/thermopro_tx4.c +++ b/lib/subghz/protocols/thermopro_tx4.c @@ -77,9 +77,10 @@ const SubGhzProtocolEncoder ws_protocol_thermopro_tx4_encoder = { const SubGhzProtocol ws_protocol_thermopro_tx4 = { .name = WS_PROTOCOL_THERMOPRO_TX4_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_thermopro_tx4_decoder, .encoder = &ws_protocol_thermopro_tx4_encoder, @@ -233,9 +234,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderThermoPRO_TX4* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/thermopro_tx4.h b/lib/subghz/protocols/thermopro_tx4.h similarity index 100% rename from applications/external/weather_station/protocols/thermopro_tx4.h rename to lib/subghz/protocols/thermopro_tx4.h diff --git a/lib/subghz/protocols/tpms_generic.c b/lib/subghz/protocols/tpms_generic.c new file mode 100644 index 000000000..b6776c5a3 --- /dev/null +++ b/lib/subghz/protocols/tpms_generic.c @@ -0,0 +1,227 @@ +#include "tpms_generic.h" +#include +#include + +#define TAG "TPMSBlockGeneric" + +void tpms_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str) { + const char* preset_name_temp; + if(!strcmp(preset_name, "AM270")) { + preset_name_temp = "FuriHalSubGhzPresetOok270Async"; + } else if(!strcmp(preset_name, "AM650")) { + preset_name_temp = "FuriHalSubGhzPresetOok650Async"; + } else if(!strcmp(preset_name, "FM238")) { + preset_name_temp = "FuriHalSubGhzPreset2FSKDev238Async"; + } else if(!strcmp(preset_name, "FM476")) { + preset_name_temp = "FuriHalSubGhzPreset2FSKDev476Async"; + } else { + preset_name_temp = "FuriHalSubGhzPresetCustom"; + } + furi_string_set(preset_str, preset_name_temp); +} + +SubGhzProtocolStatus tpms_block_generic_serialize( + TPMSBlockGeneric* instance, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(instance); + SubGhzProtocolStatus res = SubGhzProtocolStatusError; + FuriString* temp_str; + temp_str = furi_string_alloc(); + do { + stream_clean(flipper_format_get_raw_stream(flipper_format)); + if(!flipper_format_write_header_cstr( + flipper_format, TPMS_KEY_FILE_TYPE, TPMS_KEY_FILE_VERSION)) { + FURI_LOG_E(TAG, "Unable to add header"); + res = SubGhzProtocolStatusErrorParserHeader; + break; + } + + if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { + FURI_LOG_E(TAG, "Unable to add Frequency"); + res = SubGhzProtocolStatusErrorParserFrequency; + break; + } + + tpms_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); + if(!flipper_format_write_string_cstr( + flipper_format, "Preset", furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Unable to add Preset"); + res = SubGhzProtocolStatusErrorParserPreset; + break; + } + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!flipper_format_write_string_cstr( + flipper_format, "Custom_preset_module", "CC1101")) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + res = SubGhzProtocolStatusErrorParserCustomPreset; + break; + } + if(!flipper_format_write_hex( + flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + res = SubGhzProtocolStatusErrorParserCustomPreset; + break; + } + } + if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) { + FURI_LOG_E(TAG, "Unable to add Protocol"); + res = SubGhzProtocolStatusErrorParserProtocolName; + break; + } + + uint32_t temp_data = instance->id; + if(!flipper_format_write_uint32(flipper_format, "Id", &temp_data, 1)) { + FURI_LOG_E(TAG, "Unable to add Id"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + temp_data = instance->data_count_bit; + if(!flipper_format_write_uint32(flipper_format, "Bit", &temp_data, 1)) { + FURI_LOG_E(TAG, "Unable to add Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; + break; + } + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; + } + + if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Data"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + temp_data = instance->battery_low; + if(!flipper_format_write_uint32(flipper_format, "Batt", &temp_data, 1)) { + FURI_LOG_E(TAG, "Unable to add Battery_low"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + float temp = instance->pressure; + if(!flipper_format_write_float(flipper_format, "Pressure", &temp, 1)) { + FURI_LOG_E(TAG, "Unable to add Pressure"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + //DATE AGE set + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); + uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt); + + temp_data = curr_ts; + if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) { + FURI_LOG_E(TAG, "Unable to add timestamp"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + temp = instance->temperature; + if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) { + FURI_LOG_E(TAG, "Unable to add Temperature"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + res = SubGhzProtocolStatusOk; + } while(false); + furi_string_free(temp_str); + return res; +} + +SubGhzProtocolStatus + tpms_block_generic_deserialize(TPMSBlockGeneric* instance, FlipperFormat* flipper_format) { + furi_assert(instance); + SubGhzProtocolStatus res = SubGhzProtocolStatusError; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + if(!flipper_format_read_uint32(flipper_format, "Id", &temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Id"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + instance->id = temp_data; + + if(!flipper_format_read_uint32(flipper_format, "Bit", &temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; + break; + } + instance->data_count_bit = (uint8_t)temp_data; + + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Missing Data"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + instance->data = instance->data << 8 | key_data[i]; + } + + if(!flipper_format_read_uint32(flipper_format, "Batt", &temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Battery_low"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + instance->battery_low = (uint8_t)temp_data; + + float temp; + if(!flipper_format_read_float(flipper_format, "Pressure", &temp, 1)) { + FURI_LOG_E(TAG, "Missing Pressure"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + instance->pressure = temp; + + if(!flipper_format_read_uint32(flipper_format, "Ts", &temp_data, 1)) { + FURI_LOG_E(TAG, "Missing timestamp"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + instance->timestamp = temp_data; + + if(!flipper_format_read_float(flipper_format, "Temp", &temp, 1)) { + FURI_LOG_E(TAG, "Missing Temperature"); + res = SubGhzProtocolStatusErrorParserOthers; + break; + } + instance->temperature = temp; + + res = SubGhzProtocolStatusOk; + } while(0); + + return res; +} + +SubGhzProtocolStatus tpms_block_generic_deserialize_check_count_bit( + TPMSBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit) { + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = tpms_block_generic_deserialize(instance, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + if(instance->data_count_bit != count_bit) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + } while(false); + return ret; +} \ No newline at end of file diff --git a/lib/subghz/protocols/tpms_generic.h b/lib/subghz/protocols/tpms_generic.h new file mode 100644 index 000000000..d57815678 --- /dev/null +++ b/lib/subghz/protocols/tpms_generic.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include + +#include +#include "furi.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TPMS_KEY_FILE_VERSION 1 +#define TPMS_KEY_FILE_TYPE "Flipper SubGhz Key File" + +#define TPMS_NO_BATT 0xFF + +typedef struct TPMSBlockGeneric TPMSBlockGeneric; + +struct TPMSBlockGeneric { + const char* protocol_name; + uint64_t data; + uint8_t data_count_bit; + + uint32_t timestamp; + + uint32_t id; + uint8_t battery_low; + // bool storage; + float pressure; // bar + float temperature; // celsius +}; + +/** + * Get name preset. + * @param preset_name name preset + * @param preset_str Output name preset + */ +void tpms_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str); + +/** + * Serialize data TPMSBlockGeneric. + * @param instance Pointer to a TPMSBlockGeneric instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return status + */ +SubGhzProtocolStatus tpms_block_generic_serialize( + TPMSBlockGeneric* instance, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data TPMSBlockGeneric. + * @param instance Pointer to a TPMSBlockGeneric instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return status + */ +SubGhzProtocolStatus + tpms_block_generic_deserialize(TPMSBlockGeneric* instance, FlipperFormat* flipper_format); + +/** + * Deserialize data TPMSBlockGeneric. + * @param instance Pointer to a TPMSBlockGeneric instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param count_bit Count bit protocol + * @return status + */ +SubGhzProtocolStatus tpms_block_generic_deserialize_check_count_bit( + TPMSBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/external/weather_station/protocols/tx_8300.c b/lib/subghz/protocols/tx_8300.c similarity index 98% rename from applications/external/weather_station/protocols/tx_8300.c rename to lib/subghz/protocols/tx_8300.c index 3a06ce49d..15483a87b 100644 --- a/applications/external/weather_station/protocols/tx_8300.c +++ b/lib/subghz/protocols/tx_8300.c @@ -88,9 +88,10 @@ const SubGhzProtocolEncoder ws_protocol_tx_8300_encoder = { const SubGhzProtocol ws_protocol_tx_8300 = { .name = WS_PROTOCOL_TX_8300_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_tx_8300_decoder, .encoder = &ws_protocol_tx_8300_encoder, @@ -266,9 +267,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderTX_8300* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/tx_8300.h b/lib/subghz/protocols/tx_8300.h similarity index 100% rename from applications/external/weather_station/protocols/tx_8300.h rename to lib/subghz/protocols/tx_8300.h diff --git a/applications/external/weather_station/protocols/wendox_w6726.c b/lib/subghz/protocols/wendox_w6726.c similarity index 98% rename from applications/external/weather_station/protocols/wendox_w6726.c rename to lib/subghz/protocols/wendox_w6726.c index 2fbe961f7..191adc7bf 100644 --- a/applications/external/weather_station/protocols/wendox_w6726.c +++ b/lib/subghz/protocols/wendox_w6726.c @@ -82,9 +82,10 @@ const SubGhzProtocolEncoder ws_protocol_wendox_w6726_encoder = { const SubGhzProtocol ws_protocol_wendox_w6726 = { .name = WS_PROTOCOL_WENDOX_W6726_NAME, - .type = SubGhzProtocolWeatherStation, + .type = SubGhzProtocolTypeStatic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | - SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Weather | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, .decoder = &ws_protocol_wendox_w6726_decoder, .encoder = &ws_protocol_wendox_w6726_encoder, @@ -281,9 +282,9 @@ SubGhzProtocolStatus void ws_protocol_decoder_wendox_w6726_get_string(void* context, FuriString* output) { furi_assert(context); WSProtocolDecoderWendoxW6726* instance = context; - furi_string_printf( + furi_string_cat_printf( output, - "%s %dbit\r\n" + "%s\r\n%dbit\r\n" "Key:0x%lX%08lX\r\n" "Sn:0x%lX Ch:%d Bat:%d\r\n" "Temp:%3.1f C Hum:%d%%", diff --git a/applications/external/weather_station/protocols/wendox_w6726.h b/lib/subghz/protocols/wendox_w6726.h similarity index 100% rename from applications/external/weather_station/protocols/wendox_w6726.h rename to lib/subghz/protocols/wendox_w6726.h diff --git a/applications/external/weather_station/protocols/ws_generic.c b/lib/subghz/protocols/ws_generic.c similarity index 99% rename from applications/external/weather_station/protocols/ws_generic.c rename to lib/subghz/protocols/ws_generic.c index 026856a9e..c3483dadd 100644 --- a/applications/external/weather_station/protocols/ws_generic.c +++ b/lib/subghz/protocols/ws_generic.c @@ -1,7 +1,7 @@ #include "ws_generic.h" #include #include -#include "../helpers/weather_station_types.h" +//#include "../helpers/weather_station_types.h" #define TAG "WSBlockGeneric" diff --git a/applications/external/weather_station/protocols/ws_generic.h b/lib/subghz/protocols/ws_generic.h similarity index 96% rename from applications/external/weather_station/protocols/ws_generic.h rename to lib/subghz/protocols/ws_generic.h index ff047fae6..288a4b9b3 100644 --- a/applications/external/weather_station/protocols/ws_generic.h +++ b/lib/subghz/protocols/ws_generic.h @@ -21,6 +21,9 @@ extern "C" { #define WS_NO_BTN 0xFF #define WS_NO_TEMPERATURE -273.0f +#define WS_KEY_FILE_VERSION 1 +#define WS_KEY_FILE_TYPE "Flipper SubGhz Key File" + typedef struct WSBlockGeneric WSBlockGeneric; struct WSBlockGeneric { diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 8999e1d54..2e9e06ac2 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -108,7 +108,6 @@ typedef enum { SubGhzProtocolTypeStatic, SubGhzProtocolTypeDynamic, SubGhzProtocolTypeRAW, - SubGhzProtocolWeatherStation, SubGhzProtocolCustom, SubGhzProtocolTypeBinRAW, } SubGhzProtocolType; @@ -129,6 +128,8 @@ typedef enum { SubGhzProtocolFlag_AutoAlarms = (1 << 12), SubGhzProtocolFlag_Magellan = (1 << 13), SubGhzProtocolFlag_Princeton = (1 << 14), + SubGhzProtocolFlag_Weather = (1 << 15), + SubGhzProtocolFlag_TPMS = (1 << 16), } SubGhzProtocolFlag; struct SubGhzProtocol {