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

[FL-2757] SubGhz: add protocol Magellen (#1633)

* SubGhz: add decoder Paradox Wireless
* SubGhz: fix syntax
* SubGhz: rename paradox_wireless -> magellen, add encoder Magellen, parse event
* SuBghz: add unit_test Magellen

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

+ 16 - 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 188
+#define TEST_RANDOM_COUNT_PARSE 196
 #define TEST_TIMEOUT 10000
 
 static SubGhzEnvironment* environment_handler;
@@ -412,6 +412,13 @@ MU_TEST(subghz_decoder_honeywell_wdb_test) {
         "Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
 }
 
+MU_TEST(subghz_decoder_magellen_test) {
+    mu_assert(
+        subghz_decoder_test(
+            EXT_PATH("unit_tests/subghz/magellen_raw.sub"), SUBGHZ_PROTOCOL_MAGELLEN_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
+}
+
 //test encoders
 MU_TEST(subghz_encoder_princeton_test) {
     mu_assert(
@@ -515,6 +522,12 @@ MU_TEST(subghz_encoder_honeywell_wdb_test) {
         "Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
 }
 
+MU_TEST(subghz_encoder_magellen_test) {
+    mu_assert(
+        subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellen.sub")),
+        "Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
+}
+
 MU_TEST(subghz_random_test) {
     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
 }
@@ -552,6 +565,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_magellen_test);
 
     MU_RUN_TEST(subghz_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_came_test);
@@ -570,6 +584,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_magellen_test);
 
     MU_RUN_TEST(subghz_random_test);
     subghz_test_deinit();

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

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433920000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: Magellen
+Bit: 32
+Key: 00 00 00 00 37 AE 48 28

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


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


+ 444 - 0
lib/subghz/protocols/magellen.c

@@ -0,0 +1,444 @@
+#include "magellen.h"
+
+#include "../blocks/const.h"
+#include "../blocks/decoder.h"
+#include "../blocks/encoder.h"
+#include "../blocks/generic.h"
+#include "../blocks/math.h"
+
+#define TAG "SubGhzProtocolMagellen"
+
+static const SubGhzBlockConst subghz_protocol_magellen_const = {
+    .te_short = 200,
+    .te_long = 400,
+    .te_delta = 100,
+    .min_count_bit_for_found = 32,
+};
+
+struct SubGhzProtocolDecoderMagellen {
+    SubGhzProtocolDecoderBase base;
+
+    SubGhzBlockDecoder decoder;
+    SubGhzBlockGeneric generic;
+    uint16_t header_count;
+};
+
+struct SubGhzProtocolEncoderMagellen {
+    SubGhzProtocolEncoderBase base;
+
+    SubGhzProtocolBlockEncoder encoder;
+    SubGhzBlockGeneric generic;
+};
+
+typedef enum {
+    MagellenDecoderStepReset = 0,
+    MagellenDecoderStepCheckPreambula,
+    MagellenDecoderStepFoundPreambula,
+    MagellenDecoderStepSaveDuration,
+    MagellenDecoderStepCheckDuration,
+} MagellenDecoderStep;
+
+const SubGhzProtocolDecoder subghz_protocol_magellen_decoder = {
+    .alloc = subghz_protocol_decoder_magellen_alloc,
+    .free = subghz_protocol_decoder_magellen_free,
+
+    .feed = subghz_protocol_decoder_magellen_feed,
+    .reset = subghz_protocol_decoder_magellen_reset,
+
+    .get_hash_data = subghz_protocol_decoder_magellen_get_hash_data,
+    .serialize = subghz_protocol_decoder_magellen_serialize,
+    .deserialize = subghz_protocol_decoder_magellen_deserialize,
+    .get_string = subghz_protocol_decoder_magellen_get_string,
+};
+
+const SubGhzProtocolEncoder subghz_protocol_magellen_encoder = {
+    .alloc = subghz_protocol_encoder_magellen_alloc,
+    .free = subghz_protocol_encoder_magellen_free,
+
+    .deserialize = subghz_protocol_encoder_magellen_deserialize,
+    .stop = subghz_protocol_encoder_magellen_stop,
+    .yield = subghz_protocol_encoder_magellen_yield,
+};
+
+const SubGhzProtocol subghz_protocol_magellen = {
+    .name = SUBGHZ_PROTOCOL_MAGELLEN_NAME,
+    .type = SubGhzProtocolTypeStatic,
+    .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
+            SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
+
+    .decoder = &subghz_protocol_magellen_decoder,
+    .encoder = &subghz_protocol_magellen_encoder,
+};
+
+void* subghz_protocol_encoder_magellen_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolEncoderMagellen* instance = malloc(sizeof(SubGhzProtocolEncoderMagellen));
+
+    instance->base.protocol = &subghz_protocol_magellen;
+    instance->generic.protocol_name = instance->base.protocol->name;
+
+    instance->encoder.repeat = 10;
+    instance->encoder.size_upload = 256;
+    instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
+    instance->encoder.is_running = false;
+    return instance;
+}
+
+void subghz_protocol_encoder_magellen_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolEncoderMagellen* instance = context;
+    free(instance->encoder.upload);
+    free(instance);
+}
+
+/**
+ * Generating an upload from data.
+ * @param instance Pointer to a SubGhzProtocolEncoderMagellen instance
+ * @return true On success
+ */
+static bool subghz_protocol_encoder_magellen_get_upload(SubGhzProtocolEncoderMagellen* instance) {
+    furi_assert(instance);
+
+    size_t index = 0;
+
+    //Send header
+    instance->encoder.upload[index++] =
+        level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short * 4);
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short);
+    for(uint8_t i = 0; i < 12; i++) {
+        instance->encoder.upload[index++] =
+            level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short);
+        instance->encoder.upload[index++] =
+            level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short);
+    }
+    instance->encoder.upload[index++] =
+        level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short);
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long);
+
+    //Send start bit
+    instance->encoder.upload[index++] =
+        level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_long * 3);
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long);
+
+    //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_magellen_const.te_short);
+            instance->encoder.upload[index++] =
+                level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long);
+        } else {
+            //send bit 0
+            instance->encoder.upload[index++] =
+                level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_long);
+            instance->encoder.upload[index++] =
+                level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_short);
+        }
+    }
+
+    //Send stop bit
+    instance->encoder.upload[index++] =
+        level_duration_make(true, (uint32_t)subghz_protocol_magellen_const.te_short);
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_magellen_const.te_long * 100);
+
+    instance->encoder.size_upload = index;
+    return true;
+}
+
+bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolEncoderMagellen* 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_magellen_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_magellen_get_upload(instance);
+        instance->encoder.is_running = true;
+
+        res = true;
+    } while(false);
+
+    return res;
+}
+
+void subghz_protocol_encoder_magellen_stop(void* context) {
+    SubGhzProtocolEncoderMagellen* instance = context;
+    instance->encoder.is_running = false;
+}
+
+LevelDuration subghz_protocol_encoder_magellen_yield(void* context) {
+    SubGhzProtocolEncoderMagellen* instance = context;
+
+    if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
+        instance->encoder.is_running = false;
+        return level_duration_reset();
+    }
+
+    LevelDuration ret = instance->encoder.upload[instance->encoder.front];
+
+    if(++instance->encoder.front == instance->encoder.size_upload) {
+        instance->encoder.repeat--;
+        instance->encoder.front = 0;
+    }
+
+    return ret;
+}
+
+void* subghz_protocol_decoder_magellen_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolDecoderMagellen* instance = malloc(sizeof(SubGhzProtocolDecoderMagellen));
+    instance->base.protocol = &subghz_protocol_magellen;
+    instance->generic.protocol_name = instance->base.protocol->name;
+    return instance;
+}
+
+void subghz_protocol_decoder_magellen_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    free(instance);
+}
+
+void subghz_protocol_decoder_magellen_reset(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    instance->decoder.parser_step = MagellenDecoderStepReset;
+}
+
+uint8_t subghz_protocol_magellen_crc8(uint8_t* data, size_t len) {
+    uint8_t crc = 0x00;
+    size_t i, j;
+    for(i = 0; i < len; i++) {
+        crc ^= data[i];
+        for(j = 0; j < 8; j++) {
+            if((crc & 0x80) != 0)
+                crc = (uint8_t)((crc << 1) ^ 0x31);
+            else
+                crc <<= 1;
+        }
+    }
+    return crc;
+}
+
+static bool subghz_protocol_magellen_check_crc(SubGhzProtocolDecoderMagellen* instance) {
+    uint8_t data[3] = {
+        instance->decoder.decode_data >> 24,
+        instance->decoder.decode_data >> 16,
+        instance->decoder.decode_data >> 8};
+    return (instance->decoder.decode_data & 0xFF) ==
+           subghz_protocol_magellen_crc8(data, sizeof(data));
+}
+
+void subghz_protocol_decoder_magellen_feed(void* context, bool level, uint32_t duration) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+
+    switch(instance->decoder.parser_step) {
+    case MagellenDecoderStepReset:
+        if((level) && (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) <
+                       subghz_protocol_magellen_const.te_delta)) {
+            instance->decoder.parser_step = MagellenDecoderStepCheckPreambula;
+            instance->decoder.te_last = duration;
+            instance->header_count = 0;
+        }
+        break;
+
+    case MagellenDecoderStepCheckPreambula:
+        if(level) {
+            instance->decoder.te_last = duration;
+        } else {
+            if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) <
+                subghz_protocol_magellen_const.te_delta) &&
+               (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) <
+                subghz_protocol_magellen_const.te_delta)) {
+                // Found header
+                instance->header_count++;
+            } else if(
+                (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) <
+                 subghz_protocol_magellen_const.te_delta) &&
+                (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) <
+                 subghz_protocol_magellen_const.te_delta * 2) &&
+                (instance->header_count > 10)) {
+                instance->decoder.parser_step = MagellenDecoderStepFoundPreambula;
+            } else {
+                instance->decoder.parser_step = MagellenDecoderStepReset;
+            }
+        }
+        break;
+
+    case MagellenDecoderStepFoundPreambula:
+        if(level) {
+            instance->decoder.te_last = duration;
+        } else {
+            if((DURATION_DIFF(
+                    instance->decoder.te_last, subghz_protocol_magellen_const.te_short * 6) <
+                subghz_protocol_magellen_const.te_delta * 3) &&
+               (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) <
+                subghz_protocol_magellen_const.te_delta * 2)) {
+                instance->decoder.parser_step = MagellenDecoderStepSaveDuration;
+                instance->decoder.decode_data = 0;
+                instance->decoder.decode_count_bit = 0;
+            } else {
+                instance->decoder.parser_step = MagellenDecoderStepReset;
+            }
+        }
+        break;
+
+    case MagellenDecoderStepSaveDuration:
+        if(level) {
+            instance->decoder.te_last = duration;
+            instance->decoder.parser_step = MagellenDecoderStepCheckDuration;
+        } else {
+            instance->decoder.parser_step = MagellenDecoderStepReset;
+        }
+        break;
+
+    case MagellenDecoderStepCheckDuration:
+        if(!level) {
+            if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_short) <
+                subghz_protocol_magellen_const.te_delta) &&
+               (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_long) <
+                subghz_protocol_magellen_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 1);
+                instance->decoder.parser_step = MagellenDecoderStepSaveDuration;
+            } else if(
+                (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_magellen_const.te_long) <
+                 subghz_protocol_magellen_const.te_delta) &&
+                (DURATION_DIFF(duration, subghz_protocol_magellen_const.te_short) <
+                 subghz_protocol_magellen_const.te_delta)) {
+                subghz_protocol_blocks_add_bit(&instance->decoder, 0);
+                instance->decoder.parser_step = MagellenDecoderStepSaveDuration;
+            } else if(duration >= (subghz_protocol_magellen_const.te_long * 3)) {
+                //Found stop bit
+                if((instance->decoder.decode_count_bit ==
+                    subghz_protocol_magellen_const.min_count_bit_for_found) &&
+                   subghz_protocol_magellen_check_crc(instance)) {
+                    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.decode_data = 0;
+                instance->decoder.decode_count_bit = 0;
+                instance->decoder.parser_step = MagellenDecoderStepReset;
+            } else {
+                instance->decoder.parser_step = MagellenDecoderStepReset;
+            }
+        } else {
+            instance->decoder.parser_step = MagellenDecoderStepReset;
+        }
+        break;
+    }
+}
+
+/** 
+ * Analysis of received data
+ * @param instance Pointer to a SubGhzBlockGeneric* instance
+ */
+static void subghz_protocol_magellen_check_remote_controller(SubGhzBlockGeneric* instance) {
+    /*
+*   package 32b            data 24b           CRC8
+*   0x037AE4828 => 001101111010111001001000 00101000
+*   
+*   0x037AE48 (flipped in reverse bit sequence) => 0x1275EC
+*
+*   0x1275EC =>  0x12-event codes, 0x75EC-serial (dec 117236)
+*
+*   event codes
+*   bit_0: 1-alarm, 0-close
+*   bit_1: 1-Tamper On (alarm), 0-Tamper Off (ok)
+*   bit_2: ?
+*   bit_3: 1-power on
+*   bit_4: model type - door alarm
+*   bit_5: model type - motion sensor
+*   bit_6: ?
+*   bit_7: ?
+*
+*/
+    uint64_t data_rev = subghz_protocol_blocks_reverse_key(instance->data >> 8, 24);
+    instance->serial = data_rev & 0xFFFF;
+    instance->btn = (data_rev >> 16) & 0xFF;
+}
+
+static void subghz_protocol_magellen_get_event_serialize(uint8_t event, string_t output) {
+    string_cat_printf(
+        output,
+        "%s%s%s%s%s%s%s%s",
+        (event & 0x1 ? " Alarm" : "Ok"),
+        ((event >> 1) & 0x1 ? ", Tamper On (Alarm)" : ""),
+        ((event >> 2) & 0x1 ? ", ?" : ""),
+        ((event >> 3) & 0x1 ? ", Power On" : ""),
+        ((event >> 4) & 0x1 ? ", MT:Door_Alarm" : ""),
+        ((event >> 5) & 0x1 ? ", MT:Motion_Sensor" : ""),
+        ((event >> 6) & 0x1 ? ", ?" : ""),
+        ((event >> 7) & 0x1 ? ", ?" : ""));
+}
+
+uint8_t subghz_protocol_decoder_magellen_get_hash_data(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    return subghz_protocol_blocks_get_hash_data(
+        &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
+}
+
+bool subghz_protocol_decoder_magellen_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzPresetDefinition* preset) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
+}
+
+bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    bool ret = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            break;
+        }
+        if(instance->generic.data_count_bit !=
+           subghz_protocol_magellen_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_magellen_get_string(void* context, string_t output) {
+    furi_assert(context);
+    SubGhzProtocolDecoderMagellen* instance = context;
+    subghz_protocol_magellen_check_remote_controller(&instance->generic);
+    string_cat_printf(
+        output,
+        "%s %dbit\r\n"
+        "Key:0x%08lX\r\n"
+        "Sn:%03d%03d, Event:0x%02X\r\n"
+        "Stat:",
+        instance->generic.protocol_name,
+        instance->generic.data_count_bit,
+        (uint32_t)(instance->generic.data & 0xFFFFFFFF),
+        (instance->generic.serial >> 8) & 0xFF,
+        instance->generic.serial & 0xFF,
+        instance->generic.btn);
+
+    subghz_protocol_magellen_get_event_serialize(instance->generic.btn, output);
+}

+ 107 - 0
lib/subghz/protocols/magellen.h

@@ -0,0 +1,107 @@
+#pragma once
+
+#include "base.h"
+
+#define SUBGHZ_PROTOCOL_MAGELLEN_NAME "Magellen"
+
+typedef struct SubGhzProtocolDecoderMagellen SubGhzProtocolDecoderMagellen;
+typedef struct SubGhzProtocolEncoderMagellen SubGhzProtocolEncoderMagellen;
+
+extern const SubGhzProtocolDecoder subghz_protocol_magellen_decoder;
+extern const SubGhzProtocolEncoder subghz_protocol_magellen_encoder;
+extern const SubGhzProtocol subghz_protocol_magellen;
+
+/**
+ * Allocate SubGhzProtocolEncoderMagellen.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolEncoderMagellen* pointer to a SubGhzProtocolEncoderMagellen instance
+ */
+void* subghz_protocol_encoder_magellen_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolEncoderMagellen.
+ * @param context Pointer to a SubGhzProtocolEncoderMagellen instance
+ */
+void subghz_protocol_encoder_magellen_free(void* context);
+
+/**
+ * Deserialize and generating an upload to send.
+ * @param context Pointer to a SubGhzProtocolEncoderMagellen instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_encoder_magellen_deserialize(void* context, FlipperFormat* flipper_format);
+
+/**
+ * Forced transmission stop.
+ * @param context Pointer to a SubGhzProtocolEncoderMagellen instance
+ */
+void subghz_protocol_encoder_magellen_stop(void* context);
+
+/**
+ * Getting the level and duration of the upload to be loaded into DMA.
+ * @param context Pointer to a SubGhzProtocolEncoderMagellen instance
+ * @return LevelDuration 
+ */
+LevelDuration subghz_protocol_encoder_magellen_yield(void* context);
+
+/**
+ * Allocate SubGhzProtocolDecoderMagellen.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolDecoderMagellen* pointer to a SubGhzProtocolDecoderMagellen instance
+ */
+void* subghz_protocol_decoder_magellen_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolDecoderMagellen.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ */
+void subghz_protocol_decoder_magellen_free(void* context);
+
+/**
+ * Reset decoder SubGhzProtocolDecoderMagellen.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ */
+void subghz_protocol_decoder_magellen_reset(void* context);
+
+/**
+ * Parse a raw sequence of levels and durations received from the air.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ * @param level Signal level true-high false-low
+ * @param duration Duration of this level in, us
+ */
+void subghz_protocol_decoder_magellen_feed(void* context, bool level, uint32_t duration);
+
+/**
+ * Getting the hash sum of the last randomly received parcel.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ * @return hash Hash sum
+ */
+uint8_t subghz_protocol_decoder_magellen_get_hash_data(void* context);
+
+/**
+ * Serialize data SubGhzProtocolDecoderMagellen.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen 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_magellen_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    SubGhzPresetDefinition* preset);
+
+/**
+ * Deserialize data SubGhzProtocolDecoderMagellen.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_decoder_magellen_deserialize(void* context, FlipperFormat* flipper_format);
+
+/**
+ * Getting a textual representation of the received data.
+ * @param context Pointer to a SubGhzProtocolDecoderMagellen instance
+ * @param output Resulting text
+ */
+void subghz_protocol_decoder_magellen_get_string(void* context, string_t output);

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

@@ -11,7 +11,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = {
     &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_wdb, &subghz_protocol_magellen,
 
 };
 

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

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

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