Просмотр исходного кода

[FL-2723] SubGhz: add protocol Honeywell_WDB / Doorbell (#1560)

* SubGhz: add protocol Honeywell_WDB (receive/save/load/transfer)
* SubGhz: add  parsing data honeywell
* SubGhz: fix UI CAME TWEE
* SubGhz: add unit_test honeywell_wdb

Co-authored-by: あく <alleteam@gmail.com>
Skorpionm 3 лет назад
Родитель
Сommit
a39111ade2

+ 17 - 1
applications/unit_tests/subghz/subghz_test.c

@@ -13,7 +13,7 @@
 #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
 #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
 #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
-#define TEST_RANDOM_COUNT_PARSE 158
+#define TEST_RANDOM_COUNT_PARSE 188
 #define TEST_TIMEOUT 10000
 
 static SubGhzEnvironment* environment_handler;
@@ -404,6 +404,14 @@ MU_TEST(subghz_decoder_phoenix_v2_test) {
         "Test decoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
 }
 
+MU_TEST(subghz_decoder_honeywell_wdb_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/honeywell_wdb_raw.sub"),
+            SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
+}
+
 //test encoders
 MU_TEST(subghz_encoder_princeton_test) {
     mu_assert(
@@ -501,6 +509,12 @@ MU_TEST(subghz_encoder_phoenix_v2_test) {
         "Test encoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
 }
 
+MU_TEST(subghz_encoder_honeywell_wdb_test) {
+    mu_assert(
+        subghz_encoder_test(EXT_PATH("unit_tests/subghz/honeywell_wdb.sub")),
+        "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
+}
+
 MU_TEST(subghz_random_test) {
     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
 }
@@ -537,6 +551,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_decoder_bett_test);
     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_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_came_test);
@@ -554,6 +569,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_encoder_bett_test);
     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_random_test);
     subghz_test_deinit();

+ 7 - 0
assets/unit_tests/subghz/honeywell_wdb.sub

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 868350000
+Preset: FuriHalSubGhzPreset2FSKDev476Async
+Protocol: Honeywell
+Bit: 48
+Key: 00 00 0E DB 70 20 00 01

Разница между файлами не показана из-за своего большого размера
+ 5 - 0
assets/unit_tests/subghz/honeywell_wdb_raw.sub


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
assets/unit_tests/subghz/test_random_raw.sub


+ 8 - 0
lib/subghz/blocks/math.c

@@ -7,3 +7,11 @@ uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit) {
     }
     return key_reverse;
 }
+
+uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit) {
+    uint8_t parity = 0;
+    for(uint8_t i = 0; i < count_bit; i++) {
+        parity += bit_read(key, i);
+    }
+    return parity & 0x01;
+}

+ 8 - 0
lib/subghz/blocks/math.h

@@ -17,3 +17,11 @@
  * @return Reverse data
  */
 uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t count_bit);
+
+/**
+ * Get parity the data bitwise.
+ * @param key In data
+ * @param count_bit number of data bits
+ * @return parity
+ */
+uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t count_bit);

+ 1 - 1
lib/subghz/protocols/came_twee.c

@@ -455,7 +455,7 @@ void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output
 
     string_cat_printf(
         output,
-        "%s %dbit\r\n"
+        "%s %db\r\n"
         "Key:0x%lX%08lX\r\n"
         "Btn:%lX\r\n"
         "DIP:" DIP_PATTERN "\r\n",

+ 399 - 0
lib/subghz/protocols/honeywell_wdb.c

@@ -0,0 +1,399 @@
+#include "honeywell_wdb.h"
+
+#include "../blocks/const.h"
+#include "../blocks/decoder.h"
+#include "../blocks/encoder.h"
+#include "../blocks/generic.h"
+#include "../blocks/math.h"
+
+#define TAG "SubGhzProtocolHoneywellWDB"
+
+/*
+ * 
+ * https://github.com/klohner/honeywell-wireless-doorbell
+ *
+ */
+
+static const SubGhzBlockConst subghz_protocol_honeywell_wdb_const = {
+    .te_short = 160,
+    .te_long = 320,
+    .te_delta = 60,
+    .min_count_bit_for_found = 48,
+};
+
+struct SubGhzProtocolDecoderHoneywell_WDB {
+    SubGhzProtocolDecoderBase base;
+
+    SubGhzBlockDecoder decoder;
+    SubGhzBlockGeneric generic;
+    const char* device_type;
+    const char* alert;
+    uint8_t secret_knock;
+    uint8_t relay;
+    uint8_t lowbat;
+};
+
+struct SubGhzProtocolEncoderHoneywell_WDB {
+    SubGhzProtocolEncoderBase base;
+
+    SubGhzProtocolBlockEncoder encoder;
+    SubGhzBlockGeneric generic;
+};
+
+typedef enum {
+    Honeywell_WDBDecoderStepReset = 0,
+    Honeywell_WDBDecoderStepFoundStartBit,
+    Honeywell_WDBDecoderStepSaveDuration,
+    Honeywell_WDBDecoderStepCheckDuration,
+} Honeywell_WDBDecoderStep;
+
+const SubGhzProtocolDecoder subghz_protocol_honeywell_wdb_decoder = {
+    .alloc = subghz_protocol_decoder_honeywell_wdb_alloc,
+    .free = subghz_protocol_decoder_honeywell_wdb_free,
+
+    .feed = subghz_protocol_decoder_honeywell_wdb_feed,
+    .reset = subghz_protocol_decoder_honeywell_wdb_reset,
+
+    .get_hash_data = subghz_protocol_decoder_honeywell_wdb_get_hash_data,
+    .serialize = subghz_protocol_decoder_honeywell_wdb_serialize,
+    .deserialize = subghz_protocol_decoder_honeywell_wdb_deserialize,
+    .get_string = subghz_protocol_decoder_honeywell_wdb_get_string,
+};
+
+const SubGhzProtocolEncoder subghz_protocol_honeywell_wdb_encoder = {
+    .alloc = subghz_protocol_encoder_honeywell_wdb_alloc,
+    .free = subghz_protocol_encoder_honeywell_wdb_free,
+
+    .deserialize = subghz_protocol_encoder_honeywell_wdb_deserialize,
+    .stop = subghz_protocol_encoder_honeywell_wdb_stop,
+    .yield = subghz_protocol_encoder_honeywell_wdb_yield,
+};
+
+const SubGhzProtocol subghz_protocol_honeywell_wdb = {
+    .name = SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME,
+    .type = SubGhzProtocolTypeStatic,
+    .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM |
+            SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save |
+            SubGhzProtocolFlag_Send,
+
+    .decoder = &subghz_protocol_honeywell_wdb_decoder,
+    .encoder = &subghz_protocol_honeywell_wdb_encoder,
+};
+
+void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolEncoderHoneywell_WDB* instance =
+        malloc(sizeof(SubGhzProtocolEncoderHoneywell_WDB));
+
+    instance->base.protocol = &subghz_protocol_honeywell_wdb;
+    instance->generic.protocol_name = instance->base.protocol->name;
+
+    instance->encoder.repeat = 10;
+    instance->encoder.size_upload = 128;
+    instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
+    instance->encoder.is_runing = false;
+    return instance;
+}
+
+void subghz_protocol_encoder_honeywell_wdb_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolEncoderHoneywell_WDB* instance = context;
+    free(instance->encoder.upload);
+    free(instance);
+}
+
+/**
+ * Generating an upload from data.
+ * @param instance Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ * @return true On success
+ */
+static bool subghz_protocol_encoder_honeywell_wdb_get_upload(
+    SubGhzProtocolEncoderHoneywell_WDB* instance) {
+    furi_assert(instance);
+    size_t index = 0;
+    size_t size_upload = (instance->generic.data_count_bit * 2) + 2;
+    if(size_upload > instance->encoder.size_upload) {
+        FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
+        return false;
+    } else {
+        instance->encoder.size_upload = size_upload;
+    }
+    //Send header
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short * 3);
+    //Send key data
+    for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
+        if(bit_read(instance->generic.data, i - 1)) {
+            //send bit 1
+            instance->encoder.upload[index++] =
+                level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_long);
+            instance->encoder.upload[index++] =
+                level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short);
+        } else {
+            //send bit 0
+            instance->encoder.upload[index++] =
+                level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short);
+            instance->encoder.upload[index++] =
+                level_duration_make(false, (uint32_t)subghz_protocol_honeywell_wdb_const.te_long);
+        }
+    }
+    instance->encoder.upload[index++] =
+        level_duration_make(true, (uint32_t)subghz_protocol_honeywell_wdb_const.te_short * 3);
+    return true;
+}
+
+bool subghz_protocol_encoder_honeywell_wdb_deserialize(
+    void* context,
+    FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolEncoderHoneywell_WDB* instance = context;
+    bool res = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            FURI_LOG_E(TAG, "Deserialize error");
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) {
+            FURI_LOG_E(TAG, "Wrong number of bits in key");
+            break;
+        }
+        //optional parameter parameter
+        flipper_format_read_uint32(
+            flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
+
+        subghz_protocol_encoder_honeywell_wdb_get_upload(instance);
+        instance->encoder.is_runing = true;
+
+        res = true;
+    } while(false);
+
+    return res;
+}
+
+void subghz_protocol_encoder_honeywell_wdb_stop(void* context) {
+    SubGhzProtocolEncoderHoneywell_WDB* instance = context;
+    instance->encoder.is_runing = false;
+}
+
+LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context) {
+    SubGhzProtocolEncoderHoneywell_WDB* instance = context;
+
+    if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
+        instance->encoder.is_runing = false;
+        return level_duration_reset();
+    }
+
+    LevelDuration ret = instance->encoder.upload[instance->encoder.front];
+
+    if(++instance->encoder.front == instance->encoder.size_upload) {
+        instance->encoder.repeat--;
+        instance->encoder.front = 0;
+    }
+
+    return ret;
+}
+
+void* subghz_protocol_decoder_honeywell_wdb_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolDecoderHoneywell_WDB* instance =
+        malloc(sizeof(SubGhzProtocolDecoderHoneywell_WDB));
+    instance->base.protocol = &subghz_protocol_honeywell_wdb;
+    instance->generic.protocol_name = instance->base.protocol->name;
+    return instance;
+}
+
+void subghz_protocol_decoder_honeywell_wdb_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    free(instance);
+}
+
+void subghz_protocol_decoder_honeywell_wdb_reset(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    instance->decoder.parser_step = Honeywell_WDBDecoderStepReset;
+}
+
+void subghz_protocol_decoder_honeywell_wdb_feed(void* context, bool level, uint32_t duration) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    switch(instance->decoder.parser_step) {
+    case Honeywell_WDBDecoderStepReset:
+        if((!level) && (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short * 3) <
+                        subghz_protocol_honeywell_wdb_const.te_delta)) {
+            //Found header Honeywell_WDB
+            instance->decoder.decode_count_bit = 0;
+            instance->decoder.decode_data = 0;
+            instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration;
+        }
+        break;
+    case Honeywell_WDBDecoderStepSaveDuration:
+        if(level) { //save interval
+            if(DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short * 3) <
+               subghz_protocol_honeywell_wdb_const.te_delta) {
+                if((instance->decoder.decode_count_bit ==
+                    subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) &&
+                   ((instance->decoder.decode_data & 0x01) ==
+                    subghz_protocol_blocks_get_parity(
+                        instance->decoder.decode_data >> 1,
+                        subghz_protocol_honeywell_wdb_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 = Honeywell_WDBDecoderStepReset;
+                break;
+            }
+            instance->decoder.te_last = duration;
+            instance->decoder.parser_step = Honeywell_WDBDecoderStepCheckDuration;
+        } else {
+            instance->decoder.parser_step = Honeywell_WDBDecoderStepReset;
+        }
+        break;
+    case Honeywell_WDBDecoderStepCheckDuration:
+        if(!level) {
+            if((DURATION_DIFF(
+                    instance->decoder.te_last, subghz_protocol_honeywell_wdb_const.te_short) <
+                subghz_protocol_honeywell_wdb_const.te_delta) &&
+               (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_long) <
+                subghz_protocol_honeywell_wdb_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 0);
+                instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration;
+            } else if(
+                (DURATION_DIFF(
+                     instance->decoder.te_last, subghz_protocol_honeywell_wdb_const.te_long) <
+                 subghz_protocol_honeywell_wdb_const.te_delta) &&
+                (DURATION_DIFF(duration, subghz_protocol_honeywell_wdb_const.te_short) <
+                 subghz_protocol_honeywell_wdb_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 1);
+                instance->decoder.parser_step = Honeywell_WDBDecoderStepSaveDuration;
+            } else
+                instance->decoder.parser_step = Honeywell_WDBDecoderStepReset;
+        } else {
+            instance->decoder.parser_step = Honeywell_WDBDecoderStepReset;
+        }
+        break;
+    }
+}
+
+/** 
+ * Analysis of received data
+ * @param instance Pointer to a SubGhzProtocolDecoderHoneywell_WDB* instance
+ */
+static void subghz_protocol_honeywell_wdb_check_remote_controller(
+    SubGhzProtocolDecoderHoneywell_WDB* instance) {
+    /*
+ *
+ * Frame bits used in Honeywell RCWL300A, RCWL330A, Series 3, 5, 9 and all Decor Series Wireless Chimes
+ * 0000 0000 1111 1111 2222 2222 3333 3333 4444 4444 5555 5555
+ * 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210
+ * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XX.. XXX. .... KEY DATA (any change and receiver doesn't seem to recognize signal)
+ * XXXX XXXX XXXX XXXX XXXX .... .... .... .... .... .... .... KEY ID (different for each transmitter)
+ * .... .... .... .... .... 0000 00.. 0000 0000 00.. 000. .... KEY UNKNOWN 0 (always 0 in devices I've tested)
+ * .... .... .... .... .... .... ..XX .... .... .... .... .... DEVICE TYPE (10 = doorbell, 01 = PIR Motion sensor)
+ * .... .... .... .... .... .... .... .... .... ..XX ...X XXX. FLAG DATA (may be modified for possible effects on receiver)
+ * .... .... .... .... .... .... .... .... .... ..XX .... .... ALERT (00 = normal, 01 or 10 = right-left halo light pattern, 11 = full volume alarm)
+ * .... .... .... .... .... .... .... .... .... .... ...X .... SECRET KNOCK (0 = default, 1 if doorbell is pressed 3x rapidly)
+ * .... .... .... .... .... .... .... .... .... .... .... X... RELAY (1 if signal is a retransmission of a received transmission, only some models)
+ * .... .... .... .... .... .... .... .... .... .... .... .X.. FLAG UNKNOWN (0 = default, but 1 is accepted and I don't observe any effects)
+ * .... .... .... .... .... .... .... .... .... .... .... ..X. LOWBAT (1 if battery is low, receiver gives low battery alert)
+ * .... .... .... .... .... .... .... .... .... .... .... ...X PARITY (LSB of count of set bits in previous 47 bits)
+ * 
+ */
+
+    instance->generic.serial = (instance->generic.data >> 28) & 0xFFFFF;
+    switch((instance->generic.data >> 20) & 0x3) {
+    case 0x02:
+        instance->device_type = "Doorbell";
+        break;
+    case 0x01:
+        instance->device_type = "PIR-Motion";
+        break;
+    default:
+        instance->device_type = "Unknown";
+        break;
+    }
+
+    switch((instance->generic.data >> 16) & 0x3) {
+    case 0x00:
+        instance->alert = "Normal";
+        break;
+    case 0x01:
+    case 0x02:
+        instance->alert = "High";
+        break;
+    case 0x03:
+        instance->alert = "Full";
+        break;
+    default:
+        instance->alert = "Unknown";
+        break;
+    }
+
+    instance->secret_knock = (uint8_t)((instance->generic.data >> 4) & 0x1);
+    instance->relay = (uint8_t)((instance->generic.data >> 3) & 0x1);
+    instance->lowbat = (uint8_t)((instance->generic.data >> 1) & 0x1);
+}
+
+uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    return subghz_protocol_blocks_get_hash_data(
+        &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
+}
+
+bool subghz_protocol_decoder_honeywell_wdb_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzPresetDefinition* preset) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
+}
+
+bool subghz_protocol_decoder_honeywell_wdb_deserialize(
+    void* context,
+    FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    bool ret = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) {
+            FURI_LOG_E(TAG, "Wrong number of bits in key");
+            break;
+        }
+        ret = true;
+    } while(false);
+    return ret;
+}
+
+void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, string_t output) {
+    furi_assert(context);
+    SubGhzProtocolDecoderHoneywell_WDB* instance = context;
+    subghz_protocol_honeywell_wdb_check_remote_controller(instance);
+
+    string_cat_printf(
+        output,
+        "%s %dbit\r\n"
+        "Key:0x%lX%08lX\r\n"
+        "Sn:0x%05lX\r\n"
+        "DT:%s  Al:%s\r\n"
+        "SK:%01lX R:%01lX LBat:%01lX\r\n",
+        instance->generic.protocol_name,
+        instance->generic.data_count_bit,
+        (uint32_t)((instance->generic.data >> 32) & 0xFFFFFFFF),
+        (uint32_t)(instance->generic.data & 0xFFFFFFFF),
+        instance->generic.serial,
+        instance->device_type,
+        instance->alert,
+        instance->secret_knock,
+        instance->relay,
+        instance->lowbat);
+}

+ 111 - 0
lib/subghz/protocols/honeywell_wdb.h

@@ -0,0 +1,111 @@
+#pragma once
+
+#include "base.h"
+
+#define SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME "Honeywell"
+
+typedef struct SubGhzProtocolDecoderHoneywell_WDB SubGhzProtocolDecoderHoneywell_WDB;
+typedef struct SubGhzProtocolEncoderHoneywell_WDB SubGhzProtocolEncoderHoneywell_WDB;
+
+extern const SubGhzProtocolDecoder subghz_protocol_honeywell_wdb_decoder;
+extern const SubGhzProtocolEncoder subghz_protocol_honeywell_wdb_encoder;
+extern const SubGhzProtocol subghz_protocol_honeywell_wdb;
+
+/**
+ * Allocate SubGhzProtocolEncoderHoneywell_WDB.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolEncoderHoneywell_WDB* pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ */
+void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolEncoderHoneywell_WDB.
+ * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ */
+void subghz_protocol_encoder_honeywell_wdb_free(void* context);
+
+/**
+ * Deserialize and generating an upload to send.
+ * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_encoder_honeywell_wdb_deserialize(
+    void* context,
+    FlipperFormat* flipper_format);
+
+/**
+ * Forced transmission stop.
+ * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ */
+void subghz_protocol_encoder_honeywell_wdb_stop(void* context);
+
+/**
+ * Getting the level and duration of the upload to be loaded into DMA.
+ * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance
+ * @return LevelDuration 
+ */
+LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context);
+
+/**
+ * Allocate SubGhzProtocolDecoderHoneywell_WDB.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolDecoderHoneywell_WDB* pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ */
+void* subghz_protocol_decoder_honeywell_wdb_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolDecoderHoneywell_WDB.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ */
+void subghz_protocol_decoder_honeywell_wdb_free(void* context);
+
+/**
+ * Reset decoder SubGhzProtocolDecoderHoneywell_WDB.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ */
+void subghz_protocol_decoder_honeywell_wdb_reset(void* context);
+
+/**
+ * Parse a raw sequence of levels and durations received from the air.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ * @param level Signal level true-high false-low
+ * @param duration Duration of this level in, us
+ */
+void subghz_protocol_decoder_honeywell_wdb_feed(void* context, bool level, uint32_t duration);
+
+/**
+ * Getting the hash sum of the last randomly received parcel.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ * @return hash Hash sum
+ */
+uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context);
+
+/**
+ * Serialize data SubGhzProtocolDecoderHoneywell_WDB.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB 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_honeywell_wdb_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzPresetDefinition* preset);
+
+/**
+ * Deserialize data SubGhzProtocolDecoderHoneywell_WDB.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_decoder_honeywell_wdb_deserialize(
+    void* context,
+    FlipperFormat* flipper_format);
+
+/**
+ * Getting a textual representation of the received data.
+ * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance
+ * @param output Resulting text
+ */
+void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, string_t output);

+ 11 - 10
lib/subghz/protocols/registry.c

@@ -1,16 +1,17 @@
 #include "registry.h"
 
 const SubGhzProtocol* subghz_protocol_registry[] = {
-    &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_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,
 
 };
 

+ 1 - 0
lib/subghz/protocols/registry.h

@@ -32,6 +32,7 @@
 #include "bett.h"
 #include "doitrand.h"
 #include "phoenix_v2.h"
+#include "honeywell_wdb.h"
 
 /**
  * Registration by name SubGhzProtocol.

Некоторые файлы не были показаны из-за большого количества измененных файлов