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

SubGhz: add potocol Hormann HSM 868Mhz (#795)

* SubGhz: add decoder Normann
* SubGhz: rename normann -> hormann
* SubGhz: add encoder hormann
* SubGhz: delete comment

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

+ 254 - 0
lib/subghz/protocols/subghz_protocol_hormann.c

@@ -0,0 +1,254 @@
+#include "subghz_protocol_hormann.h"
+#include "subghz_protocol_common.h"
+
+struct SubGhzProtocolHormann {
+    SubGhzProtocolCommon common;
+};
+
+typedef enum {
+    HormannDecoderStepReset = 0,
+    HormannDecoderStepFoundStartHeader,
+    HormannDecoderStepFoundHeader,
+    HormannDecoderStepFoundStartBit,
+    HormannDecoderStepSaveDuration,
+    HormannDecoderStepCheckDuration,
+} HormannDecoderStep;
+
+SubGhzProtocolHormann* subghz_protocol_hormann_alloc() {
+    SubGhzProtocolHormann* instance = furi_alloc(sizeof(SubGhzProtocolHormann));
+
+    instance->common.name = "Hormann HSM";
+    instance->common.code_min_count_bit_for_found = 44;
+    instance->common.te_short = 511;
+    instance->common.te_long = 1022;
+    instance->common.te_delta = 200;
+    instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
+    instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_hormann_to_str;
+    instance->common.to_save_string =
+        (SubGhzProtocolCommonGetStrSave)subghz_protocol_hormann_to_save_str;
+    instance->common.to_load_protocol_from_file =
+        (SubGhzProtocolCommonLoadFromFile)subghz_protocol_hormann_to_load_protocol_from_file;
+    instance->common.to_load_protocol =
+        (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_hormann_to_load_protocol;
+    instance->common.get_upload_protocol =
+        (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_hormann_send_key;
+
+    return instance;
+}
+
+void subghz_protocol_hormann_free(SubGhzProtocolHormann* instance) {
+    furi_assert(instance);
+    free(instance);
+}
+
+bool subghz_protocol_hormann_send_key(
+    SubGhzProtocolHormann* instance,
+    SubGhzProtocolCommonEncoder* encoder) {
+    furi_assert(instance);
+    furi_assert(encoder);
+
+    size_t index = 0;
+    encoder->size_upload = 3 + (instance->common.code_last_count_bit * 2 + 2) * 20 + 1;
+    if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
+    //Send header
+    encoder->upload[index++] =
+        level_duration_make(false, (uint32_t)instance->common.te_short * 64);
+    encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 64);
+    encoder->upload[index++] =
+        level_duration_make(false, (uint32_t)instance->common.te_short * 64);
+    encoder->repeat = 10;
+
+    for(size_t repeat = 0; repeat < 20; repeat++) {
+        //Send start bit
+        encoder->upload[index++] =
+            level_duration_make(true, (uint32_t)instance->common.te_short * 24);
+        encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
+        //Send key data
+        for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
+            if(bit_read(instance->common.code_last_found, i - 1)) {
+                //send bit 1
+                encoder->upload[index++] =
+                    level_duration_make(true, (uint32_t)instance->common.te_long);
+                encoder->upload[index++] =
+                    level_duration_make(false, (uint32_t)instance->common.te_short);
+            } else {
+                //send bit 0
+                encoder->upload[index++] =
+                    level_duration_make(true, (uint32_t)instance->common.te_short);
+                encoder->upload[index++] =
+                    level_duration_make(false, (uint32_t)instance->common.te_long);
+            }
+        }
+    }
+    encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 24);
+    return true;
+}
+
+void subghz_protocol_hormann_reset(SubGhzProtocolHormann* instance) {
+    instance->common.parser_step = HormannDecoderStepReset;
+}
+
+void subghz_protocol_hormann_parse(SubGhzProtocolHormann* instance, bool level, uint32_t duration) {
+    switch(instance->common.parser_step) {
+    case HormannDecoderStepReset:
+        if((level) && (DURATION_DIFF(duration, instance->common.te_short * 64) <
+                       instance->common.te_delta * 64)) {
+            instance->common.parser_step = HormannDecoderStepFoundStartHeader;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    case HormannDecoderStepFoundStartHeader:
+        if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 64) <
+                        instance->common.te_delta * 64)) {
+            instance->common.parser_step = HormannDecoderStepFoundHeader;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    case HormannDecoderStepFoundHeader:
+        if((level) && (DURATION_DIFF(duration, instance->common.te_short * 24) <
+                       instance->common.te_delta * 24)) {
+            instance->common.parser_step = HormannDecoderStepFoundStartBit;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    case HormannDecoderStepFoundStartBit:
+        if((!level) &&
+           (DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
+            instance->common.parser_step = HormannDecoderStepSaveDuration;
+            instance->common.code_found = 0;
+            instance->common.code_count_bit = 0;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    case HormannDecoderStepSaveDuration:
+        if(level) { //save interval
+            if(duration >= (instance->common.te_short * 5)) {
+                instance->common.parser_step = HormannDecoderStepFoundStartBit;
+                if(instance->common.code_count_bit >=
+                   instance->common.code_min_count_bit_for_found) {
+                    instance->common.serial = 0x0;
+                    instance->common.btn = 0x0;
+
+                    instance->common.code_last_found = instance->common.code_found;
+                    instance->common.code_last_count_bit = instance->common.code_count_bit;
+
+                    if(instance->common.callback)
+                        instance->common.callback(
+                            (SubGhzProtocolCommon*)instance, instance->common.context);
+                }
+                break;
+            }
+            instance->common.te_last = duration;
+            instance->common.parser_step = HormannDecoderStepCheckDuration;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    case HormannDecoderStepCheckDuration:
+        if(!level) {
+            if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
+                instance->common.te_delta) &&
+               (DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
+                subghz_protocol_common_add_bit(&instance->common, 0);
+                instance->common.parser_step = HormannDecoderStepSaveDuration;
+            } else if(
+                (DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
+                 instance->common.te_delta) &&
+                (DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
+                subghz_protocol_common_add_bit(&instance->common, 1);
+                instance->common.parser_step = HormannDecoderStepSaveDuration;
+            } else
+                instance->common.parser_step = HormannDecoderStepReset;
+        } else {
+            instance->common.parser_step = HormannDecoderStepReset;
+        }
+        break;
+    }
+}
+
+void subghz_protocol_hormann_to_str(SubGhzProtocolHormann* instance, string_t output) {
+    uint32_t code_found_hi = instance->common.code_last_found >> 32;
+    uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
+    instance->common.btn = (instance->common.code_last_found >> 4) & 0xF;
+
+    string_cat_printf(
+        output,
+        "%s\r\n"
+        "%dbit\r\n"
+        "Key:0x%03lX%08lX\r\n"
+        "Btn:0x%01X",
+        instance->common.name,
+        instance->common.code_last_count_bit,
+        code_found_hi,
+        code_found_lo,
+        instance->common.btn);
+}
+
+void subghz_protocol_hormann_to_save_str(SubGhzProtocolHormann* instance, string_t output) {
+    string_printf(
+        output,
+        "Protocol: %s\n"
+        "Bit: %d\n"
+        "Key: %08lX%08lX\n",
+        instance->common.name,
+        instance->common.code_last_count_bit,
+        (uint32_t)(instance->common.code_last_found >> 32),
+        (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
+}
+
+bool subghz_protocol_hormann_to_load_protocol_from_file(
+    FileWorker* file_worker,
+    SubGhzProtocolHormann* instance,
+    const char* file_path) {
+    bool loaded = false;
+    string_t temp_str;
+    string_init(temp_str);
+    int res = 0;
+    int data = 0;
+
+    do {
+        // Read and parse bit data from 2nd line
+        if(!file_worker_read_until(file_worker, temp_str, '\n')) {
+            break;
+        }
+        res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
+        if(res != 1) {
+            break;
+        }
+        instance->common.code_last_count_bit = (uint8_t)data;
+
+        // Read and parse key data from 3nd line
+        if(!file_worker_read_until(file_worker, temp_str, '\n')) {
+            break;
+        }
+        // strlen("Key: ") = 5
+        string_right(temp_str, 5);
+
+        uint8_t buf_key[8] = {0};
+        if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) {
+            break;
+        }
+
+        for(uint8_t i = 0; i < 8; i++) {
+            instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i];
+        }
+
+        loaded = true;
+    } while(0);
+
+    string_clear(temp_str);
+
+    return loaded;
+}
+
+void subghz_decoder_hormann_to_load_protocol(SubGhzProtocolHormann* instance, void* context) {
+    furi_assert(context);
+    furi_assert(instance);
+    SubGhzProtocolCommonLoad* data = context;
+    instance->common.code_last_found = data->code_found;
+    instance->common.code_last_count_bit = data->code_count_bit;
+}

+ 72 - 0
lib/subghz/protocols/subghz_protocol_hormann.h

@@ -0,0 +1,72 @@
+#pragma once
+
+#include "subghz_protocol_common.h"
+
+typedef struct SubGhzProtocolHormann SubGhzProtocolHormann;
+
+/** Allocate SubGhzProtocolHormann
+ * 
+ * @return SubGhzProtocolHormann* 
+ */
+SubGhzProtocolHormann* subghz_protocol_hormann_alloc();
+
+/** Free SubGhzProtocolHormann
+ * 
+ * @param instance 
+ */
+void subghz_protocol_hormann_free(SubGhzProtocolHormann* instance);
+
+/** Get upload protocol
+ * 
+ * @param instance - SubGhzProtocolHormann instance
+ * @param encoder - SubGhzProtocolCommonEncoder encoder
+ * @return bool
+ */
+bool subghz_protocol_hormann_send_key(
+    SubGhzProtocolHormann* instance,
+    SubGhzProtocolCommonEncoder* encoder);
+
+/** Reset internal state
+ * @param instance - SubGhzProtocolHormann instance
+ */
+void subghz_protocol_hormann_reset(SubGhzProtocolHormann* instance);
+
+/** Parse accepted duration
+ * 
+ * @param instance - SubGhzProtocolHormann instance
+ * @param data - LevelDuration level_duration
+ */
+void subghz_protocol_hormann_parse(SubGhzProtocolHormann* instance, bool level, uint32_t duration);
+
+/** Outputting information from the parser
+ * 
+ * @param instance - SubGhzProtocolHormann* instance
+ * @param output   - output string
+ */
+void subghz_protocol_hormann_to_str(SubGhzProtocolHormann* instance, string_t output);
+
+/** Get a string to save the protocol
+ * 
+ * @param instance  - SubGhzProtocolHormann instance
+ * @param output    - the resulting string
+ */
+void subghz_protocol_hormann_to_save_str(SubGhzProtocolHormann* instance, string_t output);
+
+/** Loading protocol from file
+ * 
+ * @param file_worker - FileWorker file_worker
+ * @param instance - SubGhzProtocolHormann instance
+ * @param file_path - file path
+ * @return bool
+ */
+bool subghz_protocol_hormann_to_load_protocol_from_file(
+    FileWorker* file_worker,
+    SubGhzProtocolHormann* instance,
+    const char* file_path);
+
+/** Loading protocol from bin data
+ * 
+ * @param instance - SubGhzProtocolHormann instance
+ * @param context - SubGhzProtocolCommonLoad context
+ */
+void subghz_decoder_hormann_to_load_protocol(SubGhzProtocolHormann* instance, void* context);

+ 10 - 0
lib/subghz/subghz_parser.c

@@ -17,6 +17,7 @@
 #include "protocols/subghz_protocol_scher_khan.h"
 #include "protocols/subghz_protocol_kia.h"
 #include "protocols/subghz_protocol_raw.h"
+#include "protocols/subghz_protocol_hormann.h"
 
 #include "subghz_keystore.h"
 
@@ -40,6 +41,7 @@ typedef enum {
     SubGhzProtocolTypeScherKhan,
     SubGhzProtocolTypeKIA,
     SubGhzProtocolTypeRAW,
+    SubGhzProtocolTypeHormann,
 
     SubGhzProtocolTypeMax,
 } SubGhzProtocolType;
@@ -113,6 +115,8 @@ SubGhzParser* subghz_parser_alloc() {
         (SubGhzProtocolCommon*)subghz_protocol_kia_alloc();
     instance->protocols[SubGhzProtocolTypeRAW] =
         (SubGhzProtocolCommon*)subghz_protocol_raw_alloc();
+    instance->protocols[SubGhzProtocolTypeHormann] =
+        (SubGhzProtocolCommon*)subghz_protocol_hormann_alloc();
 
     return instance;
 }
@@ -148,6 +152,8 @@ void subghz_parser_free(SubGhzParser* instance) {
         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]);
     subghz_protocol_kia_free((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]);
     subghz_protocol_raw_free((SubGhzProtocolRAW*)instance->protocols[SubGhzProtocolTypeRAW]);
+    subghz_protocol_hormann_free(
+        (SubGhzProtocolHormann*)instance->protocols[SubGhzProtocolTypeHormann]);
 
     subghz_keystore_free(instance->keystore);
 
@@ -240,6 +246,8 @@ void subghz_parser_reset(SubGhzParser* instance) {
         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]);
     subghz_protocol_kia_reset((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]);
     subghz_protocol_raw_reset((SubGhzProtocolRAW*)instance->protocols[SubGhzProtocolTypeRAW]);
+    subghz_protocol_hormann_reset(
+        (SubGhzProtocolHormann*)instance->protocols[SubGhzProtocolTypeHormann]);
 }
 
 void subghz_parser_raw_parse(SubGhzParser* instance, bool level, uint32_t duration) {
@@ -290,4 +298,6 @@ void subghz_parser_parse(SubGhzParser* instance, bool level, uint32_t duration)
         duration);
     subghz_protocol_kia_parse(
         (SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA], level, duration);
+    subghz_protocol_hormann_parse(
+        (SubGhzProtocolHormann*)instance->protocols[SubGhzProtocolTypeHormann], level, duration);
 }