add app WeatherStation

OFW PR 1833 by Skorpionm
This commit is contained in:
MX 2022-10-18 19:51:44 +03:00
parent 576dab02a4
commit 84d12da45a
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
72 changed files with 4573 additions and 750 deletions

View file

@ -5,7 +5,7 @@
#include <lib/subghz/transmitter.h> #include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_keystore.h> #include <lib/subghz/subghz_keystore.h>
#include <lib/subghz/subghz_file_encoder_worker.h> #include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/subghz/protocols/registry.h> #include <lib/subghz/protocols/protocol_items.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#define TAG "SubGhz TEST" #define TAG "SubGhz TEST"
@ -413,11 +413,11 @@ MU_TEST(subghz_decoder_honeywell_wdb_test) {
"Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
} }
MU_TEST(subghz_decoder_magellen_test) { MU_TEST(subghz_decoder_magellan_test) {
mu_assert( mu_assert(
subghz_decoder_test( subghz_decoder_test(
EXT_PATH("unit_tests/subghz/magellen_raw.sub"), SUBGHZ_PROTOCOL_MAGELLEN_NAME), EXT_PATH("unit_tests/subghz/magellan_raw.sub"), SUBGHZ_PROTOCOL_MAGELLAN_NAME),
"Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n"); "Test decoder " SUBGHZ_PROTOCOL_MAGELLAN_NAME " error\r\n");
} }
MU_TEST(subghz_decoder_intertechno_v3_test) { MU_TEST(subghz_decoder_intertechno_v3_test) {
@ -545,10 +545,10 @@ MU_TEST(subghz_encoder_honeywell_wdb_test) {
"Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
} }
MU_TEST(subghz_encoder_magellen_test) { MU_TEST(subghz_encoder_magellan_test) {
mu_assert( mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellen.sub")), subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellan.sub")),
"Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n"); "Test encoder " SUBGHZ_PROTOCOL_MAGELLAN_NAME " error\r\n");
} }
MU_TEST(subghz_encoder_intertechno_v3_test) { MU_TEST(subghz_encoder_intertechno_v3_test) {
@ -600,7 +600,7 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_doitrand_test); MU_RUN_TEST(subghz_decoder_doitrand_test);
MU_RUN_TEST(subghz_decoder_phoenix_v2_test); MU_RUN_TEST(subghz_decoder_phoenix_v2_test);
MU_RUN_TEST(subghz_decoder_honeywell_wdb_test); MU_RUN_TEST(subghz_decoder_honeywell_wdb_test);
MU_RUN_TEST(subghz_decoder_magellen_test); MU_RUN_TEST(subghz_decoder_magellan_test);
MU_RUN_TEST(subghz_decoder_intertechno_v3_test); MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
MU_RUN_TEST(subghz_decoder_clemsa_test); MU_RUN_TEST(subghz_decoder_clemsa_test);
MU_RUN_TEST(subghz_decoder_oregon2_test); MU_RUN_TEST(subghz_decoder_oregon2_test);
@ -622,7 +622,7 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_doitrand_test); MU_RUN_TEST(subghz_encoder_doitrand_test);
MU_RUN_TEST(subghz_encoder_phoenix_v2_test); MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
MU_RUN_TEST(subghz_encoder_honeywell_wdb_test); MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
MU_RUN_TEST(subghz_encoder_magellen_test); MU_RUN_TEST(subghz_encoder_magellan_test);
MU_RUN_TEST(subghz_encoder_intertechno_v3_test); MU_RUN_TEST(subghz_encoder_intertechno_v3_test);
MU_RUN_TEST(subghz_encoder_clemsa_test); MU_RUN_TEST(subghz_encoder_clemsa_test);

View file

@ -72,18 +72,7 @@ typedef enum {
SubGhzViewIdTestPacket, SubGhzViewIdTestPacket,
} SubGhzViewId; } SubGhzViewId;
struct SubGhzPresetDefinition {
FuriString* name;
uint32_t frequency;
uint8_t* data;
size_t data_size;
};
typedef struct SubGhzPresetDefinition SubGhzPresetDefinition;
typedef enum { typedef enum {
SubGhzViewReceiverModeLive, SubGhzViewReceiverModeLive,
SubGhzViewReceiverModeFile, SubGhzViewReceiverModeFile,
} SubGhzViewReceiverMode; } SubGhzViewReceiverMode;
#define SUBGHZ_HISTORY_REMOVE_SAVED_ITEMS 1

View file

@ -7,7 +7,7 @@
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/stream.h> #include <lib/toolbox/stream/stream.h>
#include <lib/subghz/protocols/registry.h> #include <lib/subghz/protocols/protocol_items.h>
#define TAG "SubGhzSetType" #define TAG "SubGhzSetType"

View file

@ -3,6 +3,7 @@
#include <subghz/types.h> #include <subghz/types.h>
#include <lib/toolbox/path.h> #include <lib/toolbox/path.h>
#include "subghz_i.h" #include "subghz_i.h"
#include <lib/subghz/protocols/protocol_items.h>
#define TAG "SubGhzApp" #define TAG "SubGhzApp"
@ -243,7 +244,8 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo")); subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz_environment_set_nice_flor_s_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s")); subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(
subghz->txrx->environment, (void*)&subghz_protocol_registry);
subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING #ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz); subghz_last_settings_set_detect_raw_values(subghz);

View file

@ -9,6 +9,7 @@
#include <lib/subghz/receiver.h> #include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h> #include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_file_encoder_worker.h> #include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/subghz/protocols/protocol_items.h>
#include "helpers/subghz_chat.h" #include "helpers/subghz_chat.h"
@ -159,6 +160,7 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) {
stream_write_cstring(stream, furi_string_get_cstr(flipper_format_string)); stream_write_cstring(stream, furi_string_get_cstr(flipper_format_string));
SubGhzEnvironment* environment = subghz_environment_alloc(); SubGhzEnvironment* environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
SubGhzTransmitter* transmitter = subghz_transmitter_alloc_init(environment, "Princeton"); SubGhzTransmitter* transmitter = subghz_transmitter_alloc_init(environment, "Princeton");
subghz_transmitter_deserialize(transmitter, flipper_format); subghz_transmitter_deserialize(transmitter, flipper_format);
@ -252,6 +254,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
environment, EXT_PATH("subghz/assets/came_atomo")); environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s")); environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable); subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);
@ -371,6 +374,7 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
environment, EXT_PATH("subghz/assets/came_atomo")); environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s")); environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment); SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable); subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);

View file

@ -5,7 +5,7 @@
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <lib/flipper_format/flipper_format.h> #include <lib/flipper_format/flipper_format.h>
#include "helpers/subghz_types.h" #include <lib/subghz/types.h>
typedef struct SubGhzHistory SubGhzHistory; typedef struct SubGhzHistory SubGhzHistory;

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "helpers/subghz_types.h" #include "helpers/subghz_types.h"
#include <lib/subghz/types.h>
#include "subghz.h" #include "subghz.h"
#include "views/receiver.h" #include "views/receiver.h"
#include "views/transmitter.h" #include "views/transmitter.h"
@ -12,8 +13,6 @@
#include "views/subghz_test_static.h" #include "views/subghz_test_static.h"
#include "views/subghz_test_packet.h" #include "views/subghz_test_packet.h"
#endif #endif
// #include <furi.h>
// #include <furi_hal.h>
#include <gui/gui.h> #include <gui/gui.h>
#include <dialogs/dialogs.h> #include <dialogs/dialogs.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
@ -26,16 +25,13 @@
#include <gui/modules/widget.h> #include <gui/modules/widget.h>
#include <subghz/scenes/subghz_scene.h> #include <subghz/scenes/subghz_scene.h>
#include <lib/subghz/subghz_worker.h> #include <lib/subghz/subghz_worker.h>
#include <lib/subghz/subghz_file_encoder_worker.h> #include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/subghz/subghz_setting.h>
#include <lib/subghz/receiver.h> #include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h> #include <lib/subghz/transmitter.h>
#include "subghz_history.h" #include "subghz_history.h"
#include "subghz_setting.h"
#include "subghz_last_settings.h" #include "subghz_last_settings.h"
#include <gui/modules/variable_item_list.h> #include <gui/modules/variable_item_list.h>

View file

@ -217,7 +217,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
} else { } else {
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
} }
canvas_draw_icon(canvas, 1, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); 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)); canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff));
furi_string_reset(str_buff); furi_string_reset(str_buff);
} }

View file

@ -15,7 +15,7 @@
#include <applications/main/subghz/subghz_i.h> #include <applications/main/subghz/subghz_i.h>
#include <lib/subghz/protocols/raw.h> #include <lib/subghz/protocols/raw.h>
#include <lib/subghz/protocols/registry.h> #include <lib/subghz/protocols/protocol_items.h>
#include <lib/subghz/types.h> #include <lib/subghz/types.h>
#include <lib/subghz/protocols/keeloq.h> #include <lib/subghz/protocols/keeloq.h>
#include <lib/subghz/protocols/star_line.h> #include <lib/subghz/protocols/star_line.h>
@ -602,10 +602,12 @@ void unirfremix_tx_stop(UniRFRemix* app) {
subghz_transmitter_stop(app->tx_transmitter); subghz_transmitter_stop(app->tx_transmitter);
FURI_LOG_D(TAG, "Checking if protocol is dynamic"); FURI_LOG_D(TAG, "Checking if protocol is dynamic");
const SubGhzProtocol* registry = const SubGhzProtocolRegistry* protocol_registry_items =
subghz_protocol_registry_get_by_name(furi_string_get_cstr(app->txpreset->protocol)); subghz_environment_get_protocol_registry(app->environment);
FURI_LOG_D(TAG, "Protocol-TYPE %d", registry->type); const SubGhzProtocol* proto = subghz_protocol_registry_get_by_name(
if(registry && registry->type == SubGhzProtocolTypeDynamic) { protocol_registry_items, furi_string_get_cstr(app->txpreset->protocol));
FURI_LOG_D(TAG, "Protocol-TYPE %d", proto->type);
if(proto && proto->type == SubGhzProtocolTypeDynamic) {
FURI_LOG_D(TAG, "Protocol is dynamic. Saving key"); FURI_LOG_D(TAG, "Protocol is dynamic. Saving key");
unirfremix_save_protocol_to_file(app->tx_fff_data, app->tx_file_path); unirfremix_save_protocol_to_file(app->tx_fff_data, app->tx_file_path);
@ -838,6 +840,7 @@ void unirfremix_subghz_alloc(UniRFRemix* app) {
app->environment, EXT_PATH("subghz/assets/came_atomo")); app->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz_environment_set_nice_flor_s_rainbow_table_file_name(
app->environment, EXT_PATH("subghz/assets/nice_flor_s")); app->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry);
app->subghz_receiver = subghz_receiver_alloc_init(app->environment); app->subghz_receiver = subghz_receiver_alloc_init(app->environment);
} }

View file

@ -8,6 +8,7 @@
#include <lib/toolbox/path.h> #include <lib/toolbox/path.h>
#include <assets_icons.h> #include <assets_icons.h>
#include <lib/subghz/protocols/protocol_items.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <applications/main/subghz/subghz_i.h> #include <applications/main/subghz/subghz_i.h>
@ -158,6 +159,7 @@ static int playlist_worker_process(
// (try to) send file // (try to) send file
SubGhzEnvironment* environment = subghz_environment_alloc(); SubGhzEnvironment* environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
SubGhzTransmitter* transmitter = SubGhzTransmitter* transmitter =
subghz_transmitter_alloc_init(environment, furi_string_get_cstr(protocol)); subghz_transmitter_alloc_init(environment, furi_string_get_cstr(protocol));

View file

@ -3,6 +3,7 @@
#include <toolbox/stream/stream.h> #include <toolbox/stream/stream.h>
#include <flipper_format.h> #include <flipper_format.h>
#include <flipper_format_i.h> #include <flipper_format_i.h>
#include <lib/subghz/protocols/protocol_items.h>
#define TAG "SubBruteWorker" #define TAG "SubBruteWorker"
#define SUBBRUTE_TX_TIMEOUT 5 #define SUBBRUTE_TX_TIMEOUT 5
@ -30,6 +31,8 @@ SubBruteWorker* subbrute_worker_alloc() {
instance->decoder_result = NULL; instance->decoder_result = NULL;
instance->transmitter = NULL; instance->transmitter = NULL;
instance->environment = subghz_environment_alloc(); instance->environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry(
instance->environment, (void*)&subghz_protocol_registry);
instance->transmit_mode = false; instance->transmit_mode = false;

View file

@ -5,6 +5,7 @@
#include <lib/toolbox/stream/stream.h> #include <lib/toolbox/stream/stream.h>
#include <lib/flipper_format/flipper_format.h> #include <lib/flipper_format/flipper_format.h>
#include <lib/flipper_format/flipper_format_i.h> #include <lib/flipper_format/flipper_format_i.h>
#include <lib/subghz/protocols/protocol_items.h>
#define TAG "SubBruteDevice" #define TAG "SubBruteDevice"
@ -18,6 +19,8 @@ SubBruteDevice* subbrute_device_alloc() {
instance->decoder_result = NULL; instance->decoder_result = NULL;
instance->receiver = NULL; instance->receiver = NULL;
instance->environment = subghz_environment_alloc(); instance->environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry(
instance->environment, (void*)&subghz_protocol_registry);
#ifdef FURI_DEBUG #ifdef FURI_DEBUG
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433);

View file

@ -0,0 +1,13 @@
App(
appid="weather_station",
name="Weather Station",
apptype=FlipperAppType.PLUGIN,
entry_point="weather_station_app",
cdefines=["APP_WEATHER_STATION"],
requires=["gui"],
stack_size=4 * 1024,
order=50,
fap_icon="weather_station_10px.png",
fap_category="Tools",
fap_icon_assets="images",
)

View file

@ -0,0 +1,14 @@
#pragma once
typedef enum {
//WSCustomEvent
WSCustomEventStartId = 100,
WSCustomEventSceneSettingLock,
WSCustomEventViewReceiverOK,
WSCustomEventViewReceiverConfig,
WSCustomEventViewReceiverBack,
WSCustomEventViewReceiverOffDisplay,
WSCustomEventViewReceiverUnlock,
} WSCustomEvent;

View file

@ -0,0 +1,50 @@
#pragma once
#include <furi.h>
#include <furi_hal.h>
#define WS_VERSION_APP "0.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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,341 @@
#include "gt_wt_03.h"
#define TAG "WSProtocolGT_WT03"
/*
* Help
* https://github.com/merbanan/rtl_433/blob/5f0ff6db624270a4598958ab9dd79bb385ced3ef/src/devices/gt_wt_03.c
*
*
* Globaltronics GT-WT-03 sensor on 433.92MHz.
* The 01-set sensor has 60 ms packet gap with 10 repeats.
* The 02-set sensor has no packet gap with 23 repeats.
* Example:
* {41} 17 cf be fa 6a 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-Yes ]
* {41} 17 cf be fa 6a 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-Yes Batt-Changed ]
* {41} 17 cf fe fa ea 80 [ S1 C1 26,1 C 78.9 F 48% Bat-Good Manual-No Batt-Changed ]
* {41} 01 cf 6f 11 b2 80 [ S2 C2 23,8 C 74.8 F 48% Bat-LOW Manual-No ]
* {41} 01 c8 d0 2b 76 80 [ S2 C3 -4,4 C 24.1 F 55% Bat-Good Manual-No Batt-Changed ]
* Format string:
* ID:8h HUM:8d B:b M:b C:2d TEMP:12d CHK:8h 1x
* Data layout:
* TYP IIIIIIII HHHHHHHH BMCCTTTT TTTTTTTT XXXXXXXX
* - I: Random Device Code: changes with battery reset
* - H: Humidity: 8 Bit 00-99, Display LL=10%, Display HH=110% (Range 20-95%)
* - B: Battery: 0=OK 1=LOW
* - M: Manual Send Button Pressed: 0=not pressed, 1=pressed
* - C: Channel: 00=CH1, 01=CH2, 10=CH3
* - T: Temperature: 12 Bit 2's complement, scaled by 10, range-50.0 C (-50.1 shown as Lo) to +70.0 C (+70.1 C is shown as Hi)
* - X: Checksum, xor shifting key per byte
* Humidity:
* - the working range is 20-95 %
* - if "LL" in display view it sends 10 %
* - if "HH" in display view it sends 110%
* Checksum:
* Per byte xor the key for each 1-bit, shift per bit. Key list per bit, starting at MSB:
* - 0x00 [07]
* - 0x80 [06]
* - 0x40 [05]
* - 0x20 [04]
* - 0x10 [03]
* - 0x88 [02]
* - 0xc4 [01]
* - 0x62 [00]
* Note: this can also be seen as lower byte of a Galois/Fibonacci LFSR-16, gen 0x00, init 0x3100 (or 0x62 if reversed) resetting at every byte.
* Battery voltages:
* - U=<2,65V +- ~5% Battery indicator
* - U=>2.10C +- 5% plausible readings
* - U=2,00V +- ~5% Temperature offset -5°C Humidity offset unknown
* - U=<1,95V +- ~5% does not initialize anymore
* - U=1,90V +- 5% temperature offset -15°C
* - U=1,80V +- 5% Display is showing refresh pattern
* - U=1.75V +- ~5% TX causes cut out
*
*/
static const SubGhzBlockConst ws_protocol_gt_wt_03_const = {
.te_short = 285,
.te_long = 570,
.te_delta = 120,
.min_count_bit_for_found = 41,
};
struct WSProtocolDecoderGT_WT03 {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
uint16_t header_count;
};
struct WSProtocolEncoderGT_WT03 {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
GT_WT03DecoderStepReset = 0,
GT_WT03DecoderStepCheckPreambule,
GT_WT03DecoderStepSaveDuration,
GT_WT03DecoderStepCheckDuration,
} GT_WT03DecoderStep;
const SubGhzProtocolDecoder ws_protocol_gt_wt_03_decoder = {
.alloc = ws_protocol_decoder_gt_wt_03_alloc,
.free = ws_protocol_decoder_gt_wt_03_free,
.feed = ws_protocol_decoder_gt_wt_03_feed,
.reset = ws_protocol_decoder_gt_wt_03_reset,
.get_hash_data = ws_protocol_decoder_gt_wt_03_get_hash_data,
.serialize = ws_protocol_decoder_gt_wt_03_serialize,
.deserialize = ws_protocol_decoder_gt_wt_03_deserialize,
.get_string = ws_protocol_decoder_gt_wt_03_get_string,
};
const SubGhzProtocolEncoder ws_protocol_gt_wt_03_encoder = {
.alloc = NULL,
.free = NULL,
.deserialize = NULL,
.stop = NULL,
.yield = NULL,
};
const SubGhzProtocol ws_protocol_gt_wt_03 = {
.name = WS_PROTOCOL_GT_WT_03_NAME,
.type = SubGhzProtocolWeatherStation,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
.decoder = &ws_protocol_gt_wt_03_decoder,
.encoder = &ws_protocol_gt_wt_03_encoder,
};
void* ws_protocol_decoder_gt_wt_03_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderGT_WT03* instance = malloc(sizeof(WSProtocolDecoderGT_WT03));
instance->base.protocol = &ws_protocol_gt_wt_03;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_gt_wt_03_free(void* context) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
free(instance);
}
void ws_protocol_decoder_gt_wt_03_reset(void* context) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
static bool ws_protocol_gt_wt_03_check_crc(WSProtocolDecoderGT_WT03* instance) {
uint8_t msg[] = {
instance->decoder.decode_data >> 33,
instance->decoder.decode_data >> 25,
instance->decoder.decode_data >> 17,
instance->decoder.decode_data >> 9};
uint8_t sum = 0;
for(unsigned k = 0; k < sizeof(msg); ++k) {
uint8_t data = msg[k];
uint16_t key = 0x3100;
for(int i = 7; i >= 0; --i) {
// XOR key into sum if data bit is set
if((data >> i) & 1) sum ^= key & 0xff;
// roll the key right
key = (key >> 1);
}
}
return ((sum ^ (uint8_t)((instance->decoder.decode_data >> 1) & 0xFF)) == 0x2D);
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_gt_wt_03_remote_controller(WSBlockGeneric* instance) {
instance->id = instance->data >> 33;
instance->humidity = (instance->data >> 25) & 0xFF;
if(instance->humidity <= 10) { // actually the sensors sends 10 below working range of 20%
instance->humidity = 0;
} else if(instance->humidity > 95) { // actually the sensors sends 110 above working range of 90%
instance->humidity = 100;
}
instance->battery_low = (instance->data >> 24) & 1;
instance->btn = (instance->data >> 23) & 1;
instance->channel = ((instance->data >> 21) & 0x03) + 1;
if(!((instance->data >> 20) & 1)) {
instance->temp = (float)((instance->data >> 9) & 0x07FF) / 10.0f;
} else {
instance->temp = (float)((~(instance->data >> 9) & 0x07FF) + 1) / -10.0f;
}
}
void ws_protocol_decoder_gt_wt_03_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
switch(instance->decoder.parser_step) {
case GT_WT03DecoderStepReset:
if((level) && (DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) <
ws_protocol_gt_wt_03_const.te_delta * 2)) {
instance->decoder.parser_step = GT_WT03DecoderStepCheckPreambule;
instance->decoder.te_last = duration;
instance->header_count = 0;
}
break;
case GT_WT03DecoderStepCheckPreambule:
if(level) {
instance->decoder.te_last = duration;
} else {
if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short * 3) <
ws_protocol_gt_wt_03_const.te_delta * 2) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) <
ws_protocol_gt_wt_03_const.te_delta * 2)) {
//Found preambule
instance->header_count++;
} else if(instance->header_count == 4) {
if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short) <
ws_protocol_gt_wt_03_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_long) <
ws_protocol_gt_wt_03_const.te_delta)) {
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_long) <
ws_protocol_gt_wt_03_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short) <
ws_protocol_gt_wt_03_const.te_delta)) {
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration;
} else {
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
} else {
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
}
break;
case GT_WT03DecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = GT_WT03DecoderStepCheckDuration;
} else {
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
break;
case GT_WT03DecoderStepCheckDuration:
if(!level) {
if(((DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short * 3) <
ws_protocol_gt_wt_03_const.te_delta * 2) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short * 3) <
ws_protocol_gt_wt_03_const.te_delta * 2))) {
if((instance->decoder.decode_count_bit ==
ws_protocol_gt_wt_03_const.min_count_bit_for_found) &&
ws_protocol_gt_wt_03_check_crc(instance)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_gt_wt_03_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
instance->header_count = 1;
instance->decoder.parser_step = GT_WT03DecoderStepCheckPreambule;
break;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_short) <
ws_protocol_gt_wt_03_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_long) <
ws_protocol_gt_wt_03_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_gt_wt_03_const.te_long) <
ws_protocol_gt_wt_03_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_gt_wt_03_const.te_short) <
ws_protocol_gt_wt_03_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = GT_WT03DecoderStepSaveDuration;
} else {
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
} else {
instance->decoder.parser_step = GT_WT03DecoderStepReset;
}
break;
}
}
uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_gt_wt_03_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
ws_protocol_gt_wt_03_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderGT_WT03* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%d.%d C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(int16_t)instance->generic.temp,
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
instance->generic.humidity);
}

View file

@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_GT_WT_03_NAME "GT-WT03"
typedef struct WSProtocolDecoderGT_WT03 WSProtocolDecoderGT_WT03;
typedef struct WSProtocolEncoderGT_WT03 WSProtocolEncoderGT_WT03;
extern const SubGhzProtocolDecoder ws_protocol_gt_wt_03_decoder;
extern const SubGhzProtocolEncoder ws_protocol_gt_wt_03_encoder;
extern const SubGhzProtocol ws_protocol_gt_wt_03;
/**
* Allocate WSProtocolDecoderGT_WT03.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderGT_WT03* pointer to a WSProtocolDecoderGT_WT03 instance
*/
void* ws_protocol_decoder_gt_wt_03_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderGT_WT03.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
*/
void ws_protocol_decoder_gt_wt_03_free(void* context);
/**
* Reset decoder WSProtocolDecoderGT_WT03.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
*/
void ws_protocol_decoder_gt_wt_03_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_gt_wt_03_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderGT_WT03.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool ws_protocol_decoder_gt_wt_03_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data WSProtocolDecoderGT_WT03.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
* @param output Resulting text
*/
void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output);

View file

@ -0,0 +1,296 @@
#include "infactory.h"
#define TAG "WSProtocolInfactory"
/*
* Help
* https://github.com/merbanan/rtl_433/blob/master/src/devices/infactory.c
*
* Analysis using Genuino (see http://gitlab.com/hp-uno, e.g. uno_log_433):
* Observed On-Off-Key (OOK) data pattern:
* preamble syncPrefix data...(40 bit) syncPostfix
* HHLL HHLL HHLL HHLL HLLLLLLLLLLLLLLLL (HLLLL HLLLLLLLL HLLLL HLLLLLLLL ....) HLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
* Breakdown:
* - four preamble pairs '1'/'0' each with a length of ca. 1000us
* - syncPre, syncPost, data0, data1 have a '1' start pulse of ca. 500us
* - syncPre pulse before dataPtr has a '0' pulse length of ca. 8000us
* - data0 (0-bits) have then a '0' pulse length of ca. 2000us
* - data1 (1-bits) have then a '0' pulse length of ca. 4000us
* - syncPost after dataPtr has a '0' pulse length of ca. 16000us
* This analysis is the reason for the new r_device definitions below.
* NB: pulse_slicer_ppm does not use .gap_limit if .tolerance is set.
*
* Outdoor sensor, transmits temperature and humidity data
* - inFactory NC-3982-913/NX-5817-902, Pearl (for FWS-686 station)
* - nor-tec 73383 (weather station + sensor), Schou Company AS, Denmark
* - DAY 73365 (weather station + sensor), Schou Company AS, Denmark
* Known brand names: inFactory, nor-tec, GreenBlue, DAY. Manufacturer in China.
* Transmissions includes an id. Every 60 seconds the sensor transmits 6 packets:
* 0000 1111 | 0011 0000 | 0101 1100 | 1110 0111 | 0110 0001
* iiii iiii | cccc ub?? | tttt tttt | tttt hhhh | hhhh ??nn
* - i: identification; changes on battery switch
* - c: CRC-4; CCITT checksum, see below for computation specifics
* - u: unknown; (sometimes set at power-on, but not always)
* - b: battery low; flag to indicate low battery voltage
* - h: Humidity; BCD-encoded, each nibble is one digit, 'A0' means 100%rH
* - t: Temperature; in °F as binary number with one decimal place + 90 °F offset
* - n: Channel; Channel number 1 - 3
*
*/
static const SubGhzBlockConst ws_protocol_infactory_const = {
.te_short = 500,
.te_long = 2000,
.te_delta = 150,
.min_count_bit_for_found = 40,
};
struct WSProtocolDecoderInfactory {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
uint16_t header_count;
};
struct WSProtocolEncoderInfactory {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
InfactoryDecoderStepReset = 0,
InfactoryDecoderStepCheckPreambule,
InfactoryDecoderStepSaveDuration,
InfactoryDecoderStepCheckDuration,
} InfactoryDecoderStep;
const SubGhzProtocolDecoder ws_protocol_infactory_decoder = {
.alloc = ws_protocol_decoder_infactory_alloc,
.free = ws_protocol_decoder_infactory_free,
.feed = ws_protocol_decoder_infactory_feed,
.reset = ws_protocol_decoder_infactory_reset,
.get_hash_data = ws_protocol_decoder_infactory_get_hash_data,
.serialize = ws_protocol_decoder_infactory_serialize,
.deserialize = ws_protocol_decoder_infactory_deserialize,
.get_string = ws_protocol_decoder_infactory_get_string,
};
const SubGhzProtocolEncoder ws_protocol_infactory_encoder = {
.alloc = NULL,
.free = NULL,
.deserialize = NULL,
.stop = NULL,
.yield = NULL,
};
const SubGhzProtocol ws_protocol_infactory = {
.name = WS_PROTOCOL_INFACTORY_NAME,
.type = SubGhzProtocolWeatherStation,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
.decoder = &ws_protocol_infactory_decoder,
.encoder = &ws_protocol_infactory_encoder,
};
void* ws_protocol_decoder_infactory_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderInfactory* instance = malloc(sizeof(WSProtocolDecoderInfactory));
instance->base.protocol = &ws_protocol_infactory;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_infactory_free(void* context) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
free(instance);
}
void ws_protocol_decoder_infactory_reset(void* context) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
instance->decoder.parser_step = InfactoryDecoderStepReset;
}
static bool ws_protocol_infactory_check_crc(WSProtocolDecoderInfactory* instance) {
uint8_t msg[] = {
instance->decoder.decode_data >> 32,
(((instance->decoder.decode_data >> 24) & 0x0F) | (instance->decoder.decode_data & 0x0F)
<< 4),
instance->decoder.decode_data >> 16,
instance->decoder.decode_data >> 8,
instance->decoder.decode_data};
uint8_t crc =
subghz_protocol_blocks_crc4(msg, 4, 0x13, 0); // Koopmann 0x9, CCITT-4; FP-4; ITU-T G.704
crc ^= msg[4] >> 4; // last nibble is only XORed
return (crc == ((instance->decoder.decode_data >> 28) & 0x0F));
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_infactory_remote_controller(WSBlockGeneric* instance) {
instance->id = instance->data >> 32;
instance->battery_low = (instance->data >> 26) & 1;
instance->temp = ws_block_generic_fahrenheit_to_celsius(
((float)((instance->data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
instance->humidity =
(((instance->data >> 8) & 0x0F) * 10) + ((instance->data >> 4) & 0x0F); // BCD, 'A0'=100%rH
instance->channel = instance->data & 0x03;
}
void ws_protocol_decoder_infactory_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
switch(instance->decoder.parser_step) {
case InfactoryDecoderStepReset:
if((level) && (DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 2) <
ws_protocol_infactory_const.te_delta * 2)) {
instance->decoder.parser_step = InfactoryDecoderStepCheckPreambule;
instance->decoder.te_last = duration;
instance->header_count = 0;
}
break;
case InfactoryDecoderStepCheckPreambule:
if(level) {
instance->decoder.te_last = duration;
} else {
if((DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short * 2) <
ws_protocol_infactory_const.te_delta * 2) &&
(DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 2) <
ws_protocol_infactory_const.te_delta * 2)) {
//Found preambule
instance->header_count++;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) <
ws_protocol_infactory_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_infactory_const.te_short * 16) <
ws_protocol_infactory_const.te_delta * 8)) {
//Found syncPrefix
if(instance->header_count > 3) {
instance->decoder.parser_step = InfactoryDecoderStepSaveDuration;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
}
} else {
instance->decoder.parser_step = InfactoryDecoderStepReset;
}
}
break;
case InfactoryDecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = InfactoryDecoderStepCheckDuration;
} else {
instance->decoder.parser_step = InfactoryDecoderStepReset;
}
break;
case InfactoryDecoderStepCheckDuration:
if(!level) {
if(duration >= ((uint32_t)ws_protocol_infactory_const.te_short * 30)) {
//Found syncPostfix
if((instance->decoder.decode_count_bit ==
ws_protocol_infactory_const.min_count_bit_for_found) &&
ws_protocol_infactory_check_crc(instance)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_infactory_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
instance->decoder.parser_step = InfactoryDecoderStepReset;
break;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) <
ws_protocol_infactory_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_infactory_const.te_long) <
ws_protocol_infactory_const.te_delta * 2)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = InfactoryDecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_infactory_const.te_short) <
ws_protocol_infactory_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_infactory_const.te_long * 2) <
ws_protocol_infactory_const.te_delta * 4)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = InfactoryDecoderStepSaveDuration;
} else {
instance->decoder.parser_step = InfactoryDecoderStepReset;
}
} else {
instance->decoder.parser_step = InfactoryDecoderStepReset;
}
break;
}
}
uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_infactory_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
ws_protocol_infactory_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderInfactory* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%d.%d C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(int16_t)instance->generic.temp,
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
instance->generic.humidity);
}

View file

@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_INFACTORY_NAME "inFactory-TH"
typedef struct WSProtocolDecoderInfactory WSProtocolDecoderInfactory;
typedef struct WSProtocolEncoderInfactory WSProtocolEncoderInfactory;
extern const SubGhzProtocolDecoder ws_protocol_infactory_decoder;
extern const SubGhzProtocolEncoder ws_protocol_infactory_encoder;
extern const SubGhzProtocol ws_protocol_infactory;
/**
* Allocate WSProtocolDecoderInfactory.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderInfactory* pointer to a WSProtocolDecoderInfactory instance
*/
void* ws_protocol_decoder_infactory_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderInfactory.
* @param context Pointer to a WSProtocolDecoderInfactory instance
*/
void ws_protocol_decoder_infactory_free(void* context);
/**
* Reset decoder WSProtocolDecoderInfactory.
* @param context Pointer to a WSProtocolDecoderInfactory instance
*/
void ws_protocol_decoder_infactory_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderInfactory instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_infactory_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderInfactory instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderInfactory.
* @param context Pointer to a WSProtocolDecoderInfactory instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool ws_protocol_decoder_infactory_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data WSProtocolDecoderInfactory.
* @param context Pointer to a WSProtocolDecoderInfactory instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderInfactory instance
* @param output Resulting text
*/
void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output);

View file

@ -0,0 +1,261 @@
#include "nexus_th.h"
#define TAG "WSProtocolNexus_TH"
/*
* Help
* https://github.com/merbanan/rtl_433/blob/ef2d37cf51e3264d11cde9149ef87de2f0a4d37a/src/devices/nexus.c
*
* Nexus sensor protocol with ID, temperature and optional humidity
* also FreeTec (Pearl) NC-7345 sensors for FreeTec Weatherstation NC-7344,
* also infactory/FreeTec (Pearl) NX-3980 sensors for infactory/FreeTec NX-3974 station,
* also Solight TE82S sensors for Solight TE76/TE82/TE83/TE84 stations,
* also TFA 30.3209.02 temperature/humidity sensor.
* The sensor sends 36 bits 12 times,
* the packets are ppm modulated (distance coding) with a pulse of ~500 us
* followed by a short gap of ~1000 us for a 0 bit or a long ~2000 us gap for a
* 1 bit, the sync gap is ~4000 us.
* The data is grouped in 9 nibbles:
* [id0] [id1] [flags] [temp0] [temp1] [temp2] [const] [humi0] [humi1]
* - The 8-bit id changes when the battery is changed in the sensor.
* - flags are 4 bits B 0 C C, where B is the battery status: 1=OK, 0=LOW
* - and CC is the channel: 0=CH1, 1=CH2, 2=CH3
* - temp is 12 bit signed scaled by 10
* - const is always 1111 (0x0F)
* - humidity is 8 bits
* The sensors can be bought at Clas Ohlsen (Nexus) and Pearl (infactory/FreeTec).
*
*/
#define NEXUS_TH_CONST_DATA 0b1111
static const SubGhzBlockConst ws_protocol_nexus_th_const = {
.te_short = 500,
.te_long = 2000,
.te_delta = 150,
.min_count_bit_for_found = 36,
};
struct WSProtocolDecoderNexus_TH {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
};
struct WSProtocolEncoderNexus_TH {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
Nexus_THDecoderStepReset = 0,
Nexus_THDecoderStepSaveDuration,
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,
.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 = 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_decoder_nexus_th_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderNexus_TH* instance = malloc(sizeof(WSProtocolDecoderNexus_TH));
instance->base.protocol = &ws_protocol_nexus_th;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_nexus_th_free(void* context) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
free(instance);
}
void ws_protocol_decoder_nexus_th_reset(void* context) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
instance->decoder.parser_step = Nexus_THDecoderStepReset;
}
static bool ws_protocol_nexus_th_check(WSProtocolDecoderNexus_TH* instance) {
uint8_t type = (instance->decoder.decode_data >> 8) & 0x0F;
if((type == NEXUS_TH_CONST_DATA) && ((instance->decoder.decode_data >> 4) != 0xffffffff)) {
return true;
} else {
return false;
}
return true;
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_nexus_th_remote_controller(WSBlockGeneric* instance) {
instance->id = (instance->data >> 28) & 0xFF;
instance->battery_low = !((instance->data >> 27) & 1);
instance->channel = ((instance->data >> 24) & 0x03) + 1;
if(!((instance->data >> 23) & 1)) {
instance->temp = (float)((instance->data >> 12) & 0x07FF) / 10.0f;
} else {
instance->temp = (float)((~(instance->data >> 12) & 0x07FF) + 1) / -10.0f;
}
instance->humidity = instance->data & 0xFF;
}
void ws_protocol_decoder_nexus_th_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
switch(instance->decoder.parser_step) {
case Nexus_THDecoderStepReset:
if((!level) && (DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 8) <
ws_protocol_nexus_th_const.te_delta * 4)) {
//Found sync
instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
}
break;
case Nexus_THDecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = Nexus_THDecoderStepCheckDuration;
} else {
instance->decoder.parser_step = Nexus_THDecoderStepReset;
}
break;
case Nexus_THDecoderStepCheckDuration:
if(!level) {
if(DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 8) <
ws_protocol_nexus_th_const.te_delta * 4) {
//Found sync
instance->decoder.parser_step = Nexus_THDecoderStepReset;
if((instance->decoder.decode_count_bit ==
ws_protocol_nexus_th_const.min_count_bit_for_found) &&
ws_protocol_nexus_th_check(instance)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_nexus_th_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
instance->decoder.parser_step = Nexus_THDecoderStepCheckDuration;
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
break;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_nexus_th_const.te_short) <
ws_protocol_nexus_th_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 2) <
ws_protocol_nexus_th_const.te_delta * 2)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_nexus_th_const.te_short) <
ws_protocol_nexus_th_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_nexus_th_const.te_short * 4) <
ws_protocol_nexus_th_const.te_delta * 4)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = Nexus_THDecoderStepSaveDuration;
} else {
instance->decoder.parser_step = Nexus_THDecoderStepReset;
}
} else {
instance->decoder.parser_step = Nexus_THDecoderStepReset;
}
break;
}
}
uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_nexus_th_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
ws_protocol_nexus_th_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderNexus_TH* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%d.%d C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(int16_t)instance->generic.temp,
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
instance->generic.humidity);
}

View file

@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_NEXUS_TH_NAME "Nexus-TH"
typedef struct WSProtocolDecoderNexus_TH WSProtocolDecoderNexus_TH;
typedef struct WSProtocolEncoderNexus_TH WSProtocolEncoderNexus_TH;
extern const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder;
extern const SubGhzProtocolEncoder ws_protocol_nexus_th_encoder;
extern const SubGhzProtocol ws_protocol_nexus_th;
/**
* Allocate WSProtocolDecoderNexus_TH.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderNexus_TH* pointer to a WSProtocolDecoderNexus_TH instance
*/
void* ws_protocol_decoder_nexus_th_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderNexus_TH.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
*/
void ws_protocol_decoder_nexus_th_free(void* context);
/**
* Reset decoder WSProtocolDecoderNexus_TH.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
*/
void ws_protocol_decoder_nexus_th_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_nexus_th_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderNexus_TH.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool ws_protocol_decoder_nexus_th_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data WSProtocolDecoderNexus_TH.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
* @param output Resulting text
*/
void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output);

View file

@ -0,0 +1,12 @@
#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_03,
};
const SubGhzProtocolRegistry weather_station_protocol_registry = {
.items = weather_station_protocol_registry_items,
.size = COUNT_OF(weather_station_protocol_registry_items)};

View file

@ -0,0 +1,9 @@
#pragma once
#include "../weather_station_app_i.h"
#include "infactory.h"
#include "thermopro_tx4.h"
#include "nexus_th.h"
#include "gt_wt_03.h"
extern const SubGhzProtocolRegistry weather_station_protocol_registry;

View file

@ -0,0 +1,261 @@
#include "thermopro_tx4.h"
#define TAG "WSProtocolThermoPRO_TX4"
/*
* Help
* https://github.com/merbanan/rtl_433/blob/master/src/devices/thermopro_tx2.c
*
* The sensor sends 37 bits 6 times, before the first packet there is a sync pulse.
* The packets are ppm modulated (distance coding) with a pulse of ~500 us
* followed by a short gap of ~2000 us for a 0 bit or a long ~4000 us gap for a
* 1 bit, the sync gap is ~9000 us.
* The data is grouped in 9 nibbles
* [type] [id0] [id1] [flags] [temp0] [temp1] [temp2] [humi0] [humi1]
* - type: 4 bit fixed 1001 (9) or 0110 (5)
* - id: 8 bit a random id that is generated when the sensor starts, could include battery status
* the same batteries often generate the same id
* - flags(3): is 1 when the battery is low, otherwise 0 (ok)
* - flags(2): is 1 when the sensor sends a reading when pressing the button on the sensor
* - flags(1,0): the channel number that can be set by the sensor (1, 2, 3, X)
* - temp: 12 bit signed scaled by 10
* - humi: 8 bit always 11001100 (0xCC) if no humidity sensor is available
*
*/
#define THERMO_PRO_TX4_TYPE_1 0b1001
#define THERMO_PRO_TX4_TYPE_2 0b0110
static const SubGhzBlockConst ws_protocol_thermopro_tx4_const = {
.te_short = 500,
.te_long = 2000,
.te_delta = 150,
.min_count_bit_for_found = 37,
};
struct WSProtocolDecoderThermoPRO_TX4 {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
};
struct WSProtocolEncoderThermoPRO_TX4 {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
ThermoPRO_TX4DecoderStepReset = 0,
ThermoPRO_TX4DecoderStepSaveDuration,
ThermoPRO_TX4DecoderStepCheckDuration,
} ThermoPRO_TX4DecoderStep;
const SubGhzProtocolDecoder ws_protocol_thermopro_tx4_decoder = {
.alloc = ws_protocol_decoder_thermopro_tx4_alloc,
.free = ws_protocol_decoder_thermopro_tx4_free,
.feed = ws_protocol_decoder_thermopro_tx4_feed,
.reset = ws_protocol_decoder_thermopro_tx4_reset,
.get_hash_data = ws_protocol_decoder_thermopro_tx4_get_hash_data,
.serialize = ws_protocol_decoder_thermopro_tx4_serialize,
.deserialize = ws_protocol_decoder_thermopro_tx4_deserialize,
.get_string = ws_protocol_decoder_thermopro_tx4_get_string,
};
const SubGhzProtocolEncoder ws_protocol_thermopro_tx4_encoder = {
.alloc = NULL,
.free = NULL,
.deserialize = NULL,
.stop = NULL,
.yield = NULL,
};
const SubGhzProtocol ws_protocol_thermopro_tx4 = {
.name = WS_PROTOCOL_THERMOPRO_TX4_NAME,
.type = SubGhzProtocolWeatherStation,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
.decoder = &ws_protocol_thermopro_tx4_decoder,
.encoder = &ws_protocol_thermopro_tx4_encoder,
};
void* ws_protocol_decoder_thermopro_tx4_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderThermoPRO_TX4* instance = malloc(sizeof(WSProtocolDecoderThermoPRO_TX4));
instance->base.protocol = &ws_protocol_thermopro_tx4;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_thermopro_tx4_free(void* context) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
free(instance);
}
void ws_protocol_decoder_thermopro_tx4_reset(void* context) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset;
}
static bool ws_protocol_thermopro_tx4_check(WSProtocolDecoderThermoPRO_TX4* instance) {
uint8_t type = instance->decoder.decode_data >> 33;
if((type == THERMO_PRO_TX4_TYPE_1) || (type == THERMO_PRO_TX4_TYPE_2)) {
return true;
} else {
return false;
}
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_thermopro_tx4_remote_controller(WSBlockGeneric* instance) {
instance->id = (instance->data >> 25) & 0xFF;
instance->battery_low = (instance->data >> 24) & 1;
instance->btn = (instance->data >> 23) & 1;
instance->channel = ((instance->data >> 21) & 0x03) + 1;
if(!((instance->data >> 20) & 1)) {
instance->temp = (float)((instance->data >> 9) & 0x07FF) / 10.0f;
} else {
instance->temp = (float)((~(instance->data >> 9) & 0x07FF)+1) / -10.0f;
}
instance->humidity = (instance->data >> 1) & 0xFF;
}
void ws_protocol_decoder_thermopro_tx4_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
switch(instance->decoder.parser_step) {
case ThermoPRO_TX4DecoderStepReset:
if((!level) && (DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_short * 18) <
ws_protocol_thermopro_tx4_const.te_delta * 10)) {
//Found sync
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
}
break;
case ThermoPRO_TX4DecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepCheckDuration;
} else {
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset;
}
break;
case ThermoPRO_TX4DecoderStepCheckDuration:
if(!level) {
if(DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_short * 18) <
ws_protocol_thermopro_tx4_const.te_delta * 10) {
//Found sync
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset;
if((instance->decoder.decode_count_bit ==
ws_protocol_thermopro_tx4_const.min_count_bit_for_found) &&
ws_protocol_thermopro_tx4_check(instance)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_thermopro_tx4_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepCheckDuration;
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
break;
} else if(
(DURATION_DIFF(
instance->decoder.te_last, ws_protocol_thermopro_tx4_const.te_short) <
ws_protocol_thermopro_tx4_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_long) <
ws_protocol_thermopro_tx4_const.te_delta * 2)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration;
} else if(
(DURATION_DIFF(
instance->decoder.te_last, ws_protocol_thermopro_tx4_const.te_short) <
ws_protocol_thermopro_tx4_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_thermopro_tx4_const.te_long * 2) <
ws_protocol_thermopro_tx4_const.te_delta * 4)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepSaveDuration;
} else {
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset;
}
} else {
instance->decoder.parser_step = ThermoPRO_TX4DecoderStepReset;
}
break;
}
}
uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_thermopro_tx4_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
ws_protocol_thermopro_tx4_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderThermoPRO_TX4* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%d.%d C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(int16_t)instance->generic.temp,
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
instance->generic.humidity);
}

View file

@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_THERMOPRO_TX4_NAME "ThermoPRO-TX4"
typedef struct WSProtocolDecoderThermoPRO_TX4 WSProtocolDecoderThermoPRO_TX4;
typedef struct WSProtocolEncoderThermoPRO_TX4 WSProtocolEncoderThermoPRO_TX4;
extern const SubGhzProtocolDecoder ws_protocol_thermopro_tx4_decoder;
extern const SubGhzProtocolEncoder ws_protocol_thermopro_tx4_encoder;
extern const SubGhzProtocol ws_protocol_thermopro_tx4;
/**
* Allocate WSProtocolDecoderThermoPRO_TX4.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderThermoPRO_TX4* pointer to a WSProtocolDecoderThermoPRO_TX4 instance
*/
void* ws_protocol_decoder_thermopro_tx4_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderThermoPRO_TX4.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
*/
void ws_protocol_decoder_thermopro_tx4_free(void* context);
/**
* Reset decoder WSProtocolDecoderThermoPRO_TX4.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
*/
void ws_protocol_decoder_thermopro_tx4_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_thermopro_tx4_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderThermoPRO_TX4.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool ws_protocol_decoder_thermopro_tx4_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data WSProtocolDecoderThermoPRO_TX4.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
* @param output Resulting text
*/
void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output);

View file

@ -0,0 +1,198 @@
#include "ws_generic.h"
#include <lib/toolbox/stream/stream.h>
#include <lib/flipper_format/flipper_format_i.h>
#include "../helpers/weather_station_types.h"
#define TAG "WSBlockGeneric"
void ws_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);
}
bool ws_block_generic_serialize(
WSBlockGeneric* instance,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) {
furi_assert(instance);
bool res = false;
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, WS_KEY_FILE_TYPE, WS_KEY_FILE_VERSION)) {
FURI_LOG_E(TAG, "Unable to add header");
break;
}
if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
FURI_LOG_E(TAG, "Unable to add Frequency");
break;
}
ws_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");
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");
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");
break;
}
}
if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) {
FURI_LOG_E(TAG, "Unable to add Protocol");
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");
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");
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");
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");
break;
}
temp_data = instance->humidity;
if(!flipper_format_write_uint32(flipper_format, "Hum", &temp_data, 1)) {
FURI_LOG_E(TAG, "Unable to add Humidity");
break;
}
temp_data = instance->channel;
if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) {
FURI_LOG_E(TAG, "Unable to add Channel");
break;
}
// temp_data = instance->btn;
// if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) {
// FURI_LOG_E(TAG, "Unable to add Btn");
// break;
// }
float temp = instance->temp;
if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) {
FURI_LOG_E(TAG, "Unable to add Temperature");
break;
}
res = true;
} while(false);
furi_string_free(temp_str);
return res;
}
bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format) {
furi_assert(instance);
bool res = false;
uint32_t temp_data = 0;
do {
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(!flipper_format_read_uint32(flipper_format, "Id", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Id");
break;
}
instance->id = (uint32_t)temp_data;
if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Bit");
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");
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", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Battery_low");
break;
}
instance->battery_low = (uint8_t)temp_data;
if(!flipper_format_read_uint32(flipper_format, "Hum", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Humidity");
break;
}
instance->humidity = (uint8_t)temp_data;
if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Channel");
break;
}
instance->channel = (uint8_t)temp_data;
// if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) {
// FURI_LOG_E(TAG, "Missing Btn");
// break;
// }
// instance->btn = (uint8_t)temp_data;
float temp;
if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) {
FURI_LOG_E(TAG, "Missing Temperature");
break;
}
instance->temp = temp;
res = true;
} while(0);
return res;
}
float ws_block_generic_fahrenheit_to_celsius(float fahrenheit) {
return (fahrenheit - 32.0f) / 1.8f;
}

View file

@ -0,0 +1,61 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <lib/flipper_format/flipper_format.h>
#include "furi.h"
#include "furi_hal.h"
#include <lib/subghz/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct WSBlockGeneric WSBlockGeneric;
struct WSBlockGeneric {
const char* protocol_name;
uint64_t data;
uint32_t id;
uint8_t data_count_bit;
uint8_t battery_low;
uint8_t humidity;
uint8_t channel;
uint8_t btn;
float temp;
};
/**
* Get name preset.
* @param preset_name name preset
* @param preset_str Output name preset
*/
void ws_block_generic_get_preset_name(const char* preset_name, FuriString* preset_str);
/**
* Serialize data WSBlockGeneric.
* @param instance Pointer to a WSBlockGeneric instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool ws_block_generic_serialize(
WSBlockGeneric* instance,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data WSBlockGeneric.
* @param instance Pointer to a WSBlockGeneric instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format);
float ws_block_generic_fahrenheit_to_celsius(float fahrenheit);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,207 @@
#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));
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), "", "");
}
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);
}
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);
}

View file

@ -0,0 +1,30 @@
#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,
};

View file

@ -0,0 +1,29 @@
#pragma once
#include <gui/scene_manager.h>
// 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

View file

@ -0,0 +1,78 @@
#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 station 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);
}

View file

@ -0,0 +1,5 @@
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)

View file

@ -0,0 +1,223 @@
#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);
}

View file

@ -0,0 +1,50 @@
#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);
}

View file

@ -0,0 +1,58 @@
#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);
}

View file

@ -0,0 +1,437 @@
#include "weather_station_receiver.h"
#include "../weather_station_app_i.h"
#include "weather_station_icons.h"
#include <math.h>
#include <input/input.h>
#include <gui/elements.h>
#include <assets_icons.h>
#include <m-array.h>
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 100
#define MENU_ITEMS 4u
#define UNLOCK_CNT 3
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;
} WSReceiverModel;
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) {
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);
},
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);
}
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");
canvas_draw_line(canvas, 46, 51, 125, 51);
bool scrollbar = model->history_item > 4;
FuriString* str_buff;
str_buff = furi_string_alloc();
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, 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, &I_Scanning_123x52);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Scanning...");
canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_set_font(canvas, FontSecondary);
}
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->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));
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);
}

View file

@ -0,0 +1,36 @@
#pragma once
#include <gui/view.h>
#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_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);
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);

View file

@ -0,0 +1,150 @@
#include "weather_station_receiver.h"
#include "../weather_station_app_i.h"
#include "weather_station_icons.h"
#include "../protocols/ws_generic.h"
#include <input/input.h>
#include <gui/elements.h>
#include "math.h"
#define abs(x) ((x) > 0 ? (x) : -(x))
struct WSReceiverInfo {
View* view;
};
typedef struct {
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);
},
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, 5, 8, buffer);
snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel);
canvas_draw_str(canvas, 105, 8, buffer);
snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id);
canvas_draw_str(canvas, 5, 20, buffer);
snprintf(buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low"));
canvas_draw_str(canvas, 85, 20, buffer);
snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data);
canvas_draw_str(canvas, 5, 32, buffer);
elements_bold_rounded_frame(canvas, 2, 37, 123, 25);
canvas_set_font(canvas, FontPrimary);
canvas_draw_icon(canvas, 13 + 5, 42, &I_Therm_7x16);
snprintf(
buffer,
sizeof(buffer),
"%3.2d.%d C",
(int16_t)model->generic->temp,
abs(((int16_t)(model->generic->temp * 10) - (((int16_t)model->generic->temp) * 10))));
canvas_draw_str_aligned(canvas, 58 + 5, 46, AlignRight, AlignTop, buffer);
canvas_draw_circle(canvas, 50 + 5, 45, 1);
canvas_draw_icon(canvas, 70 + 5, 42, &I_Humid_10x15);
snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity);
canvas_draw_str(canvas, 86 + 5, 54, 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;
}
void ws_view_receiver_info_enter(void* context) {
furi_assert(context);
}
void ws_view_receiver_info_exit(void* context) {
furi_assert(context);
WSReceiverInfo* ws_receiver_info = context;
with_view_model(
ws_receiver_info->view,
WSReceiverInfoModel * model,
{ furi_string_reset(model->protocol_name); },
false);
}
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);
return ws_receiver_info;
}
void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info) {
furi_assert(ws_receiver_info);
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;
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <gui/view.h>
#include "../helpers/weather_station_types.h"
#include "../helpers/weather_station_event.h"
#include <lib/flipper_format/flipper_format.h>
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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

View file

@ -0,0 +1,178 @@
#include "weather_station_app_i.h"
#include <furi.h>
#include <furi_hal.h>
#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"), true);
//init Worker & Protocol & History
app->lock = WSLockOff;
app->txrx = malloc(sizeof(WeatherStationTxRx));
app->txrx->preset = malloc(sizeof(SubGhzPresetDefinition));
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_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);
//CC1101 off
ws_sleep(app);
// 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;
}

View file

@ -0,0 +1,159 @@
#include "weather_station_app_i.h"
#define TAG "WeatherStation"
#include <flipper_format/flipper_format_i.h>
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);
UNUSED(preset_data);
furi_hal_subghz_reset();
furi_hal_subghz_idle();
furi_hal_subghz_load_custom_preset(preset_data);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
app->txrx->txrx_state = WSTxRxStateIDLE;
}
uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) {
furi_assert(app);
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
furi_crash("WeatherStation: Incorrect RX frequency.");
}
furi_assert(
app->txrx->txrx_state != WSTxRxStateRx && app->txrx->txrx_state != WSTxRxStateSleep);
furi_hal_subghz_idle();
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_subghz_flush_rx();
furi_hal_subghz_rx();
furi_hal_subghz_start_async_rx(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);
furi_hal_subghz_idle();
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);
furi_hal_subghz_stop_async_rx();
}
furi_hal_subghz_idle();
app->txrx->txrx_state = WSTxRxStateIDLE;
}
void ws_sleep(WeatherStationApp* app) {
furi_assert(app);
furi_hal_subghz_sleep();
app->txrx->txrx_state = WSTxRxStateSleep;
}
void ws_hopper_update(WeatherStationApp* app) {
furi_assert(app);
switch(app->txrx->hopper_state) {
case WSHopperStateOFF:
return;
break;
case WSHopperStatePause:
return;
break;
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 = furi_hal_subghz_get_rssi();
// 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);
}
}

View file

@ -0,0 +1,73 @@
#pragma once
#include "helpers/weather_station_types.h"
#include "scenes/weather_station_scene.h"
#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/widget.h>
#include <notification/notification_messages.h>
#include "views/weather_station_receiver.h"
#include "views/weather_station_receiver_info.h"
#include "weather_station_history.h"
#include <lib/subghz/subghz_setting.h>
#include <lib/subghz/subghz_worker.h>
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#include <lib/subghz/registry.h>
typedef struct WeatherStationApp WeatherStationApp;
struct WeatherStationTxRx {
SubGhzWorker* worker;
SubGhzEnvironment* environment;
SubGhzReceiver* receiver;
SubGhzPresetDefinition* 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);

View file

@ -0,0 +1,247 @@
#include "weather_station_history.h"
#include <flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/stream.h>
#include <lib/subghz/receiver.h>
#include <furi.h>
#include <m-string.h>
#define WS_HISTORY_MAX 50
#define TAG "WSHistory"
typedef struct {
FuriString* item_str;
FlipperFormat* flipper_string;
uint8_t type;
uint32_t id;
SubGhzPresetDefinition* 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;
}
SubGhzPresetDefinition* ws_history_get_preset_def(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, SubGhzPresetDefinition* 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) {
WSHistoryItem* item = WSHistoryItemArray_push_raw(instance->history->data);
item->preset = malloc(sizeof(SubGhzPresetDefinition));
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];
}
if(!(uint32_t)(data >> 32)) {
furi_string_printf(
item->item_str,
"%s %lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data & 0xFFFFFFFF));
} else {
furi_string_printf(
item->item_str,
"%s %lX%08lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data >> 32),
(uint32_t)(data & 0xFFFFFFFF));
}
} while(false);
instance->last_index_write++;
return WSHistoryStateAddKeyNewDada;
}
return WSHistoryStateAddKeyUnknown;
}

View file

@ -0,0 +1,112 @@
#pragma once
#include <math.h>
#include <furi.h>
#include <furi_hal.h>
#include <lib/flipper_format/flipper_format.h>
#include <lib/subghz/types.h>
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);
SubGhzPresetDefinition* ws_history_get_preset_def(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 - SubGhzPresetDefinition preset
* @return WSHistoryStateAddKey;
*/
WSHistoryStateAddKey
ws_history_add_to_history(WSHistory* instance, void* context, SubGhzPresetDefinition* 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);

View file

@ -1,3 +1,4 @@
# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user
Filetype: Flipper SubGhz Setting File Filetype: Flipper SubGhz Setting File
Version: 1 Version: 1

View file

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,3.2,, Version,+,4.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@ -128,10 +128,16 @@ Header,+,lib/one_wire/one_wire_host.h,,
Header,+,lib/one_wire/one_wire_host_timing.h,, Header,+,lib/one_wire/one_wire_host_timing.h,,
Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/one_wire/one_wire_slave.h,,
Header,+,lib/print/wrappers.h,, Header,+,lib/print/wrappers.h,,
Header,+,lib/subghz/blocks/const.h,,
Header,+,lib/subghz/blocks/decoder.h,,
Header,+,lib/subghz/blocks/encoder.h,,
Header,+,lib/subghz/blocks/generic.h,,
Header,+,lib/subghz/blocks/math.h,,
Header,+,lib/subghz/environment.h,, Header,+,lib/subghz/environment.h,,
Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/protocols/raw.h,,
Header,+,lib/subghz/protocols/registry.h,,
Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/receiver.h,,
Header,+,lib/subghz/registry.h,,
Header,+,lib/subghz/subghz_setting.h,,
Header,+,lib/subghz/subghz_tx_rx_worker.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,,
Header,+,lib/subghz/subghz_worker.h,, Header,+,lib/subghz/subghz_worker.h,,
Header,+,lib/subghz/transmitter.h,, Header,+,lib/subghz/transmitter.h,,
@ -478,8 +484,6 @@ Function,-,atoff,float,const char*
Function,+,atoi,int,const char* Function,+,atoi,int,const char*
Function,-,atol,long,const char* Function,-,atol,long,const char*
Function,-,atoll,long long,const char* Function,-,atoll,long long,const char*
Function,-,atomo_decrypt,void,uint8_t*
Function,-,atomo_encrypt,void,uint8_t*
Function,-,basename,char*,const char* Function,-,basename,char*,const char*
Function,-,bcmp,int,"const void*, const void*, size_t" Function,-,bcmp,int,"const void*, const void*, size_t"
Function,-,bcopy,void,"const void*, void*, size_t" Function,-,bcopy,void,"const void*, void*, size_t"
@ -949,6 +953,7 @@ Function,+,furi_hal_bt_nvm_sram_sem_release,void,
Function,+,furi_hal_bt_reinit,void, Function,+,furi_hal_bt_reinit,void,
Function,+,furi_hal_bt_serial_notify_buffer_is_empty,void, Function,+,furi_hal_bt_serial_notify_buffer_is_empty,void,
Function,+,furi_hal_bt_serial_set_event_callback,void,"uint16_t, FuriHalBtSerialCallback, void*" Function,+,furi_hal_bt_serial_set_event_callback,void,"uint16_t, FuriHalBtSerialCallback, void*"
Function,+,furi_hal_bt_serial_set_rpc_status,void,FuriHalBtSerialRpcStatus
Function,+,furi_hal_bt_serial_start,void, Function,+,furi_hal_bt_serial_start,void,
Function,+,furi_hal_bt_serial_stop,void, Function,+,furi_hal_bt_serial_stop,void,
Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t" Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t"
@ -1587,8 +1592,6 @@ Function,-,j1f,float,float
Function,-,jn,double,"int, double" Function,-,jn,double,"int, double"
Function,-,jnf,float,"int, float" Function,-,jnf,float,"int, float"
Function,-,jrand48,long,unsigned short[3] Function,-,jrand48,long,unsigned short[3]
Function,-,keeloq_reset_kl_type,void,
Function,-,keeloq_reset_mfname,void,
Function,-,l64a,char*,long Function,-,l64a,char*,long
Function,-,labs,long,long Function,-,labs,long,long
Function,-,lcong48,void,unsigned short[7] Function,-,lcong48,void,unsigned short[7]
@ -2120,6 +2123,7 @@ Function,-,select,int,"int, fd_set*, fd_set*, fd_set*, timeval*"
Function,-,serial_svc_is_started,_Bool, Function,-,serial_svc_is_started,_Bool,
Function,-,serial_svc_notify_buffer_is_empty,void, Function,-,serial_svc_notify_buffer_is_empty,void,
Function,-,serial_svc_set_callbacks,void,"uint16_t, SerialServiceEventCallback, void*" Function,-,serial_svc_set_callbacks,void,"uint16_t, SerialServiceEventCallback, void*"
Function,+,serial_svc_set_rpc_status,void,SerialServiceRpcStatus
Function,-,serial_svc_start,void, Function,-,serial_svc_start,void,
Function,-,serial_svc_stop,void, Function,-,serial_svc_stop,void,
Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t" Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t"
@ -2156,8 +2160,6 @@ Function,+,srand,void,unsigned
Function,-,srand48,void,long Function,-,srand48,void,long
Function,-,srandom,void,unsigned Function,-,srandom,void,unsigned
Function,+,sscanf,int,"const char*, const char*, ..." Function,+,sscanf,int,"const char*, const char*, ..."
Function,-,star_line_reset_kl_type,void,
Function,-,star_line_reset_mfname,void,
Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*"
Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*" Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*"
Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*"
@ -2289,14 +2291,20 @@ Function,-,strupr,char*,char*
Function,-,strverscmp,int,"const char*, const char*" Function,-,strverscmp,int,"const char*, const char*"
Function,-,strxfrm,size_t,"char*, const char*, size_t" Function,-,strxfrm,size_t,"char*, const char*, size_t"
Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t" Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t"
Function,+,subghz_block_generic_deserialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*"
Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*"
Function,+,subghz_block_generic_serialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzPresetDefinition*"
Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_alloc,SubGhzEnvironment*,
Function,+,subghz_environment_free,void,SubGhzEnvironment* Function,+,subghz_environment_free,void,SubGhzEnvironment*
Function,-,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,-,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment*
Function,-,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment* Function,-,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment*
Function,-,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,-,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment*
Function,+,subghz_environment_get_protocol_name_registry,const char*,"SubGhzEnvironment*, size_t"
Function,+,subghz_environment_get_protocol_registry,void*,SubGhzEnvironment*
Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*"
Function,-,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,-,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
Function,-,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,-,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, void*"
Function,-,subghz_keystore_alloc,SubGhzKeystore*, Function,-,subghz_keystore_alloc,SubGhzKeystore*,
Function,-,subghz_keystore_free,void,SubGhzKeystore* Function,-,subghz_keystore_free,void,SubGhzKeystore*
Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore* Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore*
@ -2304,227 +2312,21 @@ Function,-,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*"
Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*" Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*"
Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t" Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t"
Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*"
Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t"
Function,+,subghz_protocol_blocks_crc4,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
Function,+,subghz_protocol_blocks_crc7,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
Function,+,subghz_protocol_blocks_crc8,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t"
Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t"
Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t"
Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t"
Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t"
Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t"
Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t"
Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*"
Function,-,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase*
Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*"
Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*" Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*"
Function,-,subghz_protocol_decoder_bett_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_bett_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_bett_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_bett_free,void,void*
Function,-,subghz_protocol_decoder_bett_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_bett_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_bett_reset,void,void*
Function,-,subghz_protocol_decoder_bett_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_came_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_came_atomo_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_came_atomo_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_came_atomo_free,void,void*
Function,-,subghz_protocol_decoder_came_atomo_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_came_atomo_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_came_atomo_reset,void,void*
Function,-,subghz_protocol_decoder_came_atomo_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_came_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_came_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_came_free,void,void*
Function,-,subghz_protocol_decoder_came_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_came_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_came_reset,void,void*
Function,-,subghz_protocol_decoder_came_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_came_twee_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_came_twee_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_came_twee_free,void,void*
Function,-,subghz_protocol_decoder_came_twee_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_came_twee_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_came_twee_reset,void,void*
Function,-,subghz_protocol_decoder_came_twee_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_chamb_code_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_chamb_code_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_chamb_code_free,void,void*
Function,-,subghz_protocol_decoder_chamb_code_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_chamb_code_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_chamb_code_reset,void,void*
Function,-,subghz_protocol_decoder_chamb_code_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_clemsa_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_clemsa_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_clemsa_free,void,void*
Function,-,subghz_protocol_decoder_clemsa_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_clemsa_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_clemsa_reset,void,void*
Function,-,subghz_protocol_decoder_clemsa_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_doitrand_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_doitrand_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_doitrand_free,void,void*
Function,-,subghz_protocol_decoder_doitrand_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_doitrand_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_doitrand_reset,void,void*
Function,-,subghz_protocol_decoder_doitrand_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_faac_slh_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_faac_slh_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_faac_slh_free,void,void*
Function,-,subghz_protocol_decoder_faac_slh_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_faac_slh_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_faac_slh_reset,void,void*
Function,-,subghz_protocol_decoder_faac_slh_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_gate_tx_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_gate_tx_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_gate_tx_free,void,void*
Function,-,subghz_protocol_decoder_gate_tx_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_gate_tx_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_gate_tx_reset,void,void*
Function,-,subghz_protocol_decoder_gate_tx_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_holtek_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_holtek_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_holtek_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_holtek_free,void,void*
Function,-,subghz_protocol_decoder_holtek_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_holtek_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_holtek_reset,void,void*
Function,-,subghz_protocol_decoder_holtek_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_honeywell_wdb_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_honeywell_wdb_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_honeywell_wdb_free,void,void*
Function,-,subghz_protocol_decoder_honeywell_wdb_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_honeywell_wdb_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_honeywell_wdb_reset,void,void*
Function,-,subghz_protocol_decoder_honeywell_wdb_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_hormann_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_hormann_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_hormann_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_hormann_free,void,void*
Function,-,subghz_protocol_decoder_hormann_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_hormann_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_hormann_reset,void,void*
Function,-,subghz_protocol_decoder_hormann_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_ido_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_ido_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_ido_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_ido_free,void,void*
Function,-,subghz_protocol_decoder_ido_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_ido_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_ido_reset,void,void*
Function,-,subghz_protocol_decoder_ido_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_intertechno_v3_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_intertechno_v3_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_intertechno_v3_free,void,void*
Function,-,subghz_protocol_decoder_intertechno_v3_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_intertechno_v3_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_intertechno_v3_reset,void,void*
Function,-,subghz_protocol_decoder_intertechno_v3_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_keeloq_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_keeloq_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_keeloq_free,void,void*
Function,-,subghz_protocol_decoder_keeloq_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_keeloq_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_keeloq_reset,void,void*
Function,-,subghz_protocol_decoder_keeloq_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_kia_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_kia_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_kia_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_kia_free,void,void*
Function,-,subghz_protocol_decoder_kia_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_kia_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_kia_reset,void,void*
Function,-,subghz_protocol_decoder_kia_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_linear_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_linear_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_linear_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_linear_free,void,void*
Function,-,subghz_protocol_decoder_linear_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_linear_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_linear_reset,void,void*
Function,-,subghz_protocol_decoder_linear_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_magellen_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_magellen_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_magellen_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_magellen_free,void,void*
Function,-,subghz_protocol_decoder_magellen_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_magellen_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_magellen_reset,void,void*
Function,-,subghz_protocol_decoder_magellen_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_marantec_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_marantec_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_marantec_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_marantec_free,void,void*
Function,-,subghz_protocol_decoder_marantec_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_marantec_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_marantec_reset,void,void*
Function,-,subghz_protocol_decoder_marantec_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_megacode_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_megacode_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_megacode_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_megacode_free,void,void*
Function,-,subghz_protocol_decoder_megacode_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_megacode_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_megacode_reset,void,void*
Function,-,subghz_protocol_decoder_megacode_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_nero_radio_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_nero_radio_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_nero_radio_free,void,void*
Function,-,subghz_protocol_decoder_nero_radio_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_nero_radio_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_nero_radio_reset,void,void*
Function,-,subghz_protocol_decoder_nero_radio_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_nero_sketch_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_nero_sketch_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_nero_sketch_free,void,void*
Function,-,subghz_protocol_decoder_nero_sketch_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_nero_sketch_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_nero_sketch_reset,void,void*
Function,-,subghz_protocol_decoder_nero_sketch_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_nice_flo_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_nice_flo_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_nice_flo_free,void,void*
Function,-,subghz_protocol_decoder_nice_flo_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_nice_flo_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_nice_flo_reset,void,void*
Function,-,subghz_protocol_decoder_nice_flo_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_nice_flor_s_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_nice_flor_s_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_nice_flor_s_free,void,void*
Function,-,subghz_protocol_decoder_nice_flor_s_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_nice_flor_s_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_nice_flor_s_reset,void,void*
Function,-,subghz_protocol_decoder_nice_flor_s_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_phoenix_v2_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_phoenix_v2_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_phoenix_v2_free,void,void*
Function,-,subghz_protocol_decoder_phoenix_v2_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_phoenix_v2_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_phoenix_v2_reset,void,void*
Function,-,subghz_protocol_decoder_phoenix_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_power_smart_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_power_smart_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_power_smart_free,void,void*
Function,-,subghz_protocol_decoder_power_smart_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_power_smart_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_power_smart_reset,void,void*
Function,-,subghz_protocol_decoder_power_smart_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_princeton_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_princeton_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_princeton_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_princeton_free,void,void*
Function,-,subghz_protocol_decoder_princeton_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_princeton_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_princeton_reset,void,void*
Function,-,subghz_protocol_decoder_princeton_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t"
@ -2536,215 +2338,20 @@ Function,-,subghz_protocol_decoder_raw_serialize,_Bool,"void*, FlipperFormat*, S
Function,-,subghz_protocol_decoder_raw_set_auto_mode,void,"void*, _Bool" Function,-,subghz_protocol_decoder_raw_set_auto_mode,void,"void*, _Bool"
Function,-,subghz_protocol_decoder_raw_set_rssi_threshold,void,"void*, int" Function,-,subghz_protocol_decoder_raw_set_rssi_threshold,void,"void*, int"
Function,-,subghz_protocol_decoder_raw_write_data,_Bool,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_raw_write_data,_Bool,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_scher_khan_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_scher_khan_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_scher_khan_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_scher_khan_free,void,void*
Function,-,subghz_protocol_decoder_scher_khan_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_scher_khan_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_scher_khan_reset,void,void*
Function,-,subghz_protocol_decoder_scher_khan_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_secplus_v1_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_secplus_v1_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_secplus_v1_free,void,void*
Function,-,subghz_protocol_decoder_secplus_v1_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_secplus_v1_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_secplus_v1_reset,void,void*
Function,-,subghz_protocol_decoder_secplus_v1_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_secplus_v2_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_secplus_v2_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_secplus_v2_free,void,void*
Function,-,subghz_protocol_decoder_secplus_v2_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_secplus_v2_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_secplus_v2_reset,void,void*
Function,-,subghz_protocol_decoder_secplus_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_somfy_keytis_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_somfy_keytis_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_somfy_keytis_free,void,void*
Function,-,subghz_protocol_decoder_somfy_keytis_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_somfy_keytis_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_somfy_keytis_reset,void,void*
Function,-,subghz_protocol_decoder_somfy_keytis_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_somfy_telis_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_somfy_telis_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_somfy_telis_free,void,void*
Function,-,subghz_protocol_decoder_somfy_telis_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_somfy_telis_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_somfy_telis_reset,void,void*
Function,-,subghz_protocol_decoder_somfy_telis_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_decoder_star_line_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_star_line_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_star_line_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_star_line_free,void,void*
Function,-,subghz_protocol_decoder_star_line_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_star_line_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_star_line_reset,void,void*
Function,-,subghz_protocol_decoder_star_line_serialize,_Bool,"void*, FlipperFormat*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_encoder_bett_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_bett_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_bett_free,void,void*
Function,-,subghz_protocol_encoder_bett_stop,void,void*
Function,-,subghz_protocol_encoder_bett_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_came_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_came_atomo_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_came_atomo_free,void,void*
Function,-,subghz_protocol_encoder_came_atomo_stop,void,void*
Function,-,subghz_protocol_encoder_came_atomo_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_came_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_came_free,void,void*
Function,-,subghz_protocol_encoder_came_stop,void,void*
Function,-,subghz_protocol_encoder_came_twee_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_came_twee_free,void,void*
Function,-,subghz_protocol_encoder_came_twee_stop,void,void*
Function,-,subghz_protocol_encoder_came_twee_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_came_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_chamb_code_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_chamb_code_free,void,void*
Function,-,subghz_protocol_encoder_chamb_code_stop,void,void*
Function,-,subghz_protocol_encoder_chamb_code_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_clemsa_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_clemsa_free,void,void*
Function,-,subghz_protocol_encoder_clemsa_stop,void,void*
Function,-,subghz_protocol_encoder_clemsa_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_doitrand_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_doitrand_free,void,void*
Function,-,subghz_protocol_encoder_doitrand_stop,void,void*
Function,-,subghz_protocol_encoder_doitrand_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_faac_slh_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_faac_slh_free,void,void*
Function,-,subghz_protocol_encoder_faac_slh_stop,void,void*
Function,-,subghz_protocol_encoder_faac_slh_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_gate_tx_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_gate_tx_free,void,void*
Function,-,subghz_protocol_encoder_gate_tx_stop,void,void*
Function,-,subghz_protocol_encoder_gate_tx_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_get_rssi_threshold,int,void* Function,-,subghz_protocol_encoder_get_rssi_threshold,int,void*
Function,-,subghz_protocol_encoder_holtek_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_holtek_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_holtek_free,void,void*
Function,-,subghz_protocol_encoder_holtek_stop,void,void*
Function,-,subghz_protocol_encoder_holtek_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_honeywell_wdb_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_honeywell_wdb_free,void,void*
Function,-,subghz_protocol_encoder_honeywell_wdb_stop,void,void*
Function,-,subghz_protocol_encoder_honeywell_wdb_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_hormann_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_hormann_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_hormann_free,void,void*
Function,-,subghz_protocol_encoder_hormann_stop,void,void*
Function,-,subghz_protocol_encoder_hormann_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_intertechno_v3_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_intertechno_v3_free,void,void*
Function,-,subghz_protocol_encoder_intertechno_v3_stop,void,void*
Function,-,subghz_protocol_encoder_intertechno_v3_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_keeloq_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_keeloq_free,void,void*
Function,-,subghz_protocol_encoder_keeloq_stop,void,void*
Function,-,subghz_protocol_encoder_keeloq_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_linear_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_linear_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_linear_free,void,void*
Function,-,subghz_protocol_encoder_linear_stop,void,void*
Function,-,subghz_protocol_encoder_linear_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_magellen_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_magellen_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_magellen_free,void,void*
Function,-,subghz_protocol_encoder_magellen_stop,void,void*
Function,-,subghz_protocol_encoder_magellen_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_marantec_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_marantec_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_marantec_free,void,void*
Function,-,subghz_protocol_encoder_marantec_stop,void,void*
Function,-,subghz_protocol_encoder_marantec_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_megacode_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_megacode_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_megacode_free,void,void*
Function,-,subghz_protocol_encoder_megacode_stop,void,void*
Function,-,subghz_protocol_encoder_megacode_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_nero_radio_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_nero_radio_free,void,void*
Function,-,subghz_protocol_encoder_nero_radio_stop,void,void*
Function,-,subghz_protocol_encoder_nero_radio_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_nero_sketch_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_nero_sketch_free,void,void*
Function,-,subghz_protocol_encoder_nero_sketch_stop,void,void*
Function,-,subghz_protocol_encoder_nero_sketch_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_nice_flo_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_nice_flo_free,void,void*
Function,-,subghz_protocol_encoder_nice_flo_stop,void,void*
Function,-,subghz_protocol_encoder_nice_flo_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_nice_flor_s_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_nice_flor_s_free,void,void*
Function,-,subghz_protocol_encoder_nice_flor_s_stop,void,void*
Function,-,subghz_protocol_encoder_nice_flor_s_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_phoenix_v2_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_phoenix_v2_free,void,void*
Function,-,subghz_protocol_encoder_phoenix_v2_stop,void,void*
Function,-,subghz_protocol_encoder_phoenix_v2_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_power_smart_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_power_smart_free,void,void*
Function,-,subghz_protocol_encoder_power_smart_stop,void,void*
Function,-,subghz_protocol_encoder_power_smart_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_princeton_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_princeton_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_princeton_free,void,void*
Function,-,subghz_protocol_encoder_princeton_stop,void,void*
Function,-,subghz_protocol_encoder_princeton_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_raw_free,void,void* Function,-,subghz_protocol_encoder_raw_free,void,void*
Function,-,subghz_protocol_encoder_raw_stop,void,void* Function,-,subghz_protocol_encoder_raw_stop,void,void*
Function,-,subghz_protocol_encoder_raw_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_raw_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_secplus_v1_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_secplus_v1_free,void,void*
Function,-,subghz_protocol_encoder_secplus_v1_stop,void,void*
Function,-,subghz_protocol_encoder_secplus_v1_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_secplus_v2_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_secplus_v2_free,void,void*
Function,-,subghz_protocol_encoder_secplus_v2_stop,void,void*
Function,-,subghz_protocol_encoder_secplus_v2_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_star_line_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_star_line_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_star_line_free,void,void*
Function,-,subghz_protocol_encoder_star_line_stop,void,void*
Function,-,subghz_protocol_encoder_star_line_yield,LevelDuration,void*
Function,-,subghz_protocol_faac_slh_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, uint32_t, const char*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_keeloq_bft_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, uint32_t, const char*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_keeloq_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_nice_flor_s_encrypt,uint64_t,"uint64_t, const char*"
Function,-,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" Function,-,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*"
Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*"
Function,-,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* Function,-,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW*
Function,-,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzPresetDefinition*" Function,-,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzPresetDefinition*"
Function,-,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* Function,-,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW*
Function,-,subghz_protocol_registry_count,size_t, Function,+,subghz_protocol_registry_count,size_t,const SubGhzProtocolRegistry*
Function,-,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,size_t Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, size_t"
Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,const char* Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*"
Function,-,subghz_protocol_secplus_v1_check_fixed,_Bool,uint32_t
Function,-,subghz_protocol_secplus_v2_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzPresetDefinition*"
Function,-,subghz_protocol_star_line_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzPresetDefinition*"
Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment*
Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t"
Function,+,subghz_receiver_free,void,SubGhzReceiver* Function,+,subghz_receiver_free,void,SubGhzReceiver*
@ -2753,6 +2360,24 @@ Function,+,subghz_receiver_reset,void,SubGhzReceiver*
Function,+,subghz_receiver_search_decoder_base_by_name,SubGhzProtocolDecoderBase*,"SubGhzReceiver*, const char*" Function,+,subghz_receiver_search_decoder_base_by_name,SubGhzProtocolDecoderBase*,"SubGhzReceiver*, const char*"
Function,+,subghz_receiver_set_filter,void,"SubGhzReceiver*, SubGhzProtocolFlag" Function,+,subghz_receiver_set_filter,void,"SubGhzReceiver*, SubGhzProtocolFlag"
Function,+,subghz_receiver_set_rx_callback,void,"SubGhzReceiver*, SubGhzReceiverCallback, void*" Function,+,subghz_receiver_set_rx_callback,void,"SubGhzReceiver*, SubGhzReceiverCallback, void*"
Function,+,subghz_setting_alloc,SubGhzSetting*,
Function,+,subghz_setting_delete_custom_preset,_Bool,"SubGhzSetting*, const char*"
Function,+,subghz_setting_free,void,SubGhzSetting*
Function,+,subghz_setting_get_default_frequency,uint32_t,SubGhzSetting*
Function,+,subghz_setting_get_frequency,uint32_t,"SubGhzSetting*, size_t"
Function,+,subghz_setting_get_frequency_count,size_t,SubGhzSetting*
Function,+,subghz_setting_get_frequency_default_index,uint32_t,SubGhzSetting*
Function,+,subghz_setting_get_hopper_frequency,uint32_t,"SubGhzSetting*, size_t"
Function,+,subghz_setting_get_hopper_frequency_count,size_t,SubGhzSetting*
Function,+,subghz_setting_get_inx_preset_by_name,int,"SubGhzSetting*, const char*"
Function,+,subghz_setting_get_preset_count,size_t,SubGhzSetting*
Function,+,subghz_setting_get_preset_data,uint8_t*,"SubGhzSetting*, size_t"
Function,+,subghz_setting_get_preset_data_by_name,uint8_t*,"SubGhzSetting*, const char*"
Function,+,subghz_setting_get_preset_data_size,size_t,"SubGhzSetting*, size_t"
Function,+,subghz_setting_get_preset_name,const char*,"SubGhzSetting*, size_t"
Function,+,subghz_setting_load,void,"SubGhzSetting*, const char*, _Bool"
Function,+,subghz_setting_load_custom_preset,_Bool,"SubGhzSetting*, const char*, FlipperFormat*"
Function,+,subghz_setting_set_default_frequency,void,"SubGhzSetting*, uint32_t"
Function,+,subghz_transmitter_alloc_init,SubGhzTransmitter*,"SubGhzEnvironment*, const char*" Function,+,subghz_transmitter_alloc_init,SubGhzTransmitter*,"SubGhzEnvironment*, const char*"
Function,+,subghz_transmitter_deserialize,_Bool,"SubGhzTransmitter*, FlipperFormat*" Function,+,subghz_transmitter_deserialize,_Bool,"SubGhzTransmitter*, FlipperFormat*"
Function,+,subghz_transmitter_free,void,SubGhzTransmitter* Function,+,subghz_transmitter_free,void,SubGhzTransmitter*
@ -4602,109 +4227,9 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence,
Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence,
Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence,
Variable,+,sequence_success,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence,
Variable,-,subghz_protocol_bett,const SubGhzProtocol,
Variable,-,subghz_protocol_bett_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_bett_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_came,const SubGhzProtocol,
Variable,-,subghz_protocol_came_atomo,const SubGhzProtocol,
Variable,-,subghz_protocol_came_atomo_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_came_atomo_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_came_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_came_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_came_twee,const SubGhzProtocol,
Variable,-,subghz_protocol_came_twee_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_came_twee_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_chamb_code,const SubGhzProtocol,
Variable,-,subghz_protocol_chamb_code_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_chamb_code_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_clemsa,const SubGhzProtocol,
Variable,-,subghz_protocol_clemsa_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_clemsa_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_doitrand,const SubGhzProtocol,
Variable,-,subghz_protocol_doitrand_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_doitrand_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_faac_slh,const SubGhzProtocol,
Variable,-,subghz_protocol_faac_slh_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_faac_slh_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_gate_tx,const SubGhzProtocol,
Variable,-,subghz_protocol_gate_tx_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_gate_tx_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_holtek,const SubGhzProtocol,
Variable,-,subghz_protocol_holtek_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_holtek_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_honeywell_wdb,const SubGhzProtocol,
Variable,-,subghz_protocol_honeywell_wdb_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_honeywell_wdb_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_hormann,const SubGhzProtocol,
Variable,-,subghz_protocol_hormann_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_hormann_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_ido,const SubGhzProtocol,
Variable,-,subghz_protocol_ido_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_ido_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_intertechno_v3,const SubGhzProtocol,
Variable,-,subghz_protocol_intertechno_v3_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_intertechno_v3_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_keeloq,const SubGhzProtocol,
Variable,-,subghz_protocol_keeloq_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_keeloq_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_kia,const SubGhzProtocol,
Variable,-,subghz_protocol_kia_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_kia_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_linear,const SubGhzProtocol,
Variable,-,subghz_protocol_linear_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_linear_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_magellen,const SubGhzProtocol,
Variable,-,subghz_protocol_magellen_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_magellen_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_marantec,const SubGhzProtocol,
Variable,-,subghz_protocol_marantec_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_marantec_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_megacode,const SubGhzProtocol,
Variable,-,subghz_protocol_megacode_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_megacode_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_nero_radio,const SubGhzProtocol,
Variable,-,subghz_protocol_nero_radio_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_nero_radio_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_nero_sketch,const SubGhzProtocol,
Variable,-,subghz_protocol_nero_sketch_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_nero_sketch_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_nice_flo,const SubGhzProtocol,
Variable,-,subghz_protocol_nice_flo_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_nice_flo_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_nice_flor_s,const SubGhzProtocol,
Variable,-,subghz_protocol_nice_flor_s_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_nice_flor_s_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_oregon2,const SubGhzProtocol,
Variable,-,subghz_protocol_phoenix_v2,const SubGhzProtocol,
Variable,-,subghz_protocol_phoenix_v2_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_phoenix_v2_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_power_smart,const SubGhzProtocol,
Variable,-,subghz_protocol_power_smart_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_power_smart_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_princeton,const SubGhzProtocol,
Variable,-,subghz_protocol_princeton_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_princeton_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_raw,const SubGhzProtocol, Variable,-,subghz_protocol_raw,const SubGhzProtocol,
Variable,-,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_scher_khan,const SubGhzProtocol,
Variable,-,subghz_protocol_scher_khan_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_scher_khan_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_secplus_v1,const SubGhzProtocol,
Variable,-,subghz_protocol_secplus_v1_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_secplus_v1_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_secplus_v2,const SubGhzProtocol,
Variable,-,subghz_protocol_secplus_v2_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_secplus_v2_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_somfy_keytis,const SubGhzProtocol,
Variable,-,subghz_protocol_somfy_keytis_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_somfy_keytis_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_somfy_telis,const SubGhzProtocol,
Variable,-,subghz_protocol_somfy_telis_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_somfy_telis_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_star_line,const SubGhzProtocol,
Variable,-,subghz_protocol_star_line_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_star_line_encoder,const SubGhzProtocolEncoder,
Variable,-,suboptarg,char*, Variable,-,suboptarg,char*,
Variable,-,u8g2_cb_mirror,const u8g2_cb_t, Variable,-,u8g2_cb_mirror,const u8g2_cb_t,
Variable,-,u8g2_cb_r0,const u8g2_cb_t, Variable,-,u8g2_cb_r0,const u8g2_cb_t,

1 entry status name type params
2 Version + 3.2 4.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
128 Header + lib/one_wire/one_wire_host_timing.h
129 Header + lib/one_wire/one_wire_slave.h
130 Header + lib/print/wrappers.h
131 Header + lib/subghz/blocks/const.h
132 Header + lib/subghz/blocks/decoder.h
133 Header + lib/subghz/blocks/encoder.h
134 Header + lib/subghz/blocks/generic.h
135 Header + lib/subghz/blocks/math.h
136 Header + lib/subghz/environment.h
137 Header + lib/subghz/protocols/raw.h
Header + lib/subghz/protocols/registry.h
138 Header + lib/subghz/receiver.h
139 Header + lib/subghz/registry.h
140 Header + lib/subghz/subghz_setting.h
141 Header + lib/subghz/subghz_tx_rx_worker.h
142 Header + lib/subghz/subghz_worker.h
143 Header + lib/subghz/transmitter.h
484 Function + atoi int const char*
485 Function - atol long const char*
486 Function - atoll long long const char*
Function - atomo_decrypt void uint8_t*
Function - atomo_encrypt void uint8_t*
487 Function - basename char* const char*
488 Function - bcmp int const void*, const void*, size_t
489 Function - bcopy void const void*, void*, size_t
953 Function + furi_hal_bt_reinit void
954 Function + furi_hal_bt_serial_notify_buffer_is_empty void
955 Function + furi_hal_bt_serial_set_event_callback void uint16_t, FuriHalBtSerialCallback, void*
956 Function + furi_hal_bt_serial_set_rpc_status void FuriHalBtSerialRpcStatus
957 Function + furi_hal_bt_serial_start void
958 Function + furi_hal_bt_serial_stop void
959 Function + furi_hal_bt_serial_tx _Bool uint8_t*, uint16_t
1592 Function - jn double int, double
1593 Function - jnf float int, float
1594 Function - jrand48 long unsigned short[3]
Function - keeloq_reset_kl_type void
Function - keeloq_reset_mfname void
1595 Function - l64a char* long
1596 Function - labs long long
1597 Function - lcong48 void unsigned short[7]
2123 Function - serial_svc_is_started _Bool
2124 Function - serial_svc_notify_buffer_is_empty void
2125 Function - serial_svc_set_callbacks void uint16_t, SerialServiceEventCallback, void*
2126 Function + serial_svc_set_rpc_status void SerialServiceRpcStatus
2127 Function - serial_svc_start void
2128 Function - serial_svc_stop void
2129 Function - serial_svc_update_tx _Bool uint8_t*, uint16_t
2160 Function - srand48 void long
2161 Function - srandom void unsigned
2162 Function + sscanf int const char*, const char*, ...
Function - star_line_reset_kl_type void
Function - star_line_reset_mfname void
2163 Function + storage_common_copy FS_Error Storage*, const char*, const char*
2164 Function + storage_common_fs_info FS_Error Storage*, const char*, uint64_t*, uint64_t*
2165 Function + storage_common_merge FS_Error Storage*, const char*, const char*
2291 Function - strverscmp int const char*, const char*
2292 Function - strxfrm size_t char*, const char*, size_t
2293 Function - strxfrm_l size_t char*, const char*, size_t, locale_t
2294 Function + subghz_block_generic_deserialize _Bool SubGhzBlockGeneric*, FlipperFormat*
2295 Function + subghz_block_generic_get_preset_name void const char*, FuriString*
2296 Function + subghz_block_generic_serialize _Bool SubGhzBlockGeneric*, FlipperFormat*, SubGhzPresetDefinition*
2297 Function + subghz_environment_alloc SubGhzEnvironment*
2298 Function + subghz_environment_free void SubGhzEnvironment*
2299 Function - subghz_environment_get_came_atomo_rainbow_table_file_name const char* SubGhzEnvironment*
2300 Function - subghz_environment_get_keystore SubGhzKeystore* SubGhzEnvironment*
2301 Function - subghz_environment_get_nice_flor_s_rainbow_table_file_name const char* SubGhzEnvironment*
2302 Function + subghz_environment_get_protocol_name_registry const char* SubGhzEnvironment*, size_t
2303 Function + subghz_environment_get_protocol_registry void* SubGhzEnvironment*
2304 Function + subghz_environment_load_keystore _Bool SubGhzEnvironment*, const char*
2305 Function - subghz_environment_set_came_atomo_rainbow_table_file_name void SubGhzEnvironment*, const char*
2306 Function - subghz_environment_set_nice_flor_s_rainbow_table_file_name void SubGhzEnvironment*, const char*
2307 Function + subghz_environment_set_protocol_registry void SubGhzEnvironment*, void*
2308 Function - subghz_keystore_alloc SubGhzKeystore*
2309 Function - subghz_keystore_free void SubGhzKeystore*
2310 Function - subghz_keystore_get_data SubGhzKeyArray_t* SubGhzKeystore*
2312 Function - subghz_keystore_raw_encrypted_save _Bool const char*, const char*, uint8_t*
2313 Function - subghz_keystore_raw_get_data _Bool const char*, size_t, uint8_t*, size_t
2314 Function - subghz_keystore_save _Bool SubGhzKeystore*, const char*, uint8_t*
2315 Function + subghz_protocol_blocks_add_bit void SubGhzBlockDecoder*, uint8_t
2316 Function + subghz_protocol_blocks_crc4 uint8_t const uint8_t[], unsigned, uint8_t, uint8_t
2317 Function + subghz_protocol_blocks_crc7 uint8_t const uint8_t[], unsigned, uint8_t, uint8_t
2318 Function + subghz_protocol_blocks_crc8 uint8_t const uint8_t[], unsigned, uint8_t, uint8_t
2319 Function + subghz_protocol_blocks_get_bit_array _Bool uint8_t[], size_t
2320 Function + subghz_protocol_blocks_get_hash_data uint8_t SubGhzBlockDecoder*, size_t
2321 Function + subghz_protocol_blocks_get_parity uint8_t uint64_t, uint8_t
2322 Function + subghz_protocol_blocks_get_upload size_t uint8_t[], size_t, LevelDuration*, size_t, uint32_t
2323 Function + subghz_protocol_blocks_reverse_key uint64_t uint64_t, uint8_t
2324 Function + subghz_protocol_blocks_set_bit_array void _Bool, uint8_t[], size_t, size_t
2325 Function - subghz_protocol_decoder_base_deserialize _Bool SubGhzProtocolDecoderBase*, FlipperFormat*
2326 Function - + subghz_protocol_decoder_base_get_hash_data uint8_t SubGhzProtocolDecoderBase*
2327 Function - subghz_protocol_decoder_base_get_string _Bool SubGhzProtocolDecoderBase*, FuriString*
2328 Function + subghz_protocol_decoder_base_serialize _Bool SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*
2329 Function - subghz_protocol_decoder_base_set_decoder_callback void SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*
Function - subghz_protocol_decoder_bett_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_bett_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_bett_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_bett_free void void*
Function - subghz_protocol_decoder_bett_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_bett_get_string void void*, FuriString*
Function - subghz_protocol_decoder_bett_reset void void*
Function - subghz_protocol_decoder_bett_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_came_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_came_atomo_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_came_atomo_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_came_atomo_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_came_atomo_free void void*
Function - subghz_protocol_decoder_came_atomo_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_came_atomo_get_string void void*, FuriString*
Function - subghz_protocol_decoder_came_atomo_reset void void*
Function - subghz_protocol_decoder_came_atomo_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_came_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_came_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_came_free void void*
Function - subghz_protocol_decoder_came_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_came_get_string void void*, FuriString*
Function - subghz_protocol_decoder_came_reset void void*
Function - subghz_protocol_decoder_came_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_came_twee_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_came_twee_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_came_twee_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_came_twee_free void void*
Function - subghz_protocol_decoder_came_twee_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_came_twee_get_string void void*, FuriString*
Function - subghz_protocol_decoder_came_twee_reset void void*
Function - subghz_protocol_decoder_came_twee_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_chamb_code_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_chamb_code_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_chamb_code_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_chamb_code_free void void*
Function - subghz_protocol_decoder_chamb_code_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_chamb_code_get_string void void*, FuriString*
Function - subghz_protocol_decoder_chamb_code_reset void void*
Function - subghz_protocol_decoder_chamb_code_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_clemsa_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_clemsa_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_clemsa_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_clemsa_free void void*
Function - subghz_protocol_decoder_clemsa_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_clemsa_get_string void void*, FuriString*
Function - subghz_protocol_decoder_clemsa_reset void void*
Function - subghz_protocol_decoder_clemsa_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_doitrand_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_doitrand_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_doitrand_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_doitrand_free void void*
Function - subghz_protocol_decoder_doitrand_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_doitrand_get_string void void*, FuriString*
Function - subghz_protocol_decoder_doitrand_reset void void*
Function - subghz_protocol_decoder_doitrand_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_faac_slh_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_faac_slh_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_faac_slh_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_faac_slh_free void void*
Function - subghz_protocol_decoder_faac_slh_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_faac_slh_get_string void void*, FuriString*
Function - subghz_protocol_decoder_faac_slh_reset void void*
Function - subghz_protocol_decoder_faac_slh_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_gate_tx_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_gate_tx_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_gate_tx_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_gate_tx_free void void*
Function - subghz_protocol_decoder_gate_tx_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_gate_tx_get_string void void*, FuriString*
Function - subghz_protocol_decoder_gate_tx_reset void void*
Function - subghz_protocol_decoder_gate_tx_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_holtek_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_holtek_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_holtek_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_holtek_free void void*
Function - subghz_protocol_decoder_holtek_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_holtek_get_string void void*, FuriString*
Function - subghz_protocol_decoder_holtek_reset void void*
Function - subghz_protocol_decoder_holtek_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_honeywell_wdb_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_honeywell_wdb_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_honeywell_wdb_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_honeywell_wdb_free void void*
Function - subghz_protocol_decoder_honeywell_wdb_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_honeywell_wdb_get_string void void*, FuriString*
Function - subghz_protocol_decoder_honeywell_wdb_reset void void*
Function - subghz_protocol_decoder_honeywell_wdb_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_hormann_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_hormann_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_hormann_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_hormann_free void void*
Function - subghz_protocol_decoder_hormann_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_hormann_get_string void void*, FuriString*
Function - subghz_protocol_decoder_hormann_reset void void*
Function - subghz_protocol_decoder_hormann_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_ido_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_ido_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_ido_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_ido_free void void*
Function - subghz_protocol_decoder_ido_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_ido_get_string void void*, FuriString*
Function - subghz_protocol_decoder_ido_reset void void*
Function - subghz_protocol_decoder_ido_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_intertechno_v3_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_intertechno_v3_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_intertechno_v3_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_intertechno_v3_free void void*
Function - subghz_protocol_decoder_intertechno_v3_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_intertechno_v3_get_string void void*, FuriString*
Function - subghz_protocol_decoder_intertechno_v3_reset void void*
Function - subghz_protocol_decoder_intertechno_v3_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_keeloq_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_keeloq_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_keeloq_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_keeloq_free void void*
Function - subghz_protocol_decoder_keeloq_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_keeloq_get_string void void*, FuriString*
Function - subghz_protocol_decoder_keeloq_reset void void*
Function - subghz_protocol_decoder_keeloq_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_kia_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_kia_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_kia_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_kia_free void void*
Function - subghz_protocol_decoder_kia_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_kia_get_string void void*, FuriString*
Function - subghz_protocol_decoder_kia_reset void void*
Function - subghz_protocol_decoder_kia_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_linear_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_linear_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_linear_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_linear_free void void*
Function - subghz_protocol_decoder_linear_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_linear_get_string void void*, FuriString*
Function - subghz_protocol_decoder_linear_reset void void*
Function - subghz_protocol_decoder_linear_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_magellen_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_magellen_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_magellen_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_magellen_free void void*
Function - subghz_protocol_decoder_magellen_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_magellen_get_string void void*, FuriString*
Function - subghz_protocol_decoder_magellen_reset void void*
Function - subghz_protocol_decoder_magellen_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_marantec_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_marantec_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_marantec_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_marantec_free void void*
Function - subghz_protocol_decoder_marantec_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_marantec_get_string void void*, FuriString*
Function - subghz_protocol_decoder_marantec_reset void void*
Function - subghz_protocol_decoder_marantec_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_megacode_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_megacode_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_megacode_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_megacode_free void void*
Function - subghz_protocol_decoder_megacode_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_megacode_get_string void void*, FuriString*
Function - subghz_protocol_decoder_megacode_reset void void*
Function - subghz_protocol_decoder_megacode_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_nero_radio_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_nero_radio_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_nero_radio_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_nero_radio_free void void*
Function - subghz_protocol_decoder_nero_radio_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_nero_radio_get_string void void*, FuriString*
Function - subghz_protocol_decoder_nero_radio_reset void void*
Function - subghz_protocol_decoder_nero_radio_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_nero_sketch_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_nero_sketch_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_nero_sketch_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_nero_sketch_free void void*
Function - subghz_protocol_decoder_nero_sketch_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_nero_sketch_get_string void void*, FuriString*
Function - subghz_protocol_decoder_nero_sketch_reset void void*
Function - subghz_protocol_decoder_nero_sketch_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_nice_flo_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_nice_flo_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_nice_flo_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_nice_flo_free void void*
Function - subghz_protocol_decoder_nice_flo_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_nice_flo_get_string void void*, FuriString*
Function - subghz_protocol_decoder_nice_flo_reset void void*
Function - subghz_protocol_decoder_nice_flo_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_nice_flor_s_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_nice_flor_s_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_nice_flor_s_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_nice_flor_s_free void void*
Function - subghz_protocol_decoder_nice_flor_s_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_nice_flor_s_get_string void void*, FuriString*
Function - subghz_protocol_decoder_nice_flor_s_reset void void*
Function - subghz_protocol_decoder_nice_flor_s_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_phoenix_v2_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_phoenix_v2_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_phoenix_v2_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_phoenix_v2_free void void*
Function - subghz_protocol_decoder_phoenix_v2_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_phoenix_v2_get_string void void*, FuriString*
Function - subghz_protocol_decoder_phoenix_v2_reset void void*
Function - subghz_protocol_decoder_phoenix_v2_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_power_smart_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_power_smart_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_power_smart_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_power_smart_free void void*
Function - subghz_protocol_decoder_power_smart_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_power_smart_get_string void void*, FuriString*
Function - subghz_protocol_decoder_power_smart_reset void void*
Function - subghz_protocol_decoder_power_smart_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_princeton_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_princeton_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_princeton_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_princeton_free void void*
Function - subghz_protocol_decoder_princeton_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_princeton_get_string void void*, FuriString*
Function - subghz_protocol_decoder_princeton_reset void void*
Function - subghz_protocol_decoder_princeton_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
2330 Function - subghz_protocol_decoder_raw_alloc void* SubGhzEnvironment*
2331 Function - subghz_protocol_decoder_raw_deserialize _Bool void*, FlipperFormat*
2332 Function - subghz_protocol_decoder_raw_feed void void*, _Bool, uint32_t
2338 Function - subghz_protocol_decoder_raw_set_auto_mode void void*, _Bool
2339 Function - subghz_protocol_decoder_raw_set_rssi_threshold void void*, int
2340 Function - subghz_protocol_decoder_raw_write_data _Bool void*, _Bool, uint32_t
Function - subghz_protocol_decoder_scher_khan_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_scher_khan_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_scher_khan_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_scher_khan_free void void*
Function - subghz_protocol_decoder_scher_khan_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_scher_khan_get_string void void*, FuriString*
Function - subghz_protocol_decoder_scher_khan_reset void void*
Function - subghz_protocol_decoder_scher_khan_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_secplus_v1_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_secplus_v1_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_secplus_v1_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_secplus_v1_free void void*
Function - subghz_protocol_decoder_secplus_v1_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_secplus_v1_get_string void void*, FuriString*
Function - subghz_protocol_decoder_secplus_v1_reset void void*
Function - subghz_protocol_decoder_secplus_v1_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_secplus_v2_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_secplus_v2_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_secplus_v2_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_secplus_v2_free void void*
Function - subghz_protocol_decoder_secplus_v2_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_secplus_v2_get_string void void*, FuriString*
Function - subghz_protocol_decoder_secplus_v2_reset void void*
Function - subghz_protocol_decoder_secplus_v2_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_somfy_keytis_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_somfy_keytis_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_somfy_keytis_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_somfy_keytis_free void void*
Function - subghz_protocol_decoder_somfy_keytis_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_somfy_keytis_get_string void void*, FuriString*
Function - subghz_protocol_decoder_somfy_keytis_reset void void*
Function - subghz_protocol_decoder_somfy_keytis_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_somfy_telis_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_somfy_telis_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_somfy_telis_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_somfy_telis_free void void*
Function - subghz_protocol_decoder_somfy_telis_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_somfy_telis_get_string void void*, FuriString*
Function - subghz_protocol_decoder_somfy_telis_reset void void*
Function - subghz_protocol_decoder_somfy_telis_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_decoder_star_line_alloc void* SubGhzEnvironment*
Function - subghz_protocol_decoder_star_line_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_decoder_star_line_feed void void*, _Bool, uint32_t
Function - subghz_protocol_decoder_star_line_free void void*
Function - subghz_protocol_decoder_star_line_get_hash_data uint8_t void*
Function - subghz_protocol_decoder_star_line_get_string void void*, FuriString*
Function - subghz_protocol_decoder_star_line_reset void void*
Function - subghz_protocol_decoder_star_line_serialize _Bool void*, FlipperFormat*, SubGhzPresetDefinition*
Function - subghz_protocol_encoder_bett_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_bett_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_bett_free void void*
Function - subghz_protocol_encoder_bett_stop void void*
Function - subghz_protocol_encoder_bett_yield LevelDuration void*
Function - subghz_protocol_encoder_came_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_came_atomo_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_came_atomo_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_came_atomo_free void void*
Function - subghz_protocol_encoder_came_atomo_stop void void*
Function - subghz_protocol_encoder_came_atomo_yield LevelDuration void*
Function - subghz_protocol_encoder_came_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_came_free void void*
Function - subghz_protocol_encoder_came_stop void void*
Function - subghz_protocol_encoder_came_twee_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_came_twee_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_came_twee_free void void*
Function - subghz_protocol_encoder_came_twee_stop void void*
Function - subghz_protocol_encoder_came_twee_yield LevelDuration void*
Function - subghz_protocol_encoder_came_yield LevelDuration void*
Function - subghz_protocol_encoder_chamb_code_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_chamb_code_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_chamb_code_free void void*
Function - subghz_protocol_encoder_chamb_code_stop void void*
Function - subghz_protocol_encoder_chamb_code_yield LevelDuration void*
Function - subghz_protocol_encoder_clemsa_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_clemsa_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_clemsa_free void void*
Function - subghz_protocol_encoder_clemsa_stop void void*
Function - subghz_protocol_encoder_clemsa_yield LevelDuration void*
Function - subghz_protocol_encoder_doitrand_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_doitrand_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_doitrand_free void void*
Function - subghz_protocol_encoder_doitrand_stop void void*
Function - subghz_protocol_encoder_doitrand_yield LevelDuration void*
Function - subghz_protocol_encoder_faac_slh_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_faac_slh_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_faac_slh_free void void*
Function - subghz_protocol_encoder_faac_slh_stop void void*
Function - subghz_protocol_encoder_faac_slh_yield LevelDuration void*
Function - subghz_protocol_encoder_gate_tx_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_gate_tx_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_gate_tx_free void void*
Function - subghz_protocol_encoder_gate_tx_stop void void*
Function - subghz_protocol_encoder_gate_tx_yield LevelDuration void*
2341 Function - subghz_protocol_encoder_get_rssi_threshold int void*
Function - subghz_protocol_encoder_holtek_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_holtek_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_holtek_free void void*
Function - subghz_protocol_encoder_holtek_stop void void*
Function - subghz_protocol_encoder_holtek_yield LevelDuration void*
Function - subghz_protocol_encoder_honeywell_wdb_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_honeywell_wdb_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_honeywell_wdb_free void void*
Function - subghz_protocol_encoder_honeywell_wdb_stop void void*
Function - subghz_protocol_encoder_honeywell_wdb_yield LevelDuration void*
Function - subghz_protocol_encoder_hormann_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_hormann_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_hormann_free void void*
Function - subghz_protocol_encoder_hormann_stop void void*
Function - subghz_protocol_encoder_hormann_yield LevelDuration void*
Function - subghz_protocol_encoder_intertechno_v3_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_intertechno_v3_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_intertechno_v3_free void void*
Function - subghz_protocol_encoder_intertechno_v3_stop void void*
Function - subghz_protocol_encoder_intertechno_v3_yield LevelDuration void*
Function - subghz_protocol_encoder_keeloq_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_keeloq_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_keeloq_free void void*
Function - subghz_protocol_encoder_keeloq_stop void void*
Function - subghz_protocol_encoder_keeloq_yield LevelDuration void*
Function - subghz_protocol_encoder_linear_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_linear_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_linear_free void void*
Function - subghz_protocol_encoder_linear_stop void void*
Function - subghz_protocol_encoder_linear_yield LevelDuration void*
Function - subghz_protocol_encoder_magellen_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_magellen_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_magellen_free void void*
Function - subghz_protocol_encoder_magellen_stop void void*
Function - subghz_protocol_encoder_magellen_yield LevelDuration void*
Function - subghz_protocol_encoder_marantec_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_marantec_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_marantec_free void void*
Function - subghz_protocol_encoder_marantec_stop void void*
Function - subghz_protocol_encoder_marantec_yield LevelDuration void*
Function - subghz_protocol_encoder_megacode_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_megacode_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_megacode_free void void*
Function - subghz_protocol_encoder_megacode_stop void void*
Function - subghz_protocol_encoder_megacode_yield LevelDuration void*
Function - subghz_protocol_encoder_nero_radio_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_nero_radio_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_nero_radio_free void void*
Function - subghz_protocol_encoder_nero_radio_stop void void*
Function - subghz_protocol_encoder_nero_radio_yield LevelDuration void*
Function - subghz_protocol_encoder_nero_sketch_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_nero_sketch_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_nero_sketch_free void void*
Function - subghz_protocol_encoder_nero_sketch_stop void void*
Function - subghz_protocol_encoder_nero_sketch_yield LevelDuration void*
Function - subghz_protocol_encoder_nice_flo_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_nice_flo_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_nice_flo_free void void*
Function - subghz_protocol_encoder_nice_flo_stop void void*
Function - subghz_protocol_encoder_nice_flo_yield LevelDuration void*
Function - subghz_protocol_encoder_nice_flor_s_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_nice_flor_s_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_nice_flor_s_free void void*
Function - subghz_protocol_encoder_nice_flor_s_stop void void*
Function - subghz_protocol_encoder_nice_flor_s_yield LevelDuration void*
Function - subghz_protocol_encoder_phoenix_v2_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_phoenix_v2_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_phoenix_v2_free void void*
Function - subghz_protocol_encoder_phoenix_v2_stop void void*
Function - subghz_protocol_encoder_phoenix_v2_yield LevelDuration void*
Function - subghz_protocol_encoder_power_smart_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_power_smart_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_power_smart_free void void*
Function - subghz_protocol_encoder_power_smart_stop void void*
Function - subghz_protocol_encoder_power_smart_yield LevelDuration void*
Function - subghz_protocol_encoder_princeton_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_princeton_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_princeton_free void void*
Function - subghz_protocol_encoder_princeton_stop void void*
Function - subghz_protocol_encoder_princeton_yield LevelDuration void*
2342 Function - subghz_protocol_encoder_raw_alloc void* SubGhzEnvironment*
2343 Function - subghz_protocol_encoder_raw_deserialize _Bool void*, FlipperFormat*
2344 Function - subghz_protocol_encoder_raw_free void void*
2345 Function - subghz_protocol_encoder_raw_stop void void*
2346 Function - subghz_protocol_encoder_raw_yield LevelDuration void*
Function - subghz_protocol_encoder_secplus_v1_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_secplus_v1_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_secplus_v1_free void void*
Function - subghz_protocol_encoder_secplus_v1_stop void void*
Function - subghz_protocol_encoder_secplus_v1_yield LevelDuration void*
Function - subghz_protocol_encoder_secplus_v2_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_secplus_v2_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_secplus_v2_free void void*
Function - subghz_protocol_encoder_secplus_v2_stop void void*
Function - subghz_protocol_encoder_secplus_v2_yield LevelDuration void*
Function - subghz_protocol_encoder_star_line_alloc void* SubGhzEnvironment*
Function - subghz_protocol_encoder_star_line_deserialize _Bool void*, FlipperFormat*
Function - subghz_protocol_encoder_star_line_free void void*
Function - subghz_protocol_encoder_star_line_stop void void*
Function - subghz_protocol_encoder_star_line_yield LevelDuration void*
Function - subghz_protocol_faac_slh_create_data _Bool void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, uint32_t, const char*, SubGhzPresetDefinition*
Function - subghz_protocol_keeloq_bft_create_data _Bool void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, uint32_t, const char*, SubGhzPresetDefinition*
Function - subghz_protocol_keeloq_create_data _Bool void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzPresetDefinition*
Function - subghz_protocol_nice_flor_s_encrypt uint64_t uint64_t, const char*
2347 Function - subghz_protocol_raw_file_encoder_worker_set_callback_end void SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*
2348 Function + subghz_protocol_raw_gen_fff_data void FlipperFormat*, const char*
2349 Function - subghz_protocol_raw_get_sample_write size_t SubGhzProtocolDecoderRAW*
2350 Function - subghz_protocol_raw_save_to_file_init _Bool SubGhzProtocolDecoderRAW*, const char*, SubGhzPresetDefinition*
2351 Function - subghz_protocol_raw_save_to_file_stop void SubGhzProtocolDecoderRAW*
2352 Function - + subghz_protocol_registry_count size_t const SubGhzProtocolRegistry*
2353 Function - + subghz_protocol_registry_get_by_index const SubGhzProtocol* size_t const SubGhzProtocolRegistry*, size_t
2354 Function + subghz_protocol_registry_get_by_name const SubGhzProtocol* const char* const SubGhzProtocolRegistry*, const char*
Function - subghz_protocol_secplus_v1_check_fixed _Bool uint32_t
Function - subghz_protocol_secplus_v2_create_data _Bool void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzPresetDefinition*
Function - subghz_protocol_star_line_create_data _Bool void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzPresetDefinition*
2355 Function + subghz_receiver_alloc_init SubGhzReceiver* SubGhzEnvironment*
2356 Function + subghz_receiver_decode void SubGhzReceiver*, _Bool, uint32_t
2357 Function + subghz_receiver_free void SubGhzReceiver*
2360 Function + subghz_receiver_search_decoder_base_by_name SubGhzProtocolDecoderBase* SubGhzReceiver*, const char*
2361 Function + subghz_receiver_set_filter void SubGhzReceiver*, SubGhzProtocolFlag
2362 Function + subghz_receiver_set_rx_callback void SubGhzReceiver*, SubGhzReceiverCallback, void*
2363 Function + subghz_setting_alloc SubGhzSetting*
2364 Function + subghz_setting_delete_custom_preset _Bool SubGhzSetting*, const char*
2365 Function + subghz_setting_free void SubGhzSetting*
2366 Function + subghz_setting_get_default_frequency uint32_t SubGhzSetting*
2367 Function + subghz_setting_get_frequency uint32_t SubGhzSetting*, size_t
2368 Function + subghz_setting_get_frequency_count size_t SubGhzSetting*
2369 Function + subghz_setting_get_frequency_default_index uint32_t SubGhzSetting*
2370 Function + subghz_setting_get_hopper_frequency uint32_t SubGhzSetting*, size_t
2371 Function + subghz_setting_get_hopper_frequency_count size_t SubGhzSetting*
2372 Function + subghz_setting_get_inx_preset_by_name int SubGhzSetting*, const char*
2373 Function + subghz_setting_get_preset_count size_t SubGhzSetting*
2374 Function + subghz_setting_get_preset_data uint8_t* SubGhzSetting*, size_t
2375 Function + subghz_setting_get_preset_data_by_name uint8_t* SubGhzSetting*, const char*
2376 Function + subghz_setting_get_preset_data_size size_t SubGhzSetting*, size_t
2377 Function + subghz_setting_get_preset_name const char* SubGhzSetting*, size_t
2378 Function + subghz_setting_load void SubGhzSetting*, const char*, _Bool
2379 Function + subghz_setting_load_custom_preset _Bool SubGhzSetting*, const char*, FlipperFormat*
2380 Function + subghz_setting_set_default_frequency void SubGhzSetting*, uint32_t
2381 Function + subghz_transmitter_alloc_init SubGhzTransmitter* SubGhzEnvironment*, const char*
2382 Function + subghz_transmitter_deserialize _Bool SubGhzTransmitter*, FlipperFormat*
2383 Function + subghz_transmitter_free void SubGhzTransmitter*
4227 Variable + sequence_single_vibro const NotificationSequence
4228 Variable + sequence_solid_yellow const NotificationSequence
4229 Variable + sequence_success const NotificationSequence
Variable - subghz_protocol_bett const SubGhzProtocol
Variable - subghz_protocol_bett_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_bett_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_came const SubGhzProtocol
Variable - subghz_protocol_came_atomo const SubGhzProtocol
Variable - subghz_protocol_came_atomo_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_came_atomo_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_came_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_came_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_came_twee const SubGhzProtocol
Variable - subghz_protocol_came_twee_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_came_twee_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_chamb_code const SubGhzProtocol
Variable - subghz_protocol_chamb_code_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_chamb_code_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_clemsa const SubGhzProtocol
Variable - subghz_protocol_clemsa_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_clemsa_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_doitrand const SubGhzProtocol
Variable - subghz_protocol_doitrand_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_doitrand_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_faac_slh const SubGhzProtocol
Variable - subghz_protocol_faac_slh_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_faac_slh_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_gate_tx const SubGhzProtocol
Variable - subghz_protocol_gate_tx_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_gate_tx_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_holtek const SubGhzProtocol
Variable - subghz_protocol_holtek_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_holtek_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_honeywell_wdb const SubGhzProtocol
Variable - subghz_protocol_honeywell_wdb_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_honeywell_wdb_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_hormann const SubGhzProtocol
Variable - subghz_protocol_hormann_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_hormann_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_ido const SubGhzProtocol
Variable - subghz_protocol_ido_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_ido_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_intertechno_v3 const SubGhzProtocol
Variable - subghz_protocol_intertechno_v3_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_intertechno_v3_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_keeloq const SubGhzProtocol
Variable - subghz_protocol_keeloq_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_keeloq_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_kia const SubGhzProtocol
Variable - subghz_protocol_kia_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_kia_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_linear const SubGhzProtocol
Variable - subghz_protocol_linear_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_linear_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_magellen const SubGhzProtocol
Variable - subghz_protocol_magellen_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_magellen_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_marantec const SubGhzProtocol
Variable - subghz_protocol_marantec_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_marantec_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_megacode const SubGhzProtocol
Variable - subghz_protocol_megacode_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_megacode_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_nero_radio const SubGhzProtocol
Variable - subghz_protocol_nero_radio_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_nero_radio_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_nero_sketch const SubGhzProtocol
Variable - subghz_protocol_nero_sketch_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_nero_sketch_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_nice_flo const SubGhzProtocol
Variable - subghz_protocol_nice_flo_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_nice_flo_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_nice_flor_s const SubGhzProtocol
Variable - subghz_protocol_nice_flor_s_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_nice_flor_s_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_oregon2 const SubGhzProtocol
Variable - subghz_protocol_phoenix_v2 const SubGhzProtocol
Variable - subghz_protocol_phoenix_v2_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_phoenix_v2_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_power_smart const SubGhzProtocol
Variable - subghz_protocol_power_smart_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_power_smart_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_princeton const SubGhzProtocol
Variable - subghz_protocol_princeton_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_princeton_encoder const SubGhzProtocolEncoder
4230 Variable - subghz_protocol_raw const SubGhzProtocol
4231 Variable - subghz_protocol_raw_decoder const SubGhzProtocolDecoder
4232 Variable - subghz_protocol_raw_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_scher_khan const SubGhzProtocol
Variable - subghz_protocol_scher_khan_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_scher_khan_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_secplus_v1 const SubGhzProtocol
Variable - subghz_protocol_secplus_v1_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_secplus_v1_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_secplus_v2 const SubGhzProtocol
Variable - subghz_protocol_secplus_v2_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_secplus_v2_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_somfy_keytis const SubGhzProtocol
Variable - subghz_protocol_somfy_keytis_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_somfy_keytis_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_somfy_telis const SubGhzProtocol
Variable - subghz_protocol_somfy_telis_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_somfy_telis_encoder const SubGhzProtocolEncoder
Variable - subghz_protocol_star_line const SubGhzProtocol
Variable - subghz_protocol_star_line_decoder const SubGhzProtocolDecoder
Variable - subghz_protocol_star_line_encoder const SubGhzProtocolEncoder
4233 Variable - suboptarg char*
4234 Variable - u8g2_cb_mirror const u8g2_cb_t
4235 Variable - u8g2_cb_r0 const u8g2_cb_t

View file

@ -10,8 +10,14 @@ env.Append(
File("#/lib/subghz/subghz_worker.h"), File("#/lib/subghz/subghz_worker.h"),
File("#/lib/subghz/subghz_tx_rx_worker.h"), File("#/lib/subghz/subghz_tx_rx_worker.h"),
File("#/lib/subghz/transmitter.h"), File("#/lib/subghz/transmitter.h"),
File("#/lib/subghz/protocols/registry.h"), File("#/lib/subghz/registry.h"),
File("#/lib/subghz/protocols/raw.h"), File("#/lib/subghz/protocols/raw.h"),
File("#/lib/subghz/blocks/const.h"),
File("#/lib/subghz/blocks/decoder.h"),
File("#/lib/subghz/blocks/encoder.h"),
File("#/lib/subghz/blocks/generic.h"),
File("#/lib/subghz/blocks/math.h"),
File("#/lib/subghz/subghz_setting.h"),
], ],
) )

View file

@ -4,9 +4,17 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { typedef struct {
const uint16_t te_long; const uint16_t te_long;
const uint16_t te_short; const uint16_t te_short;
const uint16_t te_delta; const uint16_t te_delta;
const uint8_t min_count_bit_for_found; const uint8_t min_count_bit_for_found;
} SubGhzBlockConst; } SubGhzBlockConst;
#ifdef __cplusplus
}
#endif

View file

@ -4,6 +4,10 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct SubGhzBlockDecoder SubGhzBlockDecoder; typedef struct SubGhzBlockDecoder SubGhzBlockDecoder;
struct SubGhzBlockDecoder { struct SubGhzBlockDecoder {
@ -26,3 +30,7 @@ void subghz_protocol_blocks_add_bit(SubGhzBlockDecoder* decoder, uint8_t bit);
* @return hash Hash sum * @return hash Hash sum
*/ */
uint8_t subghz_protocol_blocks_get_hash_data(SubGhzBlockDecoder* decoder, size_t len); uint8_t subghz_protocol_blocks_get_hash_data(SubGhzBlockDecoder* decoder, size_t len);
#ifdef __cplusplus
}
#endif

View file

@ -6,6 +6,10 @@
#include <lib/toolbox/level_duration.h> #include <lib/toolbox/level_duration.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { typedef struct {
bool is_running; bool is_running;
size_t repeat; size_t repeat;
@ -50,3 +54,7 @@ size_t subghz_protocol_blocks_get_upload(
LevelDuration* upload, LevelDuration* upload,
size_t max_size_upload, size_t max_size_upload,
uint32_t duration_bit); uint32_t duration_bit);
#ifdef __cplusplus
}
#endif

View file

@ -9,6 +9,10 @@
#include "furi_hal.h" #include "furi_hal.h"
#include "../types.h" #include "../types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct SubGhzBlockGeneric SubGhzBlockGeneric; typedef struct SubGhzBlockGeneric SubGhzBlockGeneric;
struct SubGhzBlockGeneric { struct SubGhzBlockGeneric {
@ -49,3 +53,7 @@ bool subghz_block_generic_serialize(
* @return true On success * @return true On success
*/ */
bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format); bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format);
#ifdef __cplusplus
}
#endif

View file

@ -14,4 +14,69 @@ uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit) {
parity += bit_read(key, i); parity += bit_read(key, i);
} }
return parity & 0x01; return parity & 0x01;
}
uint8_t subghz_protocol_blocks_crc4(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init) {
unsigned remainder = init << 4; // LSBs are unused
unsigned poly = polynomial << 4;
unsigned bit;
while(nBytes--) {
remainder ^= *message++;
for(bit = 0; bit < 8; bit++) {
if(remainder & 0x80) {
remainder = (remainder << 1) ^ poly;
} else {
remainder = (remainder << 1);
}
}
}
return remainder >> 4 & 0x0f; // discard the LSBs
}
uint8_t subghz_protocol_blocks_crc7(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init) {
unsigned remainder = init << 1; // LSB is unused
unsigned poly = polynomial << 1;
unsigned byte, bit;
for(byte = 0; byte < nBytes; ++byte) {
remainder ^= message[byte];
for(bit = 0; bit < 8; ++bit) {
if(remainder & 0x80) {
remainder = (remainder << 1) ^ poly;
} else {
remainder = (remainder << 1);
}
}
}
return remainder >> 1 & 0x7f; // discard the LSB
}
uint8_t subghz_protocol_blocks_crc8(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init) {
uint8_t remainder = init;
unsigned byte, bit;
for(byte = 0; byte < nBytes; ++byte) {
remainder ^= message[byte];
for(bit = 0; bit < 8; ++bit) {
if(remainder & 0x80) {
remainder = (remainder << 1) ^ polynomial;
} else {
remainder = (remainder << 1);
}
}
}
return remainder;
} }

View file

@ -9,7 +9,11 @@
#define bit_clear(value, bit) ((value) &= ~(1UL << (bit))) #define bit_clear(value, bit) ((value) &= ~(1UL << (bit)))
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit)) #define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y)) #define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
#define abs(x) ((x) > 0 ? (x) : -(x))
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* Flip the data bitwise. * Flip the data bitwise.
* @param key In data * @param key In data
@ -25,3 +29,51 @@ uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit);
* @return parity * @return parity
*/ */
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit); uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit);
/**
* CRC-4.
* @param message array of bytes to check
* @param nBytes number of bytes in message
* @param polynomial CRC polynomial
* @param init starting crc value
* @return CRC value
*/
uint8_t subghz_protocol_blocks_crc4(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init);
/**
* CRC-7.
* @param message array of bytes to check
* @param nBytes number of bytes in message
* @param polynomial CRC polynomial
* @param init starting crc value
* @return CRC value
*/
uint8_t subghz_protocol_blocks_crc7(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init);
/**
* Generic Cyclic Redundancy Check CRC-8.
* Example polynomial: 0x31 = x8 + x5 + x4 + 1 (x8 is implicit)
* Example polynomial: 0x80 = x8 + x7 (a normal bit-by-bit parity XOR)
* @param message array of bytes to check
* @param nBytes number of bytes in message
* @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
* @param init starting crc value
* @return CRC value
*/
uint8_t subghz_protocol_blocks_crc8(
uint8_t const message[],
unsigned nBytes,
uint8_t polynomial,
uint8_t init);
#ifdef __cplusplus
}
#endif

View file

@ -1,7 +1,9 @@
#include "environment.h" #include "environment.h"
#include "registry.h"
struct SubGhzEnvironment { struct SubGhzEnvironment {
SubGhzKeystore* keystore; SubGhzKeystore* keystore;
const SubGhzProtocolRegistry* protocol_registry;
const char* came_atomo_rainbow_table_file_name; const char* came_atomo_rainbow_table_file_name;
const char* nice_flor_s_rainbow_table_file_name; const char* nice_flor_s_rainbow_table_file_name;
}; };
@ -10,6 +12,7 @@ SubGhzEnvironment* subghz_environment_alloc() {
SubGhzEnvironment* instance = malloc(sizeof(SubGhzEnvironment)); SubGhzEnvironment* instance = malloc(sizeof(SubGhzEnvironment));
instance->keystore = subghz_keystore_alloc(); instance->keystore = subghz_keystore_alloc();
instance->protocol_registry = NULL;
instance->came_atomo_rainbow_table_file_name = NULL; instance->came_atomo_rainbow_table_file_name = NULL;
instance->nice_flor_s_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL;
@ -19,6 +22,7 @@ SubGhzEnvironment* subghz_environment_alloc() {
void subghz_environment_free(SubGhzEnvironment* instance) { void subghz_environment_free(SubGhzEnvironment* instance) {
furi_assert(instance); furi_assert(instance);
instance->protocol_registry = NULL;
instance->came_atomo_rainbow_table_file_name = NULL; instance->came_atomo_rainbow_table_file_name = NULL;
instance->nice_flor_s_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL;
subghz_keystore_free(instance->keystore); subghz_keystore_free(instance->keystore);
@ -67,3 +71,28 @@ const char*
return instance->nice_flor_s_rainbow_table_file_name; return instance->nice_flor_s_rainbow_table_file_name;
} }
void subghz_environment_set_protocol_registry(
SubGhzEnvironment* instance,
void* protocol_registry_items) {
furi_assert(instance);
const SubGhzProtocolRegistry* protocol_registry = protocol_registry_items;
instance->protocol_registry = protocol_registry;
}
void* subghz_environment_get_protocol_registry(SubGhzEnvironment* instance) {
furi_assert(instance);
furi_assert(instance->protocol_registry);
return (void*)instance->protocol_registry;
}
const char*
subghz_environment_get_protocol_name_registry(SubGhzEnvironment* instance, size_t idx) {
const SubGhzProtocol* protocol =
subghz_protocol_registry_get_by_index(instance->protocol_registry, idx);
if(protocol != NULL) {
return protocol->name;
} else {
return NULL;
}
}

View file

@ -69,6 +69,30 @@ void subghz_environment_set_nice_flor_s_rainbow_table_file_name(
const char* const char*
subghz_environment_get_nice_flor_s_rainbow_table_file_name(SubGhzEnvironment* instance); subghz_environment_get_nice_flor_s_rainbow_table_file_name(SubGhzEnvironment* instance);
/**
* Set list of protocols to work.
* @param instance Pointer to a SubGhzEnvironment instance
* @param protocol_registry_items Pointer to a SubGhzProtocolRegistry
*/
void subghz_environment_set_protocol_registry(
SubGhzEnvironment* instance,
void* protocol_registry_items);
/**
* Get list of protocols to work.
* @param instance Pointer to a SubGhzEnvironment instance
* @return Pointer to a SubGhzProtocolRegistry
*/
void* subghz_environment_get_protocol_registry(SubGhzEnvironment* instance);
/**
* Get list of protocols names.
* @param instance Pointer to a SubGhzEnvironment instance
* @param idx index protocols
* @return Pointer to a SubGhzProtocolRegistry
*/
const char* subghz_environment_get_protocol_name_registry(SubGhzEnvironment* instance, size_t idx);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -1,4 +1,4 @@
#include "magellen.h" #include "magellan.h"
#include "../blocks/const.h" #include "../blocks/const.h"
#include "../blocks/decoder.h" #include "../blocks/decoder.h"
@ -6,16 +6,16 @@
#include "../blocks/generic.h" #include "../blocks/generic.h"
#include "../blocks/math.h" #include "../blocks/math.h"
#define TAG "SubGhzProtocolMagellen" #define TAG "SubGhzProtocolMagellan"
static const SubGhzBlockConst subghz_protocol_magellen_const = { static const SubGhzBlockConst subghz_protocol_magellan_const = {
.te_short = 200, .te_short = 200,
.te_long = 400, .te_long = 400,
.te_delta = 100, .te_delta = 100,
.min_count_bit_for_found = 32, .min_count_bit_for_found = 32,
}; };
struct SubGhzProtocolDecoderMagellen { struct SubGhzProtocolDecoderMagellan {
SubGhzProtocolDecoderBase base; SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder; SubGhzBlockDecoder decoder;
@ -23,7 +23,7 @@ struct SubGhzProtocolDecoderMagellen {
uint16_t header_count; uint16_t header_count;
}; };
struct SubGhzProtocolEncoderMagellen { struct SubGhzProtocolEncoderMagellan {
SubGhzProtocolEncoderBase base; SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder; SubGhzProtocolBlockEncoder encoder;
@ -31,50 +31,50 @@ struct SubGhzProtocolEncoderMagellen {
}; };
typedef enum { typedef enum {
MagellenDecoderStepReset = 0, MagellanDecoderStepReset = 0,
MagellenDecoderStepCheckPreambula, MagellanDecoderStepCheckPreambula,
MagellenDecoderStepFoundPreambula, MagellanDecoderStepFoundPreambula,
MagellenDecoderStepSaveDuration, MagellanDecoderStepSaveDuration,
MagellenDecoderStepCheckDuration, MagellanDecoderStepCheckDuration,
} MagellenDecoderStep; } MagellanDecoderStep;
const SubGhzProtocolDecoder subghz_protocol_magellen_decoder = { const SubGhzProtocolDecoder subghz_protocol_magellan_decoder = {
.alloc = subghz_protocol_decoder_magellen_alloc, .alloc = subghz_protocol_decoder_magellan_alloc,
.free = subghz_protocol_decoder_magellen_free, .free = subghz_protocol_decoder_magellan_free,
.feed = subghz_protocol_decoder_magellen_feed, .feed = subghz_protocol_decoder_magellan_feed,
.reset = subghz_protocol_decoder_magellen_reset, .reset = subghz_protocol_decoder_magellan_reset,
.get_hash_data = subghz_protocol_decoder_magellen_get_hash_data, .get_hash_data = subghz_protocol_decoder_magellan_get_hash_data,
.serialize = subghz_protocol_decoder_magellen_serialize, .serialize = subghz_protocol_decoder_magellan_serialize,
.deserialize = subghz_protocol_decoder_magellen_deserialize, .deserialize = subghz_protocol_decoder_magellan_deserialize,
.get_string = subghz_protocol_decoder_magellen_get_string, .get_string = subghz_protocol_decoder_magellan_get_string,
}; };
const SubGhzProtocolEncoder subghz_protocol_magellen_encoder = { const SubGhzProtocolEncoder subghz_protocol_magellan_encoder = {
.alloc = subghz_protocol_encoder_magellen_alloc, .alloc = subghz_protocol_encoder_magellan_alloc,
.free = subghz_protocol_encoder_magellen_free, .free = subghz_protocol_encoder_magellan_free,
.deserialize = subghz_protocol_encoder_magellen_deserialize, .deserialize = subghz_protocol_encoder_magellan_deserialize,
.stop = subghz_protocol_encoder_magellen_stop, .stop = subghz_protocol_encoder_magellan_stop,
.yield = subghz_protocol_encoder_magellen_yield, .yield = subghz_protocol_encoder_magellan_yield,
}; };
const SubGhzProtocol subghz_protocol_magellen = { const SubGhzProtocol subghz_protocol_magellan = {
.name = SUBGHZ_PROTOCOL_MAGELLEN_NAME, .name = SUBGHZ_PROTOCOL_MAGELLAN_NAME,
.type = SubGhzProtocolTypeStatic, .type = SubGhzProtocolTypeStatic,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
.decoder = &subghz_protocol_magellen_decoder, .decoder = &subghz_protocol_magellan_decoder,
.encoder = &subghz_protocol_magellen_encoder, .encoder = &subghz_protocol_magellan_encoder,
}; };
void* subghz_protocol_encoder_magellen_alloc(SubGhzEnvironment* environment) { void* subghz_protocol_encoder_magellan_alloc(SubGhzEnvironment* environment) {
UNUSED(environment); UNUSED(environment);
SubGhzProtocolEncoderMagellen* instance = malloc(sizeof(SubGhzProtocolEncoderMagellen)); SubGhzProtocolEncoderMagellan* instance = malloc(sizeof(SubGhzProtocolEncoderMagellan));
instance->base.protocol = &subghz_protocol_magellen; instance->base.protocol = &subghz_protocol_magellan;
instance->generic.protocol_name = instance->base.protocol->name; instance->generic.protocol_name = instance->base.protocol->name;
instance->encoder.repeat = 10; instance->encoder.repeat = 10;
@ -84,75 +84,75 @@ void* subghz_protocol_encoder_magellen_alloc(SubGhzEnvironment* environment) {
return instance; return instance;
} }
void subghz_protocol_encoder_magellen_free(void* context) { void subghz_protocol_encoder_magellan_free(void* context) {
furi_assert(context); furi_assert(context);
SubGhzProtocolEncoderMagellen* instance = context; SubGhzProtocolEncoderMagellan* instance = context;
free(instance->encoder.upload); free(instance->encoder.upload);
free(instance); free(instance);
} }
/** /**
* Generating an upload from data. * Generating an upload from data.
* @param instance Pointer to a SubGhzProtocolEncoderMagellen instance * @param instance Pointer to a SubGhzProtocolEncoderMagellan instance
* @return true On success * @return true On success
*/ */
static bool subghz_protocol_encoder_magellen_get_upload(SubGhzProtocolEncoderMagellen* instance) { static bool subghz_protocol_encoder_magellan_get_upload(SubGhzProtocolEncoderMagellan* instance) {
furi_assert(instance); furi_assert(instance);
size_t index = 0; size_t index = 0;
//Send header //Send header
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short * 4); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_short * 4);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_short);
for(uint8_t i = 0; i < 12; i++) { for(uint8_t i = 0; i < 12; i++) {
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_short);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_short);
} }
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_short);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_long);
//Send start bit //Send start bit
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_long * 3); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_long * 3);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_long);
//Send key data //Send key data
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
if(bit_read(instance->generic.data, i - 1)) { if(bit_read(instance->generic.data, i - 1)) {
//send bit 1 //send bit 1
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_short);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_long);
} else { } else {
//send bit 0 //send bit 0
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_long); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_long);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_short);
} }
} }
//Send stop bit //Send stop bit
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short); level_duration_make(true, (uint32_t)subghz_protocol_magellan_const.te_short);
instance->encoder.upload[index++] = instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long * 100); level_duration_make(false, (uint32_t)subghz_protocol_magellan_const.te_long * 100);
instance->encoder.size_upload = index; instance->encoder.size_upload = index;
return true; return true;
} }
bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat* flipper_format) { bool subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context); furi_assert(context);
SubGhzProtocolEncoderMagellen* instance = context; SubGhzProtocolEncoderMagellan* instance = context;
bool res = false; bool res = false;
do { do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
@ -160,7 +160,7 @@ bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat*
break; break;
} }
if(instance->generic.data_count_bit != if(instance->generic.data_count_bit !=
subghz_protocol_magellen_const.min_count_bit_for_found) { subghz_protocol_magellan_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key"); FURI_LOG_E(TAG, "Wrong number of bits in key");
break; break;
} }
@ -168,7 +168,7 @@ bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat*
flipper_format_read_uint32( flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
if(!subghz_protocol_encoder_magellen_get_upload(instance)) break; if(!subghz_protocol_encoder_magellan_get_upload(instance)) break;
instance->encoder.is_running = true; instance->encoder.is_running = true;
res = true; res = true;
@ -177,13 +177,13 @@ bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat*
return res; return res;
} }
void subghz_protocol_encoder_magellen_stop(void* context) { void subghz_protocol_encoder_magellan_stop(void* context) {
SubGhzProtocolEncoderMagellen* instance = context; SubGhzProtocolEncoderMagellan* instance = context;
instance->encoder.is_running = false; instance->encoder.is_running = false;
} }
LevelDuration subghz_protocol_encoder_magellen_yield(void* context) { LevelDuration subghz_protocol_encoder_magellan_yield(void* context) {
SubGhzProtocolEncoderMagellen* instance = context; SubGhzProtocolEncoderMagellan* instance = context;
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
instance->encoder.is_running = false; instance->encoder.is_running = false;
@ -200,27 +200,27 @@ LevelDuration subghz_protocol_encoder_magellen_yield(void* context) {
return ret; return ret;
} }
void* subghz_protocol_decoder_magellen_alloc(SubGhzEnvironment* environment) { void* subghz_protocol_decoder_magellan_alloc(SubGhzEnvironment* environment) {
UNUSED(environment); UNUSED(environment);
SubGhzProtocolDecoderMagellen* instance = malloc(sizeof(SubGhzProtocolDecoderMagellen)); SubGhzProtocolDecoderMagellan* instance = malloc(sizeof(SubGhzProtocolDecoderMagellan));
instance->base.protocol = &subghz_protocol_magellen; instance->base.protocol = &subghz_protocol_magellan;
instance->generic.protocol_name = instance->base.protocol->name; instance->generic.protocol_name = instance->base.protocol->name;
return instance; return instance;
} }
void subghz_protocol_decoder_magellen_free(void* context) { void subghz_protocol_decoder_magellan_free(void* context) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
free(instance); free(instance);
} }
void subghz_protocol_decoder_magellen_reset(void* context) { void subghz_protocol_decoder_magellan_reset(void* context) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
uint8_t subghz_protocol_magellen_crc8(uint8_t* data, size_t len) { uint8_t subghz_protocol_magellan_crc8(uint8_t* data, size_t len) {
uint8_t crc = 0x00; uint8_t crc = 0x00;
size_t i, j; size_t i, j;
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
@ -235,99 +235,99 @@ uint8_t subghz_protocol_magellen_crc8(uint8_t* data, size_t len) {
return crc; return crc;
} }
static bool subghz_protocol_magellen_check_crc(SubGhzProtocolDecoderMagellen* instance) { static bool subghz_protocol_magellan_check_crc(SubGhzProtocolDecoderMagellan* instance) {
uint8_t data[3] = { uint8_t data[3] = {
instance->decoder.decode_data >> 24, instance->decoder.decode_data >> 24,
instance->decoder.decode_data >> 16, instance->decoder.decode_data >> 16,
instance->decoder.decode_data >> 8}; instance->decoder.decode_data >> 8};
return (instance->decoder.decode_data & 0xFF) == return (instance->decoder.decode_data & 0xFF) ==
subghz_protocol_magellen_crc8(data, sizeof(data)); subghz_protocol_magellan_crc8(data, sizeof(data));
} }
void subghz_protocol_decoder_magellen_feed(void* context, bool level, uint32_t duration) { void subghz_protocol_decoder_magellan_feed(void* context, bool level, uint32_t duration) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
switch(instance->decoder.parser_step) { switch(instance->decoder.parser_step) {
case MagellenDecoderStepReset: case MagellanDecoderStepReset:
if((level) && (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) < if((level) && (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta)) { subghz_protocol_magellan_const.te_delta)) {
instance->decoder.parser_step = MagellenDecoderStepCheckPreambula; instance->decoder.parser_step = MagellanDecoderStepCheckPreambula;
instance->decoder.te_last = duration; instance->decoder.te_last = duration;
instance->header_count = 0; instance->header_count = 0;
} }
break; break;
case MagellenDecoderStepCheckPreambula: case MagellanDecoderStepCheckPreambula:
if(level) { if(level) {
instance->decoder.te_last = duration; instance->decoder.te_last = duration;
} else { } else {
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) < if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta) && subghz_protocol_magellan_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) < (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta)) { subghz_protocol_magellan_const.te_delta)) {
// Found header // Found header
instance->header_count++; instance->header_count++;
} else if( } else if(
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) < (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta) && subghz_protocol_magellan_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) < (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_long) <
subghz_protocol_magellen_const.te_delta * 2) && subghz_protocol_magellan_const.te_delta * 2) &&
(instance->header_count > 10)) { (instance->header_count > 10)) {
instance->decoder.parser_step = MagellenDecoderStepFoundPreambula; instance->decoder.parser_step = MagellanDecoderStepFoundPreambula;
} else { } else {
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
} }
break; break;
case MagellenDecoderStepFoundPreambula: case MagellanDecoderStepFoundPreambula:
if(level) { if(level) {
instance->decoder.te_last = duration; instance->decoder.te_last = duration;
} else { } else {
if((DURATION_DIFF( if((DURATION_DIFF(
instance->decoder.te_last, subghz_protocol_magellen_const.te_short * 6) < instance->decoder.te_last, subghz_protocol_magellan_const.te_short * 6) <
subghz_protocol_magellen_const.te_delta * 3) && subghz_protocol_magellan_const.te_delta * 3) &&
(DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) < (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_long) <
subghz_protocol_magellen_const.te_delta * 2)) { subghz_protocol_magellan_const.te_delta * 2)) {
instance->decoder.parser_step = MagellenDecoderStepSaveDuration; instance->decoder.parser_step = MagellanDecoderStepSaveDuration;
instance->decoder.decode_data = 0; instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0; instance->decoder.decode_count_bit = 0;
} else { } else {
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
} }
break; break;
case MagellenDecoderStepSaveDuration: case MagellanDecoderStepSaveDuration:
if(level) { if(level) {
instance->decoder.te_last = duration; instance->decoder.te_last = duration;
instance->decoder.parser_step = MagellenDecoderStepCheckDuration; instance->decoder.parser_step = MagellanDecoderStepCheckDuration;
} else { } else {
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
break; break;
case MagellenDecoderStepCheckDuration: case MagellanDecoderStepCheckDuration:
if(!level) { if(!level) {
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) < if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta) && subghz_protocol_magellan_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) < (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_long) <
subghz_protocol_magellen_const.te_delta)) { subghz_protocol_magellan_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1); subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = MagellenDecoderStepSaveDuration; instance->decoder.parser_step = MagellanDecoderStepSaveDuration;
} else if( } else if(
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_long) < (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellan_const.te_long) <
subghz_protocol_magellen_const.te_delta) && subghz_protocol_magellan_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) < (DURATION_DIFF(duration, subghz_protocol_magellan_const.te_short) <
subghz_protocol_magellen_const.te_delta)) { subghz_protocol_magellan_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0); subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = MagellenDecoderStepSaveDuration; instance->decoder.parser_step = MagellanDecoderStepSaveDuration;
} else if(duration >= (subghz_protocol_magellen_const.te_long * 3)) { } else if(duration >= (subghz_protocol_magellan_const.te_long * 3)) {
//Found stop bit //Found stop bit
if((instance->decoder.decode_count_bit == if((instance->decoder.decode_count_bit ==
subghz_protocol_magellen_const.min_count_bit_for_found) && subghz_protocol_magellan_const.min_count_bit_for_found) &&
subghz_protocol_magellen_check_crc(instance)) { subghz_protocol_magellan_check_crc(instance)) {
instance->generic.data = instance->decoder.decode_data; instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit; instance->generic.data_count_bit = instance->decoder.decode_count_bit;
if(instance->base.callback) if(instance->base.callback)
@ -335,12 +335,12 @@ void subghz_protocol_decoder_magellen_feed(void* context, bool level, uint32_t d
} }
instance->decoder.decode_data = 0; instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0; instance->decoder.decode_count_bit = 0;
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} else { } else {
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
} else { } else {
instance->decoder.parser_step = MagellenDecoderStepReset; instance->decoder.parser_step = MagellanDecoderStepReset;
} }
break; break;
} }
@ -350,7 +350,7 @@ void subghz_protocol_decoder_magellen_feed(void* context, bool level, uint32_t d
* Analysis of received data * Analysis of received data
* @param instance Pointer to a SubGhzBlockGeneric* instance * @param instance Pointer to a SubGhzBlockGeneric* instance
*/ */
static void subghz_protocol_magellen_check_remote_controller(SubGhzBlockGeneric* instance) { static void subghz_protocol_magellan_check_remote_controller(SubGhzBlockGeneric* instance) {
/* /*
* package 32b data 24b CRC8 * package 32b data 24b CRC8
* 0x037AE4828 => 001101111010111001001000 00101000 * 0x037AE4828 => 001101111010111001001000 00101000
@ -375,7 +375,7 @@ static void subghz_protocol_magellen_check_remote_controller(SubGhzBlockGeneric*
instance->btn = (data_rev >> 16) & 0xFF; instance->btn = (data_rev >> 16) & 0xFF;
} }
static void subghz_protocol_magellen_get_event_serialize(uint8_t event, FuriString* output) { static void subghz_protocol_magellan_get_event_serialize(uint8_t event, FuriString* output) {
furi_string_cat_printf( furi_string_cat_printf(
output, output,
"%s%s%s%s%s%s%s%s", "%s%s%s%s%s%s%s%s",
@ -390,32 +390,32 @@ static void subghz_protocol_magellen_get_event_serialize(uint8_t event, FuriStri
((event >> 7) & 0x1 ? ", ?" : "")); ((event >> 7) & 0x1 ? ", ?" : ""));
} }
uint8_t subghz_protocol_decoder_magellen_get_hash_data(void* context) { uint8_t subghz_protocol_decoder_magellan_get_hash_data(void* context) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
return subghz_protocol_blocks_get_hash_data( return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
} }
bool subghz_protocol_decoder_magellen_serialize( bool subghz_protocol_decoder_magellan_serialize(
void* context, void* context,
FlipperFormat* flipper_format, FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset) { SubGhzPresetDefinition* preset) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
} }
bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat* flipper_format) { bool subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
bool ret = false; bool ret = false;
do { do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
break; break;
} }
if(instance->generic.data_count_bit != if(instance->generic.data_count_bit !=
subghz_protocol_magellen_const.min_count_bit_for_found) { subghz_protocol_magellan_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key"); FURI_LOG_E(TAG, "Wrong number of bits in key");
break; break;
} }
@ -424,10 +424,10 @@ bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat*
return ret; return ret;
} }
void subghz_protocol_decoder_magellen_get_string(void* context, FuriString* output) { void subghz_protocol_decoder_magellan_get_string(void* context, FuriString* output) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderMagellen* instance = context; SubGhzProtocolDecoderMagellan* instance = context;
subghz_protocol_magellen_check_remote_controller(&instance->generic); subghz_protocol_magellan_check_remote_controller(&instance->generic);
furi_string_cat_printf( furi_string_cat_printf(
output, output,
"%s %dbit\r\n" "%s %dbit\r\n"
@ -441,5 +441,5 @@ void subghz_protocol_decoder_magellen_get_string(void* context, FuriString* outp
instance->generic.serial & 0xFF, instance->generic.serial & 0xFF,
instance->generic.btn); instance->generic.btn);
subghz_protocol_magellen_get_event_serialize(instance->generic.btn, output); subghz_protocol_magellan_get_event_serialize(instance->generic.btn, output);
} }

View file

@ -0,0 +1,107 @@
#pragma once
#include "base.h"
#define SUBGHZ_PROTOCOL_MAGELLAN_NAME "Magellan"
typedef struct SubGhzProtocolDecoderMagellan SubGhzProtocolDecoderMagellan;
typedef struct SubGhzProtocolEncoderMagellan SubGhzProtocolEncoderMagellan;
extern const SubGhzProtocolDecoder subghz_protocol_magellan_decoder;
extern const SubGhzProtocolEncoder subghz_protocol_magellan_encoder;
extern const SubGhzProtocol subghz_protocol_magellan;
/**
* Allocate SubGhzProtocolEncoderMagellan.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolEncoderMagellan* pointer to a SubGhzProtocolEncoderMagellan instance
*/
void* subghz_protocol_encoder_magellan_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolEncoderMagellan.
* @param context Pointer to a SubGhzProtocolEncoderMagellan instance
*/
void subghz_protocol_encoder_magellan_free(void* context);
/**
* Deserialize and generating an upload to send.
* @param context Pointer to a SubGhzProtocolEncoderMagellan instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Forced transmission stop.
* @param context Pointer to a SubGhzProtocolEncoderMagellan instance
*/
void subghz_protocol_encoder_magellan_stop(void* context);
/**
* Getting the level and duration of the upload to be loaded into DMA.
* @param context Pointer to a SubGhzProtocolEncoderMagellan instance
* @return LevelDuration
*/
LevelDuration subghz_protocol_encoder_magellan_yield(void* context);
/**
* Allocate SubGhzProtocolDecoderMagellan.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolDecoderMagellan* pointer to a SubGhzProtocolDecoderMagellan instance
*/
void* subghz_protocol_decoder_magellan_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolDecoderMagellan.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
*/
void subghz_protocol_decoder_magellan_free(void* context);
/**
* Reset decoder SubGhzProtocolDecoderMagellan.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
*/
void subghz_protocol_decoder_magellan_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void subghz_protocol_decoder_magellan_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
* @return hash Hash sum
*/
uint8_t subghz_protocol_decoder_magellan_get_hash_data(void* context);
/**
* Serialize data SubGhzProtocolDecoderMagellan.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
* @return true On success
*/
bool subghz_protocol_decoder_magellan_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzPresetDefinition* preset);
/**
* Deserialize data SubGhzProtocolDecoderMagellan.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a SubGhzProtocolDecoderMagellan instance
* @param output Resulting text
*/
void subghz_protocol_decoder_magellan_get_string(void* context, FuriString* output);

View file

@ -1,6 +1,6 @@
#include "registry.h" #include "protocol_items.h"
const SubGhzProtocol* subghz_protocol_registry[] = { const SubGhzProtocol* subghz_protocol_registry_items[] = {
&subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line,
&subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh,
&subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo,
@ -11,26 +11,9 @@ const SubGhzProtocol* subghz_protocol_registry[] = {
&subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek,
&subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec,
&subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2,
&subghz_protocol_honeywell_wdb, &subghz_protocol_magellen, &subghz_protocol_intertechno_v3, &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3,
&subghz_protocol_clemsa, &subghz_protocol_oregon2}; &subghz_protocol_clemsa, &subghz_protocol_oregon2};
const SubGhzProtocol* subghz_protocol_registry_get_by_name(const char* name) { const SubGhzProtocolRegistry subghz_protocol_registry = {
for(size_t i = 0; i < subghz_protocol_registry_count(); i++) { .items = subghz_protocol_registry_items,
if(strcmp(name, subghz_protocol_registry[i]->name) == 0) { .size = COUNT_OF(subghz_protocol_registry_items)};
return subghz_protocol_registry[i];
}
}
return NULL;
}
const SubGhzProtocol* subghz_protocol_registry_get_by_index(size_t index) {
if(index < subghz_protocol_registry_count()) {
return subghz_protocol_registry[index];
} else {
return NULL;
}
}
size_t subghz_protocol_registry_count() {
return COUNT_OF(subghz_protocol_registry);
}

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "../registry.h"
#include "../types.h"
#include "princeton.h" #include "princeton.h"
#include "keeloq.h" #include "keeloq.h"
@ -33,35 +32,9 @@
#include "doitrand.h" #include "doitrand.h"
#include "phoenix_v2.h" #include "phoenix_v2.h"
#include "honeywell_wdb.h" #include "honeywell_wdb.h"
#include "magellen.h" #include "magellan.h"
#include "intertechno_v3.h" #include "intertechno_v3.h"
#include "clemsa.h" #include "clemsa.h"
#include "oregon2.h" #include "oregon2.h"
#ifdef __cplusplus extern const SubGhzProtocolRegistry subghz_protocol_registry;
extern "C" {
#endif
/**
* Registration by name SubGhzProtocol.
* @param name Protocol name
* @return SubGhzProtocol* pointer to a SubGhzProtocol instance
*/
const SubGhzProtocol* subghz_protocol_registry_get_by_name(const char* name);
/**
* Registration protocol by index in array SubGhzProtocol.
* @param index Protocol by index in array
* @return SubGhzProtocol* pointer to a SubGhzProtocol instance
*/
const SubGhzProtocol* subghz_protocol_registry_get_by_index(size_t index);
/**
* Getting the number of registered protocols.
* @return Number of protocols
*/
size_t subghz_protocol_registry_count();
#ifdef __cplusplus
}
#endif

View file

@ -1,6 +1,7 @@
#include "receiver.h" #include "receiver.h"
#include "protocols/registry.h" #include "registry.h"
#include "protocols/protocol_items.h"
#include <m-array.h> #include <m-array.h>
@ -22,9 +23,12 @@ struct SubGhzReceiver {
SubGhzReceiver* subghz_receiver_alloc_init(SubGhzEnvironment* environment) { SubGhzReceiver* subghz_receiver_alloc_init(SubGhzEnvironment* environment) {
SubGhzReceiver* instance = malloc(sizeof(SubGhzReceiver)); SubGhzReceiver* instance = malloc(sizeof(SubGhzReceiver));
SubGhzReceiverSlotArray_init(instance->slots); SubGhzReceiverSlotArray_init(instance->slots);
const SubGhzProtocolRegistry* protocol_registry_items =
subghz_environment_get_protocol_registry(environment);
for(size_t i = 0; i < subghz_protocol_registry_count(); ++i) { for(size_t i = 0; i < subghz_protocol_registry_count(protocol_registry_items); ++i) {
const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_index(i); const SubGhzProtocol* protocol =
subghz_protocol_registry_get_by_index(protocol_registry_items, i);
if(protocol->decoder && protocol->decoder->alloc) { if(protocol->decoder && protocol->decoder->alloc) {
SubGhzReceiverSlot* slot = SubGhzReceiverSlotArray_push_new(instance->slots); SubGhzReceiverSlot* slot = SubGhzReceiverSlotArray_push_new(instance->slots);
@ -34,7 +38,6 @@ SubGhzReceiver* subghz_receiver_alloc_init(SubGhzEnvironment* environment) {
instance->callback = NULL; instance->callback = NULL;
instance->context = NULL; instance->context = NULL;
return instance; return instance;
} }

30
lib/subghz/registry.c Normal file
View file

@ -0,0 +1,30 @@
#include "registry.h"
const SubGhzProtocol* subghz_protocol_registry_get_by_name(
const SubGhzProtocolRegistry* protocol_registry,
const char* name) {
furi_assert(protocol_registry);
for(size_t i = 0; i < subghz_protocol_registry_count(protocol_registry); i++) {
if(strcmp(name, protocol_registry->items[i]->name) == 0) {
return protocol_registry->items[i];
}
}
return NULL;
}
const SubGhzProtocol* subghz_protocol_registry_get_by_index(
const SubGhzProtocolRegistry* protocol_registry,
size_t index) {
furi_assert(protocol_registry);
if(index < subghz_protocol_registry_count(protocol_registry)) {
return protocol_registry->items[index];
} else {
return NULL;
}
}
size_t subghz_protocol_registry_count(const SubGhzProtocolRegistry* protocol_registry) {
furi_assert(protocol_registry);
return protocol_registry->size;
}

47
lib/subghz/registry.h Normal file
View file

@ -0,0 +1,47 @@
#pragma once
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct SubGhzEnvironment SubGhzEnvironment;
typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry;
struct SubGhzProtocolRegistry {
const SubGhzProtocol** items;
const size_t size;
};
/**
* Registration by name SubGhzProtocol.
* @param protocol_registry SubGhzProtocolRegistry
* @param name Protocol name
* @return SubGhzProtocol* pointer to a SubGhzProtocol instance
*/
const SubGhzProtocol* subghz_protocol_registry_get_by_name(
const SubGhzProtocolRegistry* protocol_registry,
const char* name);
/**
* Registration protocol by index in array SubGhzProtocol.
* @param protocol_registry SubGhzProtocolRegistry
* @param index Protocol by index in array
* @return SubGhzProtocol* pointer to a SubGhzProtocol instance
*/
const SubGhzProtocol* subghz_protocol_registry_get_by_index(
const SubGhzProtocolRegistry* protocol_registry,
size_t index);
/**
* Getting the number of registered protocols.
* @param protocol_registry SubGhzProtocolRegistry
* @return Number of protocols
*/
size_t subghz_protocol_registry_count(const SubGhzProtocolRegistry* protocol_registry);
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,6 @@
#include "subghz_setting.h" #include "subghz_setting.h"
#include "subghz_i.h" #include "types.h"
//#include "subghz_i.h"
#include <furi.h> #include <furi.h>
#include <m-list.h> #include <m-list.h>
@ -197,7 +198,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path, bool no
if(file_path) { if(file_path) {
do { do {
if(!flipper_format_file_open_existing(fff_data_file, file_path)) { if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
FURI_LOG_E(TAG, "Error open file %s", file_path); FURI_LOG_I(TAG, "File is not used %s", file_path);
break; break;
} }

View file

@ -6,6 +6,10 @@
#include <furi_hal.h> #include <furi_hal.h>
#include <lib/flipper_format/flipper_format.h> #include <lib/flipper_format/flipper_format.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SUBGHZ_SETTING_DEFAULT_PRESET_COUNT 4 #define SUBGHZ_SETTING_DEFAULT_PRESET_COUNT 4
typedef struct SubGhzSetting SubGhzSetting; typedef struct SubGhzSetting SubGhzSetting;
@ -48,3 +52,7 @@ uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance);
uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance); uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance);
void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup); void subghz_setting_set_default_frequency(SubGhzSetting* instance, uint32_t frequency_to_setup);
#ifdef __cplusplus
}
#endif

View file

@ -1,7 +1,8 @@
#include "transmitter.h" #include "transmitter.h"
#include "protocols/base.h" #include "protocols/base.h"
#include "protocols/registry.h" #include "registry.h"
#include "protocols/protocol_items.h"
struct SubGhzTransmitter { struct SubGhzTransmitter {
const SubGhzProtocol* protocol; const SubGhzProtocol* protocol;
@ -11,14 +12,17 @@ struct SubGhzTransmitter {
SubGhzTransmitter* SubGhzTransmitter*
subghz_transmitter_alloc_init(SubGhzEnvironment* environment, const char* protocol_name) { subghz_transmitter_alloc_init(SubGhzEnvironment* environment, const char* protocol_name) {
SubGhzTransmitter* instance = NULL; SubGhzTransmitter* instance = NULL;
const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name(protocol_name); const SubGhzProtocolRegistry* protocol_registry_items =
subghz_environment_get_protocol_registry(environment);
const SubGhzProtocol* protocol =
subghz_protocol_registry_get_by_name(protocol_registry_items, protocol_name);
if(protocol && protocol->encoder && protocol->encoder->alloc) { if(protocol && protocol->encoder && protocol->encoder->alloc) {
instance = malloc(sizeof(SubGhzTransmitter)); instance = malloc(sizeof(SubGhzTransmitter));
instance->protocol = protocol; instance->protocol = protocol;
instance->protocol_instance = instance->protocol->encoder->alloc(environment); instance->protocol_instance = instance->protocol->encoder->alloc(environment);
} }
return instance; return instance;
} }

View file

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
//#include "m-string.h"
#include <lib/flipper_format/flipper_format.h> #include <lib/flipper_format/flipper_format.h>
#include <lib/toolbox/level_duration.h> #include <lib/toolbox/level_duration.h>
@ -10,7 +11,6 @@
#include "environment.h" #include "environment.h"
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <subghz/helpers/subghz_types.h>
#define SUBGHZ_APP_FOLDER ANY_PATH("subghz") #define SUBGHZ_APP_FOLDER ANY_PATH("subghz")
#define SUBGHZ_RAW_FOLDER EXT_PATH("subghz") #define SUBGHZ_RAW_FOLDER EXT_PATH("subghz")
@ -26,6 +26,15 @@
// Abstract method types // Abstract method types
// //
struct SubGhzPresetDefinition {
FuriString* name;
uint32_t frequency;
uint8_t* data;
size_t data_size;
};
typedef struct SubGhzPresetDefinition SubGhzPresetDefinition;
// Allocator and Deallocator // Allocator and Deallocator
typedef void* (*SubGhzAlloc)(SubGhzEnvironment* environment); typedef void* (*SubGhzAlloc)(SubGhzEnvironment* environment);
typedef void (*SubGhzFree)(void* context); typedef void (*SubGhzFree)(void* context);
@ -74,6 +83,8 @@ typedef enum {
SubGhzProtocolTypeStatic, SubGhzProtocolTypeStatic,
SubGhzProtocolTypeDynamic, SubGhzProtocolTypeDynamic,
SubGhzProtocolTypeRAW, SubGhzProtocolTypeRAW,
SubGhzProtocolWeatherStation,
SubGhzProtocolCustom,
} SubGhzProtocolType; } SubGhzProtocolType;
typedef enum { typedef enum {
@ -96,4 +107,4 @@ typedef struct {
const SubGhzProtocolEncoder* encoder; const SubGhzProtocolEncoder* encoder;
const SubGhzProtocolDecoder* decoder; const SubGhzProtocolDecoder* decoder;
} SubGhzProtocol; } SubGhzProtocol;