From e5682e37f67dc5f55079b6b10ebff7999b9d6033 Mon Sep 17 00:00:00 2001 From: herbenderbler Date: Sat, 14 Mar 2026 18:59:00 -0600 Subject: [PATCH] feat(subghz): add Honeywell 5834-4 keyfob protocol (#4339) - Add Honeywell 5834-4 decoder and encoder (345 MHz, 48-bit frame, AM650, pulse-width encoding; Arm Away, Stay, Disarm, Panic) - Register protocol and add Set Type preset Honeywell5834_345 - Add unit tests and test assets (honeywell_5834.sub, Manifest_test) - Size encoder upload buffer for 48-bit frame only (H5834_UPLOAD_MAX) to save ~116 bytes RAM per encoder instance on device --- .../resources/unit_tests/Manifest_test | 4 + .../unit_tests/subghz/honeywell_5834.sub | 7 + .../unit_tests/tests/subghz/subghz_test.c | 16 + .../main/subghz/helpers/subghz_custom_event.h | 1 + .../subghz/scenes/subghz_scene_set_type.c | 16 + lib/subghz/protocols/honeywell_5834.c | 387 ++++++++++++++++++ lib/subghz/protocols/honeywell_5834.h | 111 +++++ lib/subghz/protocols/protocol_items.c | 77 ++-- lib/subghz/protocols/protocol_items.h | 1 + 9 files changed, 569 insertions(+), 51 deletions(-) create mode 100644 applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_5834.sub create mode 100644 lib/subghz/protocols/honeywell_5834.c create mode 100644 lib/subghz/protocols/honeywell_5834.h diff --git a/applications/debug/unit_tests/resources/unit_tests/Manifest_test b/applications/debug/unit_tests/resources/unit_tests/Manifest_test index db2979ee6f9e..06e62748d9de 100644 --- a/applications/debug/unit_tests/resources/unit_tests/Manifest_test +++ b/applications/debug/unit_tests/resources/unit_tests/Manifest_test @@ -40,6 +40,10 @@ F:54ceacb8c156f9534fc7ee0a0911f4da:11380:subghz/holtek_ht12x_raw.sub F:4a9567c1543cf3e7bb5350b635d9076f:31238:subghz/holtek_raw.sub F:ca86c0d78364d704ff62b0698093d396:162:subghz/honeywell_wdb.sub F:f606548c935adc8d8bc804326ef67543:38415:subghz/honeywell_wdb_raw.sub +F:14edaac76a69457b795c5c391cf581b1:12281:subghz/honeywell_5834_arm_away.sub +F:a958447531d0ea1a1f6ee3ccb3501842:10041:subghz/honeywell_5834_disarm.sub +F:d8f736cc1c020e9c062bb8ced371dcba:10239:subghz/honeywell_5834_panic.sub +F:f406deee6ecb957cb40a8edcad58f842:13442:subghz/honeywell_5834_stay.sub F:20bba4b0aec006ced7e82513f9459e31:15532:subghz/hormann_hsm_raw.sub F:3392f2db6aa7777e937db619b86203bb:10637:subghz/ido_117_111_raw.sub F:cc5c7968527cc233ef11a08986e31bf2:167:subghz/intertechno_v3.sub diff --git a/applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_5834.sub b/applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_5834.sub new file mode 100644 index 000000000000..3aa93d07497e --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/subghz/honeywell_5834.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 345000000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Honeywell5834 +Bit: 48 +Key: 00 00 AB CD E0 00 04 00 diff --git a/applications/debug/unit_tests/tests/subghz/subghz_test.c b/applications/debug/unit_tests/tests/subghz/subghz_test.c index ae83ed562ecf..ff69c608808f 100644 --- a/applications/debug/unit_tests/tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/tests/subghz/subghz_test.c @@ -585,6 +585,14 @@ MU_TEST(subghz_decoder_honeywell_wdb_test) { "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); } +MU_TEST(subghz_decoder_honeywell_5834_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/honeywell_5834_raw.sub"), + SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME), + "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME " error\r\n"); +} + MU_TEST(subghz_decoder_magellan_test) { mu_assert( subghz_decoder_test( @@ -837,6 +845,12 @@ MU_TEST(subghz_encoder_honeywell_wdb_test) { "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n"); } +MU_TEST(subghz_encoder_honeywell_5834_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/honeywell_5834.sub")), + "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME " error\r\n"); +} + MU_TEST(subghz_encoder_magellan_test) { mu_assert( subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellan.sub")), @@ -973,6 +987,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_doitrand_test); MU_RUN_TEST(subghz_decoder_phoenix_v2_test); MU_RUN_TEST(subghz_decoder_honeywell_wdb_test); + MU_RUN_TEST(subghz_decoder_honeywell_5834_test); MU_RUN_TEST(subghz_decoder_magellan_test); MU_RUN_TEST(subghz_decoder_intertechno_v3_test); MU_RUN_TEST(subghz_decoder_clemsa_test); @@ -1012,6 +1027,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_doitrand_test); MU_RUN_TEST(subghz_encoder_phoenix_v2_test); MU_RUN_TEST(subghz_encoder_honeywell_wdb_test); + MU_RUN_TEST(subghz_encoder_honeywell_5834_test); MU_RUN_TEST(subghz_encoder_magellan_test); MU_RUN_TEST(subghz_encoder_intertechno_v3_test); MU_RUN_TEST(subghz_encoder_clemsa_test); diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index 571f3feb9c96..6555a4fd7c7c 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -22,6 +22,7 @@ typedef enum { SubmenuIndexSecPlus_v2_310_00, SubmenuIndexSecPlus_v2_315_00, SubmenuIndexSecPlus_v2_390_00, + SubmenuIndexHoneywell5834_345, //SubGhzCustomEvent SubGhzCustomEventSceneDeleteSuccess = 100, diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index f76bd9e27d28..f6c87584af64 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -109,6 +109,12 @@ void subghz_scene_set_type_on_enter(void* context) { SubmenuIndexSecPlus_v2_390_00, subghz_scene_set_type_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "Honeywell5834_345", + SubmenuIndexHoneywell5834_345, + subghz_scene_set_type_submenu_callback, + subghz); submenu_set_selected_item( subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType)); @@ -212,6 +218,16 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { generated_protocol = subghz_txrx_gen_secplus_v2_protocol( subghz->txrx, "AM650", 390000000, key, 0x68, 0xE500000); break; + case SubmenuIndexHoneywell5834_345: { + /* 20-bit random serial in bits [47:28], default Arm Away state */ + uint64_t serial_20 = (uint64_t)(key & 0xFFFFF) << 28; + uint64_t state_bits = (uint64_t)0x40 << 4; /* Arm Away in state byte */ + uint64_t frame = serial_20 | state_bits; + /* Set parity: bit 0 = popcount parity of bits [47:1] */ + frame |= subghz_protocol_blocks_get_parity(frame >> 1, 47); + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 345000000, SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME, frame, 48); + } break; default: return false; break; diff --git a/lib/subghz/protocols/honeywell_5834.c b/lib/subghz/protocols/honeywell_5834.c new file mode 100644 index 000000000000..6a84dfbf5369 --- /dev/null +++ b/lib/subghz/protocols/honeywell_5834.c @@ -0,0 +1,387 @@ +#include "honeywell_5834.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolHoneywell5834" + +/* + * Honeywell 5834-4 wireless security keyfob + * Frequency: 345.000 MHz + * Modulation: AM/OOK (AM650 preset) + * Encoding: Pulse-width modulation (pulse duration encodes bit) + * short pulse (<183 µs) = 0, long pulse (>=183 µs) = 1 + * + * Frame: sync_gap(710µs low) + sync_pulse(300µs high) + gap + 48 data bits + * Data layout (same 5800 family as WDB): + * bits [47:28] = 20-bit serial/device ID + * bits [27:2] = device type, channel, state, loop + * bit [0] = parity (LSB of popcount of bits [47:1]) + * + * Buttons: Arm Away, Arm Stay, Disarm, Panic + */ + +/* Timing constants (µs) derived from RAW captures */ +#define H5834_TE_SHORT 160 +#define H5834_TE_LONG 290 +#define H5834_TE_DELTA 80 +#define H5834_SYNC_GAP 710 +#define H5834_SYNC_PULSE 300 +#define H5834_GAP 120 +#define H5834_MIN_COUNT_BIT 48 +/* Encoder: sync(3) + 48 data bits * 2 (pulse+gap) = 99 LevelDuration entries */ +#define H5834_UPLOAD_MAX (3 + (H5834_MIN_COUNT_BIT * 2)) + +static const SubGhzBlockConst subghz_protocol_honeywell_5834_const = { + .te_short = H5834_TE_SHORT, + .te_long = H5834_TE_LONG, + .te_delta = H5834_TE_DELTA, + .min_count_bit_for_found = H5834_MIN_COUNT_BIT, +}; + +struct SubGhzProtocolDecoderHoneywell5834 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderHoneywell5834 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + Honeywell5834DecoderStepReset = 0, + Honeywell5834DecoderStepFoundSyncGap, + Honeywell5834DecoderStepSaveDuration, + Honeywell5834DecoderStepCheckDuration, +} Honeywell5834DecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_honeywell_5834_decoder = { + .alloc = subghz_protocol_decoder_honeywell_5834_alloc, + .free = subghz_protocol_decoder_honeywell_5834_free, + + .feed = subghz_protocol_decoder_honeywell_5834_feed, + .reset = subghz_protocol_decoder_honeywell_5834_reset, + + .get_hash_data = subghz_protocol_decoder_honeywell_5834_get_hash_data, + .serialize = subghz_protocol_decoder_honeywell_5834_serialize, + .deserialize = subghz_protocol_decoder_honeywell_5834_deserialize, + .get_string = subghz_protocol_decoder_honeywell_5834_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_honeywell_5834_encoder = { + .alloc = subghz_protocol_encoder_honeywell_5834_alloc, + .free = subghz_protocol_encoder_honeywell_5834_free, + + .deserialize = subghz_protocol_encoder_honeywell_5834_deserialize, + .stop = subghz_protocol_encoder_honeywell_5834_stop, + .yield = subghz_protocol_encoder_honeywell_5834_yield, +}; + +const SubGhzProtocol subghz_protocol_honeywell_5834 = { + .name = SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | + SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_honeywell_5834_decoder, + .encoder = &subghz_protocol_honeywell_5834_encoder, +}; + +/* ─── Encoder ─────────────────────────────────────────────────────────── */ + +void* subghz_protocol_encoder_honeywell_5834_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderHoneywell5834* instance = + malloc(sizeof(SubGhzProtocolEncoderHoneywell5834)); + + instance->base.protocol = &subghz_protocol_honeywell_5834; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = H5834_UPLOAD_MAX; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_honeywell_5834_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderHoneywell5834* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generate an upload from data. + * Frame on air: sync_gap (low) + sync_pulse (high) + gap (low) + data bits (pulse-width encoded) + */ +static bool subghz_protocol_encoder_honeywell_5834_get_upload( + SubGhzProtocolEncoderHoneywell5834* instance) { + furi_assert(instance); + + /* sync(3) + data_bits * 2; 48-bit frame => 99 entries (H5834_UPLOAD_MAX) */ + size_t index = 0; + size_t size_upload = 3 + (instance->generic.data_count_bit * 2); + if(size_upload > H5834_UPLOAD_MAX) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } + instance->encoder.size_upload = size_upload; + + /* Sync: gap (low) + pulse (high) + short gap (low) */ + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)H5834_SYNC_GAP); + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)H5834_SYNC_PULSE); + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)H5834_GAP); + + /* Data bits – MSB first (bit data_count_bit-1 .. 0) */ + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + /* bit 1: long pulse */ + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)H5834_TE_LONG); + } else { + /* bit 0: short pulse */ + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)H5834_TE_SHORT); + } + /* inter-bit gap */ + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)H5834_GAP); + } + /* Replace last inter-bit gap with inter-frame tail for decoder frame-end detection */ + instance->encoder.upload[index - 1] = level_duration_make(false, 15000); + return true; +} + +SubGhzProtocolStatus subghz_protocol_encoder_honeywell_5834_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderHoneywell5834* instance = context; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_honeywell_5834_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { + break; + } + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_honeywell_5834_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } + instance->encoder.is_running = true; + } while(false); + + return ret; +} + +void subghz_protocol_encoder_honeywell_5834_stop(void* context) { + SubGhzProtocolEncoderHoneywell5834* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_honeywell_5834_yield(void* context) { + SubGhzProtocolEncoderHoneywell5834* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +/* ─── Decoder ─────────────────────────────────────────────────────────── */ + +void* subghz_protocol_decoder_honeywell_5834_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderHoneywell5834* instance = + malloc(sizeof(SubGhzProtocolDecoderHoneywell5834)); + instance->base.protocol = &subghz_protocol_honeywell_5834; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_honeywell_5834_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + free(instance); +} + +void subghz_protocol_decoder_honeywell_5834_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + instance->decoder.parser_step = Honeywell5834DecoderStepReset; +} + +void subghz_protocol_decoder_honeywell_5834_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + + switch(instance->decoder.parser_step) { + case Honeywell5834DecoderStepReset: + if((!level) && (DURATION_DIFF(duration, H5834_SYNC_GAP) < 200)) { + /* Found sync gap (~710 µs low) */ + instance->decoder.decode_count_bit = 0; + instance->decoder.decode_data = 0; + instance->decoder.parser_step = Honeywell5834DecoderStepFoundSyncGap; + } + break; + + case Honeywell5834DecoderStepFoundSyncGap: + if(level && (DURATION_DIFF(duration, H5834_SYNC_PULSE) < 150)) { + /* Found sync pulse (~300 µs high) – next is short gap, then data */ + instance->decoder.parser_step = Honeywell5834DecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Honeywell5834DecoderStepReset; + } + break; + + case Honeywell5834DecoderStepSaveDuration: + if(level) { + /* HIGH pulse – save for classification in next LOW */ + instance->decoder.te_last = duration; + instance->decoder.parser_step = Honeywell5834DecoderStepCheckDuration; + } else { + /* LOW gap before first data pulse (post-sync gap) – skip */ + if(duration > 10000) { + /* Very long gap: frame ended before any data */ + instance->decoder.parser_step = Honeywell5834DecoderStepReset; + } + /* Otherwise stay in StepSaveDuration, waiting for next HIGH */ + } + break; + + case Honeywell5834DecoderStepCheckDuration: + if(!level) { + /* LOW gap – classify the preceding pulse */ + if(DURATION_DIFF(instance->decoder.te_last, H5834_TE_SHORT) < + subghz_protocol_honeywell_5834_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else if( + DURATION_DIFF(instance->decoder.te_last, H5834_TE_LONG) < + subghz_protocol_honeywell_5834_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else { + /* Pulse doesn't match either – reset */ + instance->decoder.parser_step = Honeywell5834DecoderStepReset; + break; + } + + /* Check for frame end (inter-frame gap > 10 ms) */ + if(duration > 10000) { + if(instance->decoder.decode_count_bit >= + subghz_protocol_honeywell_5834_const.min_count_bit_for_found) { + /* Parity check: bit 0 == parity of bits [1..47] */ + if((instance->decoder.decode_data & 0x01) == + subghz_protocol_blocks_get_parity( + instance->decoder.decode_data >> 1, + subghz_protocol_honeywell_5834_const.min_count_bit_for_found - 1)) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + instance->decoder.parser_step = Honeywell5834DecoderStepReset; + } else { + instance->decoder.parser_step = Honeywell5834DecoderStepSaveDuration; + } + } else { + instance->decoder.parser_step = Honeywell5834DecoderStepReset; + } + break; + } +} + +/** + * Extract fields from received data. + * Uses the Honeywell 5800-series frame layout (same family as WDB). + */ +static const char* subghz_protocol_honeywell_5834_get_button_name(uint8_t state_data) { + /* State/button byte: lower bits indicate function. + * Exact mapping derived from captures; common 5800-series values: */ + switch(state_data & 0xF0) { + case 0x40: + return "Arm Away"; + case 0x20: + return "Arm Stay"; + case 0x10: + return "Disarm"; + case 0x80: + return "Panic"; + default: + return "Unknown"; + } +} + +uint8_t subghz_protocol_decoder_honeywell_5834_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_5834_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_5834_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_honeywell_5834_const.min_count_bit_for_found); +} + +void subghz_protocol_decoder_honeywell_5834_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderHoneywell5834* instance = context; + + uint32_t serial = (instance->generic.data >> 28) & 0xFFFFF; + uint8_t state_data = (instance->generic.data >> 4) & 0xFF; + const char* btn_name = subghz_protocol_honeywell_5834_get_button_name(state_data); + uint8_t lowbat = (uint8_t)((instance->generic.data >> 1) & 0x1); + + furi_string_cat_printf( + output, + "%s\r\n" + "Key:0x%lX%08lX %dbit\r\n" + "Sn:0x%05lX Btn:%s\r\n" + "LBat:%01X\r\n", + instance->generic.protocol_name, + (uint32_t)((instance->generic.data >> 32) & 0xFFFFFFFF), + (uint32_t)(instance->generic.data & 0xFFFFFFFF), + instance->generic.data_count_bit, + serial, + btn_name, + lowbat); +} diff --git a/lib/subghz/protocols/honeywell_5834.h b/lib/subghz/protocols/honeywell_5834.h new file mode 100644 index 000000000000..879b91594524 --- /dev/null +++ b/lib/subghz/protocols/honeywell_5834.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_HONEYWELL_5834_NAME "Honeywell5834" + +typedef struct SubGhzProtocolDecoderHoneywell5834 SubGhzProtocolDecoderHoneywell5834; +typedef struct SubGhzProtocolEncoderHoneywell5834 SubGhzProtocolEncoderHoneywell5834; + +extern const SubGhzProtocolDecoder subghz_protocol_honeywell_5834_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_honeywell_5834_encoder; +extern const SubGhzProtocol subghz_protocol_honeywell_5834; + +/** + * Allocate SubGhzProtocolEncoderHoneywell5834. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderHoneywell5834* pointer to instance + */ +void* subghz_protocol_encoder_honeywell_5834_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderHoneywell5834. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell5834 instance + */ +void subghz_protocol_encoder_honeywell_5834_free(void* context); + +/** + * Deserialize and generate an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell5834 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return status + */ +SubGhzProtocolStatus subghz_protocol_encoder_honeywell_5834_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell5834 instance + */ +void subghz_protocol_encoder_honeywell_5834_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderHoneywell5834 instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_honeywell_5834_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderHoneywell5834. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderHoneywell5834* pointer to instance + */ +void* subghz_protocol_decoder_honeywell_5834_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderHoneywell5834. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + */ +void subghz_protocol_decoder_honeywell_5834_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderHoneywell5834. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + */ +void subghz_protocol_decoder_honeywell_5834_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_honeywell_5834_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_honeywell_5834_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderHoneywell5834. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return status + */ +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_5834_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderHoneywell5834. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return status + */ +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_5834_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderHoneywell5834 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_honeywell_5834_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 91ceaec32029..e450a465984d 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -1,57 +1,32 @@ #include "protocol_items.h" // IWYU pragma: keep const SubGhzProtocol* const subghz_protocol_registry_items[] = { - &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_flor_s, - &subghz_protocol_came_twee, - &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, - &subghz_protocol_ido, - &subghz_protocol_kia, - &subghz_protocol_hormann, - &subghz_protocol_nero_radio, - &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, - &subghz_protocol_scher_khan, - &subghz_protocol_princeton, - &subghz_protocol_raw, - &subghz_protocol_linear, - &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, - &subghz_protocol_megacode, - &subghz_protocol_holtek, - &subghz_protocol_chamb_code, - &subghz_protocol_power_smart, - &subghz_protocol_marantec, - &subghz_protocol_bett, - &subghz_protocol_doitrand, - &subghz_protocol_phoenix_v2, - &subghz_protocol_honeywell_wdb, - &subghz_protocol_magellan, - &subghz_protocol_intertechno_v3, - &subghz_protocol_clemsa, - &subghz_protocol_ansonic, - &subghz_protocol_smc5326, - &subghz_protocol_holtek_th12x, - &subghz_protocol_linear_delta3, - &subghz_protocol_dooya, - &subghz_protocol_alutech_at_4n, - &subghz_protocol_kinggates_stylo_4k, - &subghz_protocol_bin_raw, - &subghz_protocol_mastercode, - &subghz_protocol_legrand, - &subghz_protocol_dickert_mahs, - &subghz_protocol_gangqi, - &subghz_protocol_marantec24, - &subghz_protocol_hollarm, - &subghz_protocol_hay21, - &subghz_protocol_revers_rb2, - &subghz_protocol_feron, + &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_flor_s, &subghz_protocol_came_twee, + &subghz_protocol_came_atomo, &subghz_protocol_nero_sketch, + &subghz_protocol_ido, &subghz_protocol_kia, + &subghz_protocol_hormann, &subghz_protocol_nero_radio, + &subghz_protocol_somfy_telis, &subghz_protocol_somfy_keytis, + &subghz_protocol_scher_khan, &subghz_protocol_princeton, + &subghz_protocol_raw, &subghz_protocol_linear, + &subghz_protocol_secplus_v2, &subghz_protocol_secplus_v1, + &subghz_protocol_megacode, &subghz_protocol_holtek, + &subghz_protocol_chamb_code, &subghz_protocol_power_smart, + &subghz_protocol_marantec, &subghz_protocol_bett, + &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, + &subghz_protocol_honeywell_wdb, &subghz_protocol_honeywell_5834, + &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, + &subghz_protocol_clemsa, &subghz_protocol_ansonic, + &subghz_protocol_smc5326, &subghz_protocol_holtek_th12x, + &subghz_protocol_linear_delta3, &subghz_protocol_dooya, + &subghz_protocol_alutech_at_4n, &subghz_protocol_kinggates_stylo_4k, + &subghz_protocol_bin_raw, &subghz_protocol_mastercode, + &subghz_protocol_legrand, &subghz_protocol_dickert_mahs, + &subghz_protocol_gangqi, &subghz_protocol_marantec24, + &subghz_protocol_hollarm, &subghz_protocol_hay21, + &subghz_protocol_revers_rb2, &subghz_protocol_feron, &subghz_protocol_roger, }; diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 1cde46ef5000..fc64f6e9d2ee 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -34,6 +34,7 @@ #include "doitrand.h" #include "phoenix_v2.h" #include "honeywell_wdb.h" +#include "honeywell_5834.h" #include "magellan.h" #include "intertechno_v3.h" #include "clemsa.h"