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

SubGhz: add protocol PowerSmart / SolarSmart Roller Shutters (#1335)

* SubGhz: add protocol Power Smart
* SubGhz: parsing protocol Power Smart
* SubGhz: add parsing cannel
* SubGhz: add unit test
* SubGhz: update files unit test_random_raw

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

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

@@ -13,7 +13,7 @@
 #define CAME_ATOMO_DIR_NAME "/ext/subghz/assets/came_atomo"
 #define NICE_FLOR_S_DIR_NAME "/ext/subghz/assets/nice_flor_s"
 #define TEST_RANDOM_DIR_NAME "/ext/unit_tests/subghz/test_random_raw.sub"
-#define TEST_RANDOM_COUNT_PARSE 113
+#define TEST_RANDOM_COUNT_PARSE 119
 #define TEST_TIMEOUT 10000
 
 static SubGhzEnvironment* environment_handler;
@@ -361,6 +361,13 @@ MU_TEST(subghz_decoder_holtek_test) {
         "Test decoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n");
 }
 
+MU_TEST(subghz_decoder_power_smart_test) {
+    mu_assert(
+        subghz_decoder_test(
+            "/ext/unit_tests/subghz/power_smart_raw.sub", SUBGHZ_PROTOCOL_POWER_SMART_NAME),
+        "Test decoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n");
+}
+
 //test encoders
 MU_TEST(subghz_encoder_princeton_test) {
     mu_assert(
@@ -428,6 +435,12 @@ MU_TEST(subghz_encoder_secplus_v2_test) {
         "Test encoder " SUBGHZ_PROTOCOL_SECPLUS_V2_NAME " error\r\n");
 }
 
+MU_TEST(subghz_encoder_power_smart_test) {
+    mu_assert(
+        subghz_encoder_test("/ext/unit_tests/subghz/power_smart.sub"),
+        "Test encoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n");
+}
+
 MU_TEST(subghz_random_test) {
     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
 }
@@ -459,6 +472,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_decoder_secplus_v1_test);
     MU_RUN_TEST(subghz_decoder_secplus_v2_test);
     MU_RUN_TEST(subghz_decoder_holtek_test);
+    MU_RUN_TEST(subghz_decoder_power_smart_test);
 
     MU_RUN_TEST(subghz_encoder_princeton_test);
     MU_RUN_TEST(subghz_encoder_came_test);
@@ -471,6 +485,7 @@ MU_TEST_SUITE(subghz) {
     MU_RUN_TEST(subghz_encoder_holtek_test);
     MU_RUN_TEST(subghz_encoder_secplus_v1_test);
     MU_RUN_TEST(subghz_encoder_secplus_v2_test);
+    MU_RUN_TEST(subghz_encoder_power_smart_test);
 
     MU_RUN_TEST(subghz_random_test);
     subghz_test_deinit();

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

@@ -0,0 +1,7 @@
+Filetype: Flipper SubGhz Key File
+Version: 1
+Frequency: 433420000
+Preset: FuriHalSubGhzPresetOok650Async
+Protocol: Power Smart
+Bit: 64
+Key: FD C1 36 AC AA 3E C9 52

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


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


+ 380 - 0
lib/subghz/protocols/power_smart.c

@@ -0,0 +1,380 @@
+#include "power_smart.h"
+#include <lib/toolbox/manchester_decoder.h>
+#include <lib/toolbox/manchester_encoder.h>
+#include "../blocks/const.h"
+#include "../blocks/decoder.h"
+#include "../blocks/encoder.h"
+#include "../blocks/generic.h"
+#include "../blocks/math.h"
+
+#define TAG "SubGhzProtocolPowerSmart"
+#define POWER_SMART_PACKET_HEADER 0xFD000000AA000000
+#define POWER_SMART_PACKET_HEADER_MASK 0xFF000000FF000000
+
+#define CHANNEL_PATTERN "%c%c%c%c%c%c"
+#define CNT_TO_CHANNEL(dip)                                                             \
+    (dip & 0x0001 ? '*' : '-'), (dip & 0x0002 ? '*' : '-'), (dip & 0x0004 ? '*' : '-'), \
+        (dip & 0x0008 ? '*' : '-'), (dip & 0x0010 ? '*' : '-'), (dip & 0x0020 ? '*' : '-')
+
+static const SubGhzBlockConst subghz_protocol_power_smart_const = {
+    .te_short = 225,
+    .te_long = 450,
+    .te_delta = 100,
+    .min_count_bit_for_found = 64,
+};
+
+struct SubGhzProtocolDecoderPowerSmart {
+    SubGhzProtocolDecoderBase base;
+
+    SubGhzBlockDecoder decoder;
+    SubGhzBlockGeneric generic;
+    ManchesterState manchester_saved_state;
+    uint16_t header_count;
+};
+
+struct SubGhzProtocolEncoderPowerSmart {
+    SubGhzProtocolEncoderBase base;
+
+    SubGhzProtocolBlockEncoder encoder;
+    SubGhzBlockGeneric generic;
+};
+
+typedef enum {
+    PowerSmartDecoderStepReset = 0,
+    PowerSmartDecoderFoundHeader,
+    PowerSmartDecoderStepDecoderData,
+} PowerSmartDecoderStep;
+
+const SubGhzProtocolDecoder subghz_protocol_power_smart_decoder = {
+    .alloc = subghz_protocol_decoder_power_smart_alloc,
+    .free = subghz_protocol_decoder_power_smart_free,
+
+    .feed = subghz_protocol_decoder_power_smart_feed,
+    .reset = subghz_protocol_decoder_power_smart_reset,
+
+    .get_hash_data = subghz_protocol_decoder_power_smart_get_hash_data,
+    .serialize = subghz_protocol_decoder_power_smart_serialize,
+    .deserialize = subghz_protocol_decoder_power_smart_deserialize,
+    .get_string = subghz_protocol_decoder_power_smart_get_string,
+};
+
+const SubGhzProtocolEncoder subghz_protocol_power_smart_encoder = {
+    .alloc = subghz_protocol_encoder_power_smart_alloc,
+    .free = subghz_protocol_encoder_power_smart_free,
+
+    .deserialize = subghz_protocol_encoder_power_smart_deserialize,
+    .stop = subghz_protocol_encoder_power_smart_stop,
+    .yield = subghz_protocol_encoder_power_smart_yield,
+};
+
+const SubGhzProtocol subghz_protocol_power_smart = {
+    .name = SUBGHZ_PROTOCOL_POWER_SMART_NAME,
+    .type = SubGhzProtocolTypeStatic,
+    .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
+            SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
+
+    .decoder = &subghz_protocol_power_smart_decoder,
+    .encoder = &subghz_protocol_power_smart_encoder,
+};
+
+void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolEncoderPowerSmart* instance = malloc(sizeof(SubGhzProtocolEncoderPowerSmart));
+
+    instance->base.protocol = &subghz_protocol_power_smart;
+    instance->generic.protocol_name = instance->base.protocol->name;
+
+    instance->encoder.repeat = 10;
+    instance->encoder.size_upload = 1024;
+    instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
+    instance->encoder.is_runing = false;
+    return instance;
+}
+
+void subghz_protocol_encoder_power_smart_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolEncoderPowerSmart* instance = context;
+    free(instance->encoder.upload);
+    free(instance);
+}
+
+static LevelDuration
+    subghz_protocol_encoder_power_smart_add_duration_to_upload(ManchesterEncoderResult result) {
+    LevelDuration data = {.duration = 0, .level = 0};
+    switch(result) {
+    case ManchesterEncoderResultShortLow:
+        data.duration = subghz_protocol_power_smart_const.te_short;
+        data.level = false;
+        break;
+    case ManchesterEncoderResultLongLow:
+        data.duration = subghz_protocol_power_smart_const.te_long;
+        data.level = false;
+        break;
+    case ManchesterEncoderResultLongHigh:
+        data.duration = subghz_protocol_power_smart_const.te_long;
+        data.level = true;
+        break;
+    case ManchesterEncoderResultShortHigh:
+        data.duration = subghz_protocol_power_smart_const.te_short;
+        data.level = true;
+        break;
+
+    default:
+        furi_crash("SubGhz: ManchesterEncoderResult is incorrect.");
+        break;
+    }
+    return level_duration_make(data.level, data.duration);
+}
+
+/**
+ * Generating an upload from data.
+ * @param instance Pointer to a SubGhzProtocolEncoderPowerSmart instance
+ */
+static void
+    subghz_protocol_encoder_power_smart_get_upload(SubGhzProtocolEncoderPowerSmart* instance) {
+    furi_assert(instance);
+    size_t index = 0;
+
+    ManchesterEncoderState enc_state;
+    manchester_encoder_reset(&enc_state);
+    ManchesterEncoderResult result;
+
+    for(int i = 8; i > 0; i--) {
+        for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
+            if(!manchester_encoder_advance(
+                   &enc_state, !bit_read(instance->generic.data, i - 1), &result)) {
+                instance->encoder.upload[index++] =
+                    subghz_protocol_encoder_power_smart_add_duration_to_upload(result);
+                manchester_encoder_advance(
+                    &enc_state, !bit_read(instance->generic.data, i - 1), &result);
+            }
+            instance->encoder.upload[index++] =
+                subghz_protocol_encoder_power_smart_add_duration_to_upload(result);
+        }
+    }
+    instance->encoder.upload[index] = subghz_protocol_encoder_power_smart_add_duration_to_upload(
+        manchester_encoder_finish(&enc_state));
+    if(level_duration_get_level(instance->encoder.upload[index])) {
+        index++;
+    }
+    instance->encoder.upload[index++] =
+        level_duration_make(false, (uint32_t)subghz_protocol_power_smart_const.te_long * 1111);
+    instance->encoder.size_upload = index;
+}
+
+/** 
+ * Analysis of received data
+ * @param instance Pointer to a SubGhzBlockGeneric* instance
+ */
+static void subghz_protocol_power_smart_remote_controller(SubGhzBlockGeneric* instance) {
+    /*
+    * Protocol: Manchester encoding, symbol rate ~2222.
+    * Packet Format: 
+    *       0xFDXXXXYYAAZZZZWW where 0xFD and 0xAA sync word
+    *                           XXXX = ~ZZZZ, YY=(~WW)-1 
+    * Example:
+    *                               SYNC1 K1 CHANNEL DATA1   K2 DATA2    SYNC2  ~K1 ~CHANNEL ~DATA2  ~K2 (~DATA2)-1
+    *       0xFD2137ACAADEC852 => 11111101 0 010000 10011011 1 10101100 10101010  1  1011110 1100100  0  01010010
+    *       0xFDA137ACAA5EC852 => 11111101 1 010000 10011011 1 10101100 10101010  0  1011110 1100100  0  01010010
+    *       0xFDA136ACAA5EC952 => 11111101 1 010000 10011011 0 10101100 10101010  0  1011110 1100100  1  01010010
+    * 
+    * Key:
+    *       K1K2
+    *        0 0 - key_unknown
+    *        0 1 - key_down
+    *        1 0 - key_up
+    *        1 1 - key_stop
+    *        
+    */
+
+    instance->btn = ((instance->data >> 54) & 0x02) | ((instance->data >> 40) & 0x1);
+    instance->serial = ((instance->data >> 33) & 0x3FFF00) | ((instance->data >> 32) & 0xFF);
+    instance->cnt = ((instance->data >> 49) & 0x3F);
+}
+
+bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolEncoderPowerSmart* instance = context;
+    bool res = false;
+    do {
+        if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
+            FURI_LOG_E(TAG, "Deserialize error");
+            break;
+        }
+
+        //optional parameter parameter
+        flipper_format_read_uint32(
+            flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
+
+        subghz_protocol_power_smart_remote_controller(&instance->generic);
+        subghz_protocol_encoder_power_smart_get_upload(instance);
+        instance->encoder.is_runing = true;
+
+        res = true;
+    } while(false);
+
+    return res;
+}
+
+void subghz_protocol_encoder_power_smart_stop(void* context) {
+    SubGhzProtocolEncoderPowerSmart* instance = context;
+    instance->encoder.is_runing = false;
+}
+
+LevelDuration subghz_protocol_encoder_power_smart_yield(void* context) {
+    SubGhzProtocolEncoderPowerSmart* 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_power_smart_alloc(SubGhzEnvironment* environment) {
+    UNUSED(environment);
+    SubGhzProtocolDecoderPowerSmart* instance = malloc(sizeof(SubGhzProtocolDecoderPowerSmart));
+    instance->base.protocol = &subghz_protocol_power_smart;
+    instance->generic.protocol_name = instance->base.protocol->name;
+    return instance;
+}
+
+void subghz_protocol_decoder_power_smart_free(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    free(instance);
+}
+
+void subghz_protocol_decoder_power_smart_reset(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    manchester_advance(
+        instance->manchester_saved_state,
+        ManchesterEventReset,
+        &instance->manchester_saved_state,
+        NULL);
+}
+
+bool subghz_protocol_power_smart_chek_valid(uint64_t packet) {
+    uint32_t data_1 = (uint32_t)((packet >> 40) & 0xFFFF);
+    uint32_t data_2 = (uint32_t)((~packet >> 8) & 0xFFFF);
+    uint8_t data_3 = (uint8_t)(packet >> 32) & 0xFF;
+    uint8_t data_4 = (uint8_t)(((~packet) & 0xFF) - 1);
+    return (data_1 == data_2) && (data_3 == data_4);
+}
+
+void subghz_protocol_decoder_power_smart_feed(
+    void* context,
+    bool level,
+    volatile uint32_t duration) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    ManchesterEvent event = ManchesterEventReset;
+    if(!level) {
+        if(DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_short) <
+           subghz_protocol_power_smart_const.te_delta) {
+            event = ManchesterEventShortLow;
+        } else if(
+            DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_long) <
+            subghz_protocol_power_smart_const.te_delta * 2) {
+            event = ManchesterEventLongLow;
+        }
+    } else {
+        if(DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_short) <
+           subghz_protocol_power_smart_const.te_delta) {
+            event = ManchesterEventShortHigh;
+        } else if(
+            DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_long) <
+            subghz_protocol_power_smart_const.te_delta * 2) {
+            event = ManchesterEventLongHigh;
+        }
+    }
+    if(event != ManchesterEventReset) {
+        bool data;
+        bool data_ok = manchester_advance(
+            instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
+
+        if(data_ok) {
+            instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
+        }
+        if((instance->decoder.decode_data & POWER_SMART_PACKET_HEADER_MASK) ==
+           POWER_SMART_PACKET_HEADER) {
+            if(subghz_protocol_power_smart_chek_valid(instance->decoder.decode_data)) {
+                instance->decoder.decode_data = instance->decoder.decode_data;
+                instance->generic.data = instance->decoder.decode_data;
+                instance->generic.data_count_bit =
+                    subghz_protocol_power_smart_const.min_count_bit_for_found;
+                if(instance->base.callback)
+                    instance->base.callback(&instance->base, instance->base.context);
+                instance->decoder.decode_data = 0;
+                instance->decoder.decode_count_bit = 0;
+            }
+        }
+    } else {
+        instance->decoder.decode_data = 0;
+        instance->decoder.decode_count_bit = 0;
+        manchester_advance(
+            instance->manchester_saved_state,
+            ManchesterEventReset,
+            &instance->manchester_saved_state,
+            NULL);
+    }
+}
+
+static const char* subghz_protocol_power_smart_get_name_button(uint8_t btn) {
+    btn &= 0x3;
+    const char* name_btn[0x4] = {"Unknown", "Down", "Up", "Stop"};
+    return name_btn[btn];
+}
+
+uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    return subghz_protocol_blocks_get_hash_data(
+        &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
+}
+
+bool subghz_protocol_decoder_power_smart_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    uint32_t frequency,
+    FuriHalSubGhzPreset preset) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+}
+
+bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    return subghz_block_generic_deserialize(&instance->generic, flipper_format);
+}
+
+void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output) {
+    furi_assert(context);
+    SubGhzProtocolDecoderPowerSmart* instance = context;
+    subghz_protocol_power_smart_remote_controller(&instance->generic);
+
+    string_cat_printf(
+        output,
+        "%s %db\r\n"
+        "Key:0x%lX%08lX\r\n"
+        "Sn:0x%07lX \r\n"
+        "Btn:%s\r\n"
+        "Channel:" CHANNEL_PATTERN "\r\n",
+        instance->generic.protocol_name,
+        instance->generic.data_count_bit,
+        (uint32_t)(instance->generic.data >> 32),
+        (uint32_t)(instance->generic.data & 0xFFFFFFFF),
+        instance->generic.serial,
+        subghz_protocol_power_smart_get_name_button(instance->generic.btn),
+        CNT_TO_CHANNEL(instance->generic.cnt));
+}

+ 109 - 0
lib/subghz/protocols/power_smart.h

@@ -0,0 +1,109 @@
+#pragma once
+
+#include "base.h"
+
+#define SUBGHZ_PROTOCOL_POWER_SMART_NAME "Power Smart"
+
+typedef struct SubGhzProtocolDecoderPowerSmart SubGhzProtocolDecoderPowerSmart;
+typedef struct SubGhzProtocolEncoderPowerSmart SubGhzProtocolEncoderPowerSmart;
+
+extern const SubGhzProtocolDecoder subghz_protocol_power_smart_decoder;
+extern const SubGhzProtocolEncoder subghz_protocol_power_smart_encoder;
+extern const SubGhzProtocol subghz_protocol_power_smart;
+
+/**
+ * Allocate SubGhzProtocolEncoderPowerSmart.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolEncoderPowerSmart* pointer to a SubGhzProtocolEncoderPowerSmart instance
+ */
+void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolEncoderPowerSmart.
+ * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance
+ */
+void subghz_protocol_encoder_power_smart_free(void* context);
+
+/**
+ * Deserialize and generating an upload to send.
+ * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format);
+
+/**
+ * Forced transmission stop.
+ * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance
+ */
+void subghz_protocol_encoder_power_smart_stop(void* context);
+
+/**
+ * Getting the level and duration of the upload to be loaded into DMA.
+ * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance
+ * @return LevelDuration 
+ */
+LevelDuration subghz_protocol_encoder_power_smart_yield(void* context);
+
+/**
+ * Allocate SubGhzProtocolDecoderPowerSmart.
+ * @param environment Pointer to a SubGhzEnvironment instance
+ * @return SubGhzProtocolDecoderPowerSmart* pointer to a SubGhzProtocolDecoderPowerSmart instance
+ */
+void* subghz_protocol_decoder_power_smart_alloc(SubGhzEnvironment* environment);
+
+/**
+ * Free SubGhzProtocolDecoderPowerSmart.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ */
+void subghz_protocol_decoder_power_smart_free(void* context);
+
+/**
+ * Reset decoder SubGhzProtocolDecoderPowerSmart.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ */
+void subghz_protocol_decoder_power_smart_reset(void* context);
+
+/**
+ * Parse a raw sequence of levels and durations received from the air.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ * @param level Signal level true-high false-low
+ * @param duration Duration of this level in, us
+ */
+void subghz_protocol_decoder_power_smart_feed(void* context, bool level, uint32_t duration);
+
+/**
+ * Getting the hash sum of the last randomly received parcel.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ * @return hash Hash sum
+ */
+uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context);
+
+/**
+ * Serialize data SubGhzProtocolDecoderPowerSmart.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @param frequency The frequency at which the signal was received, Hz
+ * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @return true On success
+ */
+bool subghz_protocol_decoder_power_smart_serialize(
+    void* context,
+    FlipperFormat* flipper_format,
+    uint32_t frequency,
+    FuriHalSubGhzPreset preset);
+
+/**
+ * Deserialize data SubGhzProtocolDecoderPowerSmart.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ * @param flipper_format Pointer to a FlipperFormat instance
+ * @return true On success
+ */
+bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format);
+
+/**
+ * Getting a textual representation of the received data.
+ * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
+ * @param output Resulting text
+ */
+void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output);

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

@@ -1,15 +1,15 @@
 #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_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,
 
 };
 

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

@@ -27,6 +27,7 @@
 #include "megacode.h"
 #include "holtek.h"
 #include "chamberlain_code.h"
+#include "power_smart.h"
 
 /**
  * Registration by name SubGhzProtocol.

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