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 a6d8edab1..f16508c2c 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, @@ -280,6 +282,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); } @@ -439,6 +448,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/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index d3e45c34e..724c7c572 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 1st Sept, 2023 -# Last Checked 14th Sept, 2023 +# Last Checked 1st Oct, 2023 # name: Power type: parsed diff --git a/assets/resources/infrared/assets/fans.ir b/assets/resources/infrared/assets/fans.ir index e560e1c78..938bc96a6 100644 --- a/assets/resources/infrared/assets/fans.ir +++ b/assets/resources/infrared/assets/fans.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -#Last Updated 14th Sept, 2023 -#Last Checked 14th Sept, 2023 +#Last Updated 1st Oct, 2023 +#Last Checked 1st Oct, 2023 # name: Power type: raw @@ -1995,3 +1995,111 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 2280 776 785 1565 783 796 782 790 783 1549 783 810 752 805 752 800 752 858 752 830 752 826 776 797 775 793 774 789 773 810 747 805 747 102605 2223 832 752 1595 753 825 752 820 752 1581 752 811 751 806 751 802 750 860 750 833 775 804 773 799 773 795 773 790 773 785 772 780 773 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4612 4435 543 1461 544 1460 545 1461 544 1460 543 1462 518 1487 518 2441 516 1513 491 1513 492 2465 492 1513 516 2441 516 1488 516 1489 515 2443 514 1492 514 1485 4580 4467 513 1492 513 1492 513 1492 513 1491 514 1492 513 1492 513 2445 513 1492 513 1492 513 2445 513 1492 513 2445 513 1492 513 1492 513 2445 513 1493 513 14064 9205 2275 513 +# +name: Speed_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4611 4435 544 1460 545 1460 546 1459 546 1460 519 1487 517 1487 518 2440 518 1488 517 1488 516 1512 517 2440 517 1488 516 1488 516 1489 515 2444 513 2445 514 1485 4581 4467 513 1492 513 1492 513 1492 513 1492 513 1492 513 1492 513 2444 514 1492 513 1491 514 1492 513 2445 513 1492 513 1492 513 1492 513 2444 513 2446 513 14066 9203 2275 513 +# +name: Speed_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4611 4434 545 1460 545 1459 546 1457 548 1458 521 1485 520 1485 545 2413 544 1462 542 2439 518 1487 517 1489 515 2444 512 1493 512 1493 512 1493 512 2446 512 1486 4581 4470 512 1493 511 1493 512 1493 512 1493 512 1493 512 1493 512 2446 511 1493 511 2446 512 1493 512 1493 512 2446 512 1493 512 1494 511 1493 512 2447 512 14071 9203 2279 511 +# +name: Timer +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4608 4436 545 1458 547 1458 547 1458 547 1458 521 1484 521 1485 520 2439 544 1461 544 2440 518 1487 517 2441 516 1489 515 2444 513 1493 512 1492 513 1494 512 1486 4577 4471 512 1493 512 1493 512 1493 512 1492 513 1493 512 1493 512 2446 512 1493 512 2446 512 1493 512 2446 512 1493 512 2446 512 1493 512 1493 512 1494 512 14051 9198 2279 512 +# +name: Rotate +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4605 4437 544 1460 545 1459 546 1458 546 1459 520 1485 520 1486 545 2414 543 1487 517 1488 515 1489 515 1491 513 2446 512 2446 511 2446 512 1493 512 1494 511 1487 4573 4472 511 1493 511 1493 511 1493 511 1493 512 1494 510 1494 511 2446 511 1493 511 1494 511 1494 510 1493 511 2447 511 2446 511 2446 511 1494 511 1495 511 14064 9191 2281 510 +# +name: Mode +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 4617 4436 544 1459 545 1458 545 1458 546 1458 520 1485 519 1485 545 2413 544 1462 542 1486 517 2440 515 2442 513 1492 512 1492 513 2444 512 1492 512 1493 513 1485 4582 4469 512 1493 512 1492 512 1492 512 1493 511 1493 512 1492 512 2445 511 1493 511 1493 511 2445 512 2446 511 1493 511 1493 511 2445 511 1493 511 1494 511 14048 9216 2280 512 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9220 4459 632 565 628 539 628 539 627 540 626 542 624 545 622 548 619 571 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 1652 596 571 596 571 596 572 595 1652 596 571 596 571 596 571 596 572 595 1652 596 1652 596 1653 595 571 596 1652 596 39508 9197 2229 595 96159 9231 2229 596 +# +name: Speed_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9244 4432 633 564 629 538 630 538 629 539 627 540 626 542 624 570 598 547 620 1651 597 1651 597 1651 597 1651 597 1651 597 1651 597 1651 598 1651 597 1651 597 1651 597 1651 597 570 597 570 597 570 597 570 597 570 597 570 597 570 597 570 598 1651 597 1651 597 1651 597 1651 597 1652 596 39509 9207 2227 597 +# +name: Speed_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9223 4461 632 565 628 540 627 540 626 541 625 542 624 545 622 547 621 571 597 1629 620 1652 597 1653 595 1653 596 1653 596 1653 596 1653 596 1653 596 572 596 572 595 1653 596 1653 595 572 595 572 596 572 595 572 595 1653 596 1653 596 572 595 572 595 1653 596 1653 595 1653 596 1653 595 39519 9204 2229 596 +# +name: Timer +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9227 4459 634 564 629 539 629 538 629 539 627 541 625 543 624 570 598 571 597 1652 597 1652 597 1652 597 1652 597 1652 597 1652 597 1652 597 1652 597 1652 597 571 597 571 596 1652 597 571 596 571 597 571 596 571 597 571 596 1652 597 1652 597 571 597 1652 597 1652 597 1653 596 1653 596 39523 9207 2229 596 +# +name: Rotate +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9223 4459 633 564 629 538 629 538 628 539 627 541 624 544 622 570 597 570 597 1651 597 1651 597 1651 597 1651 598 1651 597 1651 597 1651 597 1651 597 570 597 1651 597 1651 597 1651 597 1651 597 570 598 1651 597 570 597 1651 597 570 597 570 597 570 597 570 597 1652 596 570 597 1652 596 39519 9202 2226 597 +# +name: Mode +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9241 4434 633 565 602 565 628 539 628 539 627 540 626 542 624 545 622 547 620 1628 620 1629 619 1629 619 1652 596 1653 595 1629 619 1652 596 1653 595 571 596 1653 595 571 596 571 596 572 595 571 596 1653 595 572 595 1653 595 571 596 1653 595 1653 595 1653 595 1653 596 572 595 1653 595 39519 9226 2229 597 +# +name: Power +type: raw +frequency: 40000 +duty_cycle: 0.4 +data: 20592 6864 2288 9152 11440 2288 2288 6864 2288 2288 2288 13728 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 1328 375 1304 375 460 1196 1327 379 1299 379 430 1221 459 1221 458 1222 483 1197 483 1198 481 1222 1299 7068 1297 382 1297 382 453 1227 1296 382 1297 382 453 1227 453 1228 452 1228 452 1227 453 1228 452 1228 1296 7322 1295 383 1296 383 452 1228 1296 383 1296 383 452 1228 452 1228 452 1228 452 1228 452 1228 452 1228 1296 7070 1295 383 1296 384 451 1228 1296 383 1296 383 452 1228 452 1229 451 1228 451 1229 451 1228 451 1229 1295 +# +name: Speed_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 1327 373 1306 377 459 1194 1329 373 1305 377 1276 402 433 1219 486 1194 486 1195 484 1219 1302 379 1299 7067 1299 380 1299 381 455 1224 1299 381 1298 381 1298 381 455 1225 455 1225 455 1225 455 1225 1298 381 1298 7344 1298 381 1299 381 455 1225 1298 381 1298 381 1298 381 455 1225 455 1225 455 1225 455 1226 1298 381 1298 7069 1298 382 1298 382 454 1225 1298 382 1298 382 1298 382 454 1226 454 1226 454 1226 454 1226 1297 382 1297 +# +name: Speed_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 1330 377 1302 377 459 1193 1330 376 1303 376 1277 401 435 1218 487 1194 486 1194 1329 377 1299 380 456 7911 1299 380 1299 380 456 1225 1299 380 1299 380 1299 380 456 1224 456 1225 455 1225 1298 381 1299 380 456 8149 1299 381 1298 381 455 1225 1299 380 1299 381 1299 381 455 1225 455 1225 455 1226 1298 381 1299 381 455 7913 1298 381 1299 381 455 1226 1298 381 1299 381 1298 382 454 1225 455 1226 454 1226 1298 382 1298 381 455 +# +name: Rotate +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 1329 373 1306 377 459 1193 1330 377 1302 377 1277 402 434 1219 485 1195 1329 377 1300 379 456 1224 455 7911 1299 381 1298 381 455 1224 1299 380 1299 381 1298 381 455 1225 455 1225 1299 380 1299 381 455 1225 455 8165 1298 381 1299 381 455 1225 1299 381 1299 381 1298 381 455 1225 455 1226 1298 381 1299 381 455 1225 455 7913 1298 381 1298 381 455 1226 1297 381 1298 382 1297 382 454 1226 454 1226 1297 382 1298 382 454 1226 454 +# +name: Timer +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 1330 376 1303 376 460 1192 1331 376 1302 376 459 1191 463 1217 462 1218 1331 376 459 1195 484 1219 460 7907 1300 379 1300 380 456 1223 1300 380 1300 380 456 1224 456 1224 456 1224 1299 380 456 1224 456 1224 456 8166 1299 380 1299 380 456 1224 1299 380 1299 380 456 1224 456 1224 455 1224 1299 380 456 1224 455 1224 456 7909 1299 380 1299 380 455 1224 1299 380 1299 380 456 1224 455 1225 455 1225 1298 381 455 1225 454 1225 455 diff --git a/assets/resources/infrared/assets/projectors.ir b/assets/resources/infrared/assets/projectors.ir index 46e6abd7d..2fef79ee4 100644 --- a/assets/resources/infrared/assets/projectors.ir +++ b/assets/resources/infrared/assets/projectors.ir @@ -1,9 +1,9 @@ Filetype: IR library file Version: 1 -# Last Updated 14th Sept, 2023 -# Last Checked 14th Sept, 2023 -# -# TEMPORARY POWER FIX EDITION (All power buttons duplicated for a double press) +# Last Updated 1st Oct, 2023 +# Last Checked 1st Oct, 2023 +# +# TEMP FIX FOR POWER # # ON name: Power @@ -85,18 +85,18 @@ address: 08 13 00 00 command: 87 78 00 00 # name: Power -type: parsed -protocol: NECext -address: 08 13 00 00 -command: 87 78 00 00 -# -name: Power type: raw frequency: 38000 duty_cycle: 0.330000 data: 9055 4338 672 1551 669 1553 618 1603 619 481 617 482 616 481 617 507 591 1605 645 479 619 1577 645 1578 644 1578 644 479 619 480 618 1581 641 480 617 1605 617 1606 616 1606 615 483 615 1608 614 484 614 484 614 484 614 484 614 484 614 484 614 1609 614 484 614 1609 614 1609 613 1609 613 40058 9000 2068 614 95467 9022 2068 614 # name: Power +type: parsed +protocol: NECext +address: 08 13 00 00 +command: 87 78 00 00 +# +name: Power type: raw frequency: 38000 duty_cycle: 0.330000 @@ -150,18 +150,19 @@ protocol: NEC address: 02 00 00 00 command: 1D 00 00 00 # -name: Power -type: parsed -protocol: NEC -address: 02 00 00 00 -command: 1D 00 00 00 -# # ON name: Power type: raw frequency: 38000 duty_cycle: 0.330000 data: 9096 4436 620 505 647 478 648 501 623 1599 647 1624 623 502 623 503 621 504 619 1628 618 507 617 507 617 1630 617 508 616 1630 617 1630 617 1631 616 508 616 508 617 508 616 1631 616 508 617 508 617 508 616 508 616 1630 616 1630 616 1631 616 508 616 1630 617 1630 617 1630 617 1631 617 509 616 508 616 509 616 509 616 509 616 509 615 509 616 508 617 1631 616 1631 615 1631 616 1631 616 1631 616 1631 616 1631 615 1631 616 14435 9093 2186 615 96359 9095 2184 617 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 1D 00 00 00 +# # ON name: Power type: raw @@ -227,7 +228,19 @@ name: Power type: raw frequency: 38000 duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 data: 3522 1701 472 426 444 1269 472 426 444 426 443 427 443 427 443 426 444 427 443 426 444 427 442 428 441 429 440 431 438 1304 437 433 437 433 438 433 437 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1305 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 459 411 459 411 459 411 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 459 411 459 411 1330 411 1330 411 460 410 1330 411 1330 411 1331 410 1330 411 74392 3516 1736 436 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 435 435 1305 436 435 435 435 435 1306 435 435 435 435 435 435 435 436 434 436 434 436 434 435 435 436 434 436 434 436 434 1330 411 1331 410 1330 411 1330 411 1330 411 459 411 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 435 436 434 436 1306 435 435 435 435 435 1306 435 435 435 435 435 435 435 435 435 435 435 436 434 436 434 435 435 436 434 435 435 1306 435 1330 411 1307 434 1331 410 1308 433 436 434 436 434 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 435 435 434 436 434 436 434 436 434 436 434 436 1306 435 435 435 435 435 435 435 1306 435 435 435 436 434 1306 435 435 435 436 434 436 434 435 435 436 434 436 434 460 410 460 410 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 434 436 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 435 435 435 435 434 436 1306 435 434 436 435 435 435 435 1306 435 436 434 435 435 1306 435 435 435 436 434 436 434 436 434 436 434 460 410 437 433 459 411 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3514 1736 437 434 436 1304 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 435 435 434 436 434 436 435 435 434 436 1305 436 435 435 435 435 435 435 1306 435 435 435 435 435 1306 435 435 435 436 434 435 435 459 411 436 434 435 435 459 411 459 411 459 411 459 411 1330 411 1306 435 1330 411 1330 411 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 # name: Vol_up type: raw @@ -252,18 +265,18 @@ type: parsed protocol: NECext address: 83 F4 00 00 command: 4F B0 00 00 -# ON -name: Power -type: parsed -protocol: NECext -address: 83 F4 00 00 -command: 4F B0 00 00 # name: Power type: parsed protocol: NECext address: 80 19 00 00 command: 10 EF 00 00 +# ON +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4F B0 00 00 # name: Power type: parsed @@ -291,18 +304,6 @@ command: 51 00 00 00 # name: Power type: parsed -protocol: NEC -address: 80 00 00 00 -command: 51 00 00 00 -# -name: Power -type: parsed -protocol: NECext -address: 40 40 00 00 -command: 0A F5 00 00 -# -name: Power -type: parsed protocol: NECext address: 40 40 00 00 command: 0A F5 00 00 @@ -315,6 +316,18 @@ command: 4E B1 00 00 # name: Power type: parsed +protocol: NEC +address: 80 00 00 00 +command: 51 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 40 40 00 00 +command: 0A F5 00 00 +# +name: Power +type: parsed protocol: NECext address: 00 30 00 00 command: 4E B1 00 00 @@ -406,14 +419,14 @@ command: 0B F4 00 00 name: Power type: parsed protocol: NECext -address: 84 F4 00 00 -command: 0B F4 00 00 +address: 33 00 00 00 +command: 00 FF 00 00 # name: Power type: parsed protocol: NECext -address: 33 00 00 00 -command: 00 FF 00 00 +address: 84 F4 00 00 +command: 0B F4 00 00 # name: Power type: parsed @@ -497,13 +510,13 @@ name: Power type: parsed protocol: NEC address: 32 00 00 00 -command: 02 00 00 00 +command: 2E 00 00 00 # name: Power type: parsed protocol: NEC address: 32 00 00 00 -command: 2E 00 00 00 +command: 02 00 00 00 # name: Power type: parsed @@ -587,13 +600,13 @@ name: Power type: parsed protocol: NEC address: 31 00 00 00 -command: 91 00 00 00 +command: 90 00 00 00 # name: Power type: parsed protocol: NEC address: 31 00 00 00 -command: 90 00 00 00 +command: 91 00 00 00 # name: Power type: parsed @@ -652,18 +665,6 @@ command: 00 00 00 00 name: Power type: parsed protocol: NECext -address: 30 00 00 00 -command: 00 00 00 00 -# -name: Power -type: parsed -protocol: NECext -address: 87 4E 00 00 -command: 0D 00 00 00 -# -name: Power -type: parsed -protocol: NECext address: 87 4E 00 00 command: 0D 00 00 00 # @@ -674,6 +675,18 @@ duty_cycle: 0.330000 data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595 # name: Power +type: parsed +protocol: NECext +address: 30 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 0D 00 00 00 +# +name: Power type: raw frequency: 38000 duty_cycle: 0.330000 @@ -714,18 +727,18 @@ type: parsed protocol: NECext address: 83 F4 00 00 command: 4E B1 00 00 -# OFF -name: Power -type: parsed -protocol: NECext -address: 83 F4 00 00 -command: 4E B1 00 00 # name: Power type: parsed protocol: NEC address: 03 00 00 00 command: 1D 00 00 00 +# OFF +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4E B1 00 00 # name: Power type: parsed @@ -750,18 +763,18 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 -# OFF -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 # name: Power type: parsed protocol: Samsung32 address: 07 00 00 00 command: E6 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 # name: Power type: parsed @@ -1041,18 +1054,18 @@ command: 81 00 00 00 # name: Power type: parsed -protocol: NEC -address: 31 00 00 00 -command: 81 00 00 00 -# -name: Power -type: parsed protocol: NECext address: 83 F4 00 00 command: 17 E8 00 00 # name: Power type: parsed +protocol: NEC +address: 31 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed protocol: NECext address: 83 F4 00 00 command: 17 E8 00 00 @@ -1269,18 +1282,18 @@ command: 40 00 00 00 # name: Power type: parsed -protocol: NEC -address: 01 00 00 00 -command: 40 00 00 00 -# -name: Power -type: parsed protocol: NECext address: 00 BD 00 00 command: 01 FE 00 00 # name: Power type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Power +type: parsed protocol: NECext address: 00 BD 00 00 command: 01 FE 00 00 @@ -1464,3 +1477,21 @@ type: raw frequency: 38000 duty_cycle: 0.33 data: 353 1742 355 693 355 1742 355 1742 355 693 355 1744 353 694 354 1743 354 693 355 1743 354 694 354 693 355 694 354 1742 355 695 353 43687 354 1743 354 696 352 1744 353 1744 353 694 354 695 353 1742 355 694 354 1743 354 694 354 1743 354 1742 355 1742 355 694 354 1744 353 41606 351 1745 352 696 352 1746 351 1746 351 697 351 1747 350 696 352 1745 352 698 350 1746 351 698 350 696 352 698 350 1746 351 699 349 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 02 00 00 00 +# +name: Mute +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: D1 00 00 00 diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index 6142663b8..e7a7525fe 100755 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 1st Sept, 2023 -# Last Checked 14th Sept, 2023 +# Last Updated 1st Oct, 2023 +# Last Checked 1st Oct, 2023 # name: Power type: parsed @@ -2369,3 +2369,27 @@ type: parsed protocol: NECext address: 00 7F 00 00 command: 06 F9 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 69 69 00 00 +command: 01 FE 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 69 69 00 00 +command: 0A F5 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 69 69 00 00 +command: 0B F4 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 69 69 00 00 +command: 0E F1 00 00 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/lib/lfrfid/tools/t5577.c b/lib/lfrfid/tools/t5577.c index a931f02cf..666a5c8fe 100644 --- a/lib/lfrfid/tools/t5577.c +++ b/lib/lfrfid/tools/t5577.c @@ -110,9 +110,9 @@ void t5577_write_with_pass(LFRFIDT5577* data, uint32_t password) { t5577_start(); FURI_CRITICAL_ENTER(); for(size_t i = 0; i < data->blocks_to_write; i++) { - t5577_write_block_pass(0, false, data->block[i], true, password); + t5577_write_block_pass(i, false, data->block[i], true, password); } t5577_write_reset(); FURI_CRITICAL_EXIT(); t5577_stop(); -} \ No newline at end of file +} 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 a2e25c8ad..50d5f0ced 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -112,7 +112,6 @@ typedef enum { SubGhzProtocolTypeStatic, SubGhzProtocolTypeDynamic, SubGhzProtocolTypeRAW, - SubGhzProtocolWeatherStation, SubGhzProtocolCustom, SubGhzProtocolTypeBinRAW, } SubGhzProtocolType; @@ -133,6 +132,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 {