SubghzD rework (#2210)

* Removed controller code

* Add Legrand

* Added Somify Keytis

* Somify

* better display
This commit is contained in:
Totoo
2024-07-29 07:47:50 +02:00
committed by GitHub
parent 9211975868
commit 765e3be55b
37 changed files with 1008 additions and 275 deletions

View File

@@ -53,8 +53,6 @@ class FProtoSubGhzDCame : public FProtoSubGhzDBase {
parser_step = CameDecoderStepFoundStartBit;
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == AIRFORCE_COUNT_BIT) ||
(decode_count_bit == PRASTEL_COUNT_BIT) || (decode_count_bit == CAME_24_COUNT_BIT)) {
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
data = decode_data;
data_count_bit = decode_count_bit;
// if flippa hacky, i hacky

View File

@@ -45,36 +45,6 @@ class FProtoSubGhzDCameAtomo : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
data ^= 0xFFFFFFFFFFFFFFFF;
data <<= 4;
uint8_t pack[8] = {};
pack[0] = (data >> 56);
pack[1] = ((data >> 48) & 0xFF);
pack[2] = ((data >> 40) & 0xFF);
pack[3] = ((data >> 32) & 0xFF);
pack[4] = ((data >> 24) & 0xFF);
pack[5] = ((data >> 16) & 0xFF);
pack[6] = ((data >> 8) & 0xFF);
pack[7] = (data & 0xFF);
atomo_decrypt(pack);
cnt = (uint16_t)pack[1] << 8 | pack[2];
serial = (uint32_t)(pack[3]) << 24 | pack[4] << 16 | pack[5] << 8 | pack[6];
uint8_t btn_decode = (pack[7] >> 4);
if (btn_decode == 0x0) {
btn = 0x1;
} else if (btn_decode == 0x2) {
btn = 0x2;
} else if (btn_decode == 0x4) {
btn = 0x3;
} else if (btn_decode == 0x6) {
btn = 0x4;
}
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -45,7 +45,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
subghz_protocol_came_twee_remote_controller();
if (callback) callback(this);
}
decode_data = 0;
@@ -79,69 +78,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
protected:
ManchesterState manchester_saved_state = ManchesterStateMid1;
void subghz_protocol_came_twee_remote_controller() {
/* Came Twee 54 bit, rolling code 15 parcels with
* a decreasing counter from 0xE to 0x0
* with originally coded dip switches on the console 10 bit code
*
* 0x003FFF72E04A6FEE
* 0x003FFF72D17B5EDD
* 0x003FFF72C2684DCC
* 0x003FFF72B3193CBB
* 0x003FFF72A40E2BAA
* 0x003FFF72953F1A99
* 0x003FFF72862C0988
* 0x003FFF7277DDF877
* 0x003FFF7268C2E766
* 0x003FFF7259F3D655
* 0x003FFF724AE0C544
* 0x003FFF723B91B433
* 0x003FFF722C86A322
* 0x003FFF721DB79211
* 0x003FFF720EA48100
*
* decryption
* the last 32 bits, do XOR by the desired number, divide the result by 4,
* convert the first 16 bits of the resulting 32-bit number to bin and do
* bit-by-bit mirroring, adding up to 10 bits
*
* Example
* Step 1. 0x003FFF721DB79211 => 0x1DB79211
* Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
* Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
* Step 5. 0x002AA3C0 => 0x002A
* Step 6. 0x002A bin => b101010
* Step 7. b101010 => b0101010000
* Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
*/
uint8_t cnt_parcel = (uint8_t)(data & 0xF);
serial = (uint32_t)(data & 0x0FFFFFFFF);
data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
data /= 4;
btn = (data >> 4) & 0x0F;
data >>= 16;
data = (uint16_t)FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 16);
cnt = data >> 6;
}
inline static const uint32_t came_twee_magic_numbers_xor[15] = {
0x0E0E0E00,
0x1D1D1D11,
0x2C2C2C22,
0x3B3B3B33,
0x4A4A4A44,
0x59595955,
0x68686866,
0x77777777,
0x86868688,
0x95959599,
0xA4A4A4AA,
0xB3B3B3BB,
0xC2C2C2CC,
0xD1D1D1DD,
0xE0E0E0EE,
};
};
#endif

View File

@@ -57,8 +57,6 @@ class FProtoSubGhzDChambCode : public FProtoSubGhzDBase {
if (!level) { // save interval
if (duration > te_short * 5) {
if (decode_count_bit >= min_count_bit_for_found) {
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
if (subghz_protocol_decoder_chamb_code_check_mask_and_parse()) {
data = decode_data;
data_count_bit = decode_count_bit;

View File

@@ -64,11 +64,6 @@ class FProtoSubGhzDClemsa : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
serial = (data >> 2) & 0xFFFF;
btn = (data & 0x03);
if (callback) callback(this);
}
parser_step = ClemsaDecoderStepSaveDuration;

View File

@@ -46,10 +46,6 @@ class FProtoSubGhzDDoitrand : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
cnt = (data >> 24) | ((data >> 15) & 0x1);
btn = ((data >> 18) & 0x3);
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -74,16 +74,6 @@ class FProtoSubGhzDDooya : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller:
serial = (data >> 16);
if ((data >> 12) & 0x0F) {
cnt = (data >> 8) & 0x0F;
} else {
cnt = 0xFF;
}
btn = data & 0xFF;
if (callback) callback(this);
}
break;

View File

@@ -46,12 +46,6 @@ class FProtoSubGhzDGateTx : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
uint32_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
serial = (code_found_reverse & 0xFF) << 12 | ((code_found_reverse >> 8) & 0xFF) << 4 | ((code_found_reverse >> 20) & 0x0F);
btn = ((code_found_reverse >> 16) & 0x0F);
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -51,22 +51,6 @@ class FProtoSubGhzDHoltek : public FProtoSubGhzDBase {
if ((decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
serial = FProtoGeneral::subghz_protocol_blocks_reverse_key((data >> 16) & 0xFFFFF, 20);
uint16_t btn = data & 0xFFFF;
if ((btn & 0xf) != 0xA) {
btn = 0x1 << 4 | (btn & 0xF);
} else if (((btn >> 4) & 0xF) != 0xA) {
btn = 0x2 << 4 | ((btn >> 4) & 0xF);
} else if (((btn >> 8) & 0xF) != 0xA) {
btn = 0x3 << 4 | ((btn >> 8) & 0xF);
} else if (((btn >> 12) & 0xF) != 0xA) {
btn = 0x4 << 4 | ((btn >> 12) & 0xF);
} else {
btn = 0;
}
if (callback) callback(this);
}
}

View File

@@ -47,9 +47,6 @@ class FProtoSubGhzDHoltekHt12x : public FProtoSubGhzDBase {
if (data != decode_data) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
btn = data & 0x0F;
cnt = (data >> 4) & 0xFF;
if (callback) callback(this);
}
}

View File

@@ -73,8 +73,6 @@ class FProtoSubGhzDHoneywell : public FProtoSubGhzDBase {
// the data is good. process it.
data = decode_data;
data_count_bit = decode_count_bit; // maybe set it to 64, and hack the first 2 bits to 1! will see if replay needs it
serial = (decode_data >> 24) & 0xFFFFF;
btn = (decode_data >> 16) & 0xFF; // not exactly button, but can contain btn data too.
if (callback) callback(this);
decode_data = 0;
decode_count_bit = 0;

View File

@@ -49,8 +49,6 @@ class FProtoSubGhzDHormann : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
btn = (data >> 4) & 0xF;
if (callback) callback(this);
}
break;

View File

@@ -0,0 +1,130 @@
#ifndef __FPROTO_HORMANNBISECURE_H__
#define __FPROTO_HORMANNBISECURE_H__
#include "subghzdbase.hpp"
typedef enum {
HormannBiSecurDecoderStepReset = 0,
HormannBiSecurDecoderStepFoundPreambleAlternatingShort,
HormannBiSecurDecoderStepFoundPreambleHighVeryLong,
HormannBiSecurDecoderStepFoundPreambleAlternatingLong,
HormannBiSecurDecoderStepFoundData,
} HormannBiSecurDecoderStep;
class FProtoSubGhzDHormannBiSecure : public FProtoSubGhzDBase {
public:
FProtoSubGhzDHormannBiSecure() {
sensorType = FPS_HORMANN;
te_short = 208;
te_long = 416;
te_delta = 104;
min_count_bit_for_found = 176;
}
void subghz_protocol_decoder_hormann_bisecur_reset() {
parser_step = HormannBiSecurDecoderStepReset;
data = 0;
for (uint8_t i = 0; i < 22; ++i) dataa[i] = 0;
data_count_bit = 0;
manchester_saved_state = ManchesterStateStart1;
}
void feed(bool level, uint32_t duration) {
ManchesterEvent event = ManchesterEventReset;
switch (parser_step) {
case HormannBiSecurDecoderStepReset:
if (!level && DURATION_DIFF(duration, duration_short + duration_half_short) < te_delta) {
parser_step = HormannBiSecurDecoderStepFoundPreambleAlternatingShort;
}
break;
case HormannBiSecurDecoderStepFoundPreambleAlternatingShort:
if (DURATION_DIFF(duration, duration_short) < te_delta) {
// stay on the same step, the pattern repeats around 21 times
break;
}
if (level && DURATION_DIFF(duration, duration_long * 4) < te_delta) {
parser_step = HormannBiSecurDecoderStepFoundPreambleHighVeryLong;
break;
}
parser_step = HormannBiSecurDecoderStepReset;
break;
case HormannBiSecurDecoderStepFoundPreambleHighVeryLong:
if (!level && DURATION_DIFF(duration, duration_long) < te_delta) {
sync_cnt = 3;
parser_step = HormannBiSecurDecoderStepFoundPreambleAlternatingLong;
break;
}
parser_step = HormannBiSecurDecoderStepReset;
break;
case HormannBiSecurDecoderStepFoundPreambleAlternatingLong:
if (level == (sync_cnt-- & 1) &&
DURATION_DIFF(duration, duration_long) < te_delta) {
if (!sync_cnt) {
FProtoGeneral::manchester_advance_alt(manchester_saved_state, event, &manchester_saved_state, NULL);
parser_step = HormannBiSecurDecoderStepFoundData;
}
// stay on the same step, or advance to the next if enough transitions are found
break;
}
parser_step = HormannBiSecurDecoderStepReset;
break;
case HormannBiSecurDecoderStepFoundData:
if (DURATION_DIFF(duration, duration_short) < te_delta ||
(
// the last bit can be arbitrary long, but it is parsed as a short
data_count_bit == min_count_bit_for_found - 1 &&
duration > duration_short)) {
event = !level ? ManchesterEventShortHigh : ManchesterEventShortLow;
}
if (DURATION_DIFF(duration, duration_long) < te_delta) {
event = !level ? ManchesterEventLongHigh : ManchesterEventLongLow;
}
if (event == ManchesterEventReset) {
subghz_protocol_decoder_hormann_bisecur_reset();
} else {
bool new_level;
if (manchester_advance_alt(instance->manchester_saved_state, event, &instance->manchester_saved_state, &new_level)) {
subghz_protocol_decoder_hormann_bisecur_add_bit(instance, new_level);
}
}
break;
}
}
void subghz_protocol_decoder_hormann_bisecur_add_bit(bool level) {
if (data_count_bit >= min_count_bit_for_found) {
return;
}
if (level) {
uint8_t byte_index = data_count_bit / 8;
uint8_t bit_index = data_count_bit % 8;
dataa[byte_index] |= 1 << (7 - bit_index);
}
data_count_bit++;
if (data_count_bit >= min_count_bit_for_found) {
if (callback) {
callback(this);
} else {
subghz_protocol_decoder_hormann_bisecur_reset();
}
}
}
protected:
ManchesterState manchester_saved_state = ManchesterStateMid1;
uint8_t dataa[22] = {0};
uint8_t sync_cnt = 0;
};
#endif

View File

@@ -46,12 +46,6 @@ class FProtoSubGhzDIdo : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
uint64_t code_found_reverse = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
serial = code_fix & 0xFFFFF;
btn = (code_fix >> 20) & 0x0F;
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -68,7 +68,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
(decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
data = decode_data;
data_count_bit = decode_count_bit;
remote_controller();
if (callback) callback(this);
}
break;
@@ -120,29 +119,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
}
protected:
void remote_controller() {
if (data_count_bit == min_count_bit_for_found) {
serial = (data >> 6) & 0x3FFFFFF;
if ((data >> 5) & 0x1) {
cnt = 1 << 5;
} else {
cnt = (~data & 0xF);
}
btn = (data >> 4) & 0x1;
} else if (data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) {
serial = (data >> 10) & 0x3FFFFFF;
if ((data >> 9) & 0x1) {
cnt = 1 << 5;
} else {
cnt = (~(data >> 4) & 0xF);
}
btn = data & 0xF;
} else {
serial = 0;
cnt = 0;
btn = 0;
}
}
};
#endif

View File

@@ -60,12 +60,6 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
if (data != decode_data) {
data = decode_data;
data_count_bit = min_count_bit_for_found;
// controller
uint64_t key = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit);
uint32_t key_fix = key >> 32;
// uint32_t key_hop = key & 0x00000000ffffffff; //unused
serial = key_fix & 0x0FFFFFFF;
btn = key_fix >> 28;
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -61,13 +61,8 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
if (decode_count_bit ==
min_count_bit_for_found) {
data = data_2;
data_2 = decode_data;
data_2 = decode_data; // TODO DATA2
data_count_bit = decode_count_bit;
// controller
uint64_t fix = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 53);
btn = (fix >> 17) & 0x0F;
serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF);
if (callback) callback(this);
}

View File

@@ -0,0 +1,113 @@
#ifndef __FPROTO_LEGRAND_H__
#define __FPROTO_LEGRAND_H__
#include "subghzdbase.hpp"
typedef enum {
LegrandDecoderStepReset = 0,
LegrandDecoderStepFirstBit,
LegrandDecoderStepSaveDuration,
LegrandDecoderStepCheckDuration,
} LegrandDecoderStep;
class FProtoSubGhzDLegrand : public FProtoSubGhzDBase {
public:
FProtoSubGhzDLegrand() {
sensorType = FPS_LEGRAND;
te_short = 375;
te_long = 1125;
te_delta = 150;
min_count_bit_for_found = 18;
}
void feed(bool level, uint32_t duration) {
switch (parser_step) {
case LegrandDecoderStepReset:
if (!level && DURATION_DIFF(duration, te_short * 16) < te_delta * 8) {
parser_step = LegrandDecoderStepFirstBit;
decode_data = 0;
decode_count_bit = 0;
te = 0;
}
break;
case LegrandDecoderStepFirstBit:
if (level) {
if (DURATION_DIFF(duration, te_short) < te_delta) {
subghz_protocol_blocks_add_bit(0);
te += duration * 4; // long low that is part of sync, then short high
}
if (DURATION_DIFF(duration, te_long) < te_delta * 3) {
subghz_protocol_blocks_add_bit(1);
te += duration / 3 * 4; // short low that is part of sync, then long high
}
if (decode_count_bit > 0) {
// advance to the next step if either short or long is found
parser_step = LegrandDecoderStepSaveDuration;
break;
}
}
parser_step = LegrandDecoderStepReset;
break;
case LegrandDecoderStepSaveDuration:
if (!level) {
te_last = duration;
te += duration;
parser_step = LegrandDecoderStepCheckDuration;
break;
}
parser_step = LegrandDecoderStepReset;
break;
case LegrandDecoderStepCheckDuration:
if (level) {
uint8_t found = 0;
if (DURATION_DIFF(te_last, te_long) < te_delta * 3 && DURATION_DIFF(duration, te_short) < te_delta) {
found = 1;
subghz_protocol_blocks_add_bit(0);
}
if (DURATION_DIFF(te_last, te_short) < te_delta && DURATION_DIFF(duration, te_long) < te_delta * 3) {
found = 1;
subghz_protocol_blocks_add_bit(1);
}
if (found) {
te += duration;
if (decode_count_bit <
min_count_bit_for_found) {
parser_step = LegrandDecoderStepSaveDuration;
break;
}
// enough bits for a packet found, save it only if there was a previous packet
// with the same data
if (data && (data != decode_data)) {
te /= decode_count_bit * 4;
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) {
callback(this);
}
}
// fallthrough to reset, the next bit is expected to be a sync
// it also takes care of resetting the decoder state
}
}
parser_step = LegrandDecoderStepReset;
break;
}
}
protected:
uint32_t te = 0;
};
#endif

View File

@@ -54,11 +54,8 @@ class FProtoSubGhzDLinear : public FProtoSubGhzDBase {
subghz_protocol_blocks_add_bit(1);
}
if (decode_count_bit == min_count_bit_for_found) {
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
break;

View File

@@ -50,12 +50,8 @@ class FProtoSubGhzDLinearDelta3 : public FProtoSubGhzDBase {
}
if (decode_count_bit == min_count_bit_for_found) {
if ((data == decode_data) && data) {
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
parser_step = LinearD3DecoderStepSaveDuration;

View File

@@ -92,11 +92,6 @@ class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
subghz_protocol_magellan_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 8, 24);
serial = data_rev & 0xFFFF;
btn = (data_rev >> 16) & 0xFF;
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -45,9 +45,6 @@ class FProtoSubGhzDMarantec : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
btn = (data >> 16) & 0xF;
serial = ((data >> 12) & 0xFFFFFF00) | ((data >> 8) & 0xFF);
if (callback) callback(this);
}
decode_data = 1;

View File

@@ -63,9 +63,7 @@ class FProtoSubGhzDMastercode : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
serial = (data >> 4) & 0xFFFF;
btn = (data >> 2 & 0x03);
if (callback) callback(this);
}
parser_step = MastercodeDecoderStepSaveDuration;

View File

@@ -50,16 +50,7 @@ class FProtoSubGhzDMegacode : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
if ((data >> 23) == 1) {
serial = (data >> 3) & 0xFFFF;
btn = data & 0b111;
cnt = (data >> 19) & 0b1111;
} else {
serial = 0;
btn = 0;
cnt = 0;
}
if (callback) callback(this);
}
break;

View File

@@ -47,9 +47,6 @@ class FProtoSubGhzDNiceflo : public FProtoSubGhzDBase {
if (duration >= (te_short * 4)) {
parser_step = NiceFloDecoderStepFoundStartBit;
if (decode_count_bit >= min_count_bit_for_found) {
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) callback(this);

View File

@@ -58,10 +58,7 @@ class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == NICE_ONE_COUNT_BIT)) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller-
cnt = SD_NO_CNT;
serial = SD_NO_SERIAL;
btn = SD_NO_BTN;
if (callback) callback(this);
}
break;

View File

@@ -47,12 +47,6 @@ class FProtoSubGhzDPhoenixV2 : public FProtoSubGhzDBase {
min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
uint64_t data_rev = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, data_count_bit + 4);
serial = data_rev & 0xFFFFFFFF;
cnt = (data_rev >> 40) & 0xFFFF;
btn = (data_rev >> 32) & 0xF;
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -52,11 +52,6 @@ class FProtoSubGhzDPowerSmart : public FProtoSubGhzDBase {
data = decode_data;
data_count_bit = min_count_bit_for_found;
// controller
btn = ((data >> 54) & 0x02) | ((data >> 40) & 0x1);
serial = ((data >> 33) & 0x3FFF00) | ((data >> 32) & 0xFF);
cnt = ((data >> 49) & 0x3F);
if (callback) callback(this);
decode_data = 0;
decode_count_bit = 0;

View File

@@ -44,9 +44,6 @@ class FProtoSubGhzDPrinceton : public FProtoSubGhzDBase {
if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit;
// controller
serial = data >> 4;
btn = data & 0xF;
if (callback) callback(this);
}
decode_data = 0;

View File

@@ -0,0 +1,129 @@
#ifndef __FPROTO_SOMIFYKEYTIS_H__
#define __FPROTO_SOMIFYKEYTIS_H__
#include "subghzdbase.hpp"
typedef enum {
SomfyKeytisDecoderStepReset = 0,
SomfyKeytisDecoderStepCheckPreambula,
SomfyKeytisDecoderStepFoundPreambula,
SomfyKeytisDecoderStepStartDecode,
SomfyKeytisDecoderStepDecoderData,
} SomfyKeytisDecoderStep;
class FProtoSubGhzDSomifyKeytis : public FProtoSubGhzDBase {
public:
FProtoSubGhzDSomifyKeytis() {
sensorType = FPS_SOMIFY_KEYTIS;
te_short = 640;
te_long = 1280;
te_delta = 250;
min_count_bit_for_found = 80;
}
void feed(bool level, uint32_t duration) {
ManchesterEvent event = ManchesterEventReset;
switch (parser_step) {
case SomfyKeytisDecoderStepReset:
if ((level) && DURATION_DIFF(duration, te_short * 4) < te_delta * 4) {
parser_step = SomfyKeytisDecoderStepFoundPreambula;
header_count++;
}
break;
case SomfyKeytisDecoderStepFoundPreambula:
if ((!level) && (DURATION_DIFF(duration, te_short * 4) < te_delta * 4)) {
parser_step = SomfyKeytisDecoderStepCheckPreambula;
} else {
header_count = 0;
parser_step = SomfyKeytisDecoderStepReset;
}
break;
case SomfyKeytisDecoderStepCheckPreambula:
if (level) {
if (DURATION_DIFF(duration, te_short * 4) < te_delta * 4) {
parser_step = SomfyKeytisDecoderStepFoundPreambula;
header_count++;
} else if (
(header_count > 1) && (DURATION_DIFF(duration, te_short * 7) < te_delta * 4)) {
parser_step = SomfyKeytisDecoderStepDecoderData;
decode_data = 0;
decode_count_bit = 0;
// press_duration_counter = 0;
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
}
}
break;
case SomfyKeytisDecoderStepDecoderData:
if (!level) {
if (DURATION_DIFF(duration, te_short) < te_delta) {
event = ManchesterEventShortLow;
} else if (
DURATION_DIFF(duration, te_long) < te_delta) {
event = ManchesterEventLongLow;
} else if (
duration >= (te_long + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) {
// check crc
uint64_t data_tmp = data ^ (data >> 8);
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_keytis_crc(data_tmp)) {
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
}
decode_data = 0;
decode_count_bit = 0;
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
parser_step = SomfyKeytisDecoderStepReset;
} else {
parser_step = SomfyKeytisDecoderStepReset;
}
} else {
if (DURATION_DIFF(duration, te_short) <
te_delta) {
event = ManchesterEventShortHigh;
} else if (
DURATION_DIFF(duration, te_long) <
te_delta) {
event = ManchesterEventLongHigh;
} else {
parser_step = SomfyKeytisDecoderStepReset;
}
}
if (event != ManchesterEventReset) {
bool data;
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &data);
if (data_ok) {
if (decode_count_bit < 56) {
decode_data = (decode_data << 1) | data;
} else {
// press_duration_counter = (press_duration_counter << 1) | data;
}
decode_count_bit++;
}
}
break;
}
}
protected:
ManchesterState manchester_saved_state = ManchesterStateMid1;
uint8_t subghz_protocol_somfy_keytis_crc(uint64_t data) {
uint8_t crc = 0;
data &= 0xFFF0FFFFFFFFFF;
for (uint8_t i = 0; i < 56; i += 8) {
crc = crc ^ data >> i ^ (data >> (i + 4));
}
return crc & 0xf;
}
};
#endif

View File

@@ -0,0 +1,123 @@
#ifndef __FPROTO_SOMIFYTELIS_H__
#define __FPROTO_SOMIFYTELIS_H__
#include "subghzdbase.hpp"
typedef enum {
SomfyTelisDecoderStepReset = 0,
SomfyTelisDecoderStepCheckPreambula,
SomfyTelisDecoderStepFoundPreambula,
SomfyTelisDecoderStepStartDecode,
SomfyTelisDecoderStepDecoderData,
} SomfyTelisDecoderStep;
class FProtoSubGhzDSomifyTelis : public FProtoSubGhzDBase {
public:
FProtoSubGhzDSomifyTelis() {
sensorType = FPS_SOMIFY_TELIS;
te_short = 640;
te_long = 1280;
te_delta = 250;
min_count_bit_for_found = 56;
}
void feed(bool level, uint32_t duration) {
ManchesterEvent event = ManchesterEventReset;
switch (parser_step) {
case SomfyTelisDecoderStepReset:
if ((level) && DURATION_DIFF(duration, te_short * 4) < te_delta * 4) {
parser_step = SomfyTelisDecoderStepFoundPreambula;
header_count++;
}
break;
case SomfyTelisDecoderStepFoundPreambula:
if ((!level) && (DURATION_DIFF(duration, te_short * 4) < te_delta * 4)) {
parser_step = SomfyTelisDecoderStepCheckPreambula;
} else {
header_count = 0;
parser_step = SomfyTelisDecoderStepReset;
}
break;
case SomfyTelisDecoderStepCheckPreambula:
if (level) {
if (DURATION_DIFF(duration, te_short * 4) < te_delta * 4) {
parser_step = SomfyTelisDecoderStepFoundPreambula;
header_count++;
} else if (
(header_count > 1) &&
(DURATION_DIFF(duration, te_short * 7) < te_delta * 4)) {
parser_step = SomfyTelisDecoderStepDecoderData;
decode_data = 0;
decode_count_bit = 0;
header_count = 0;
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
}
}
break;
case SomfyTelisDecoderStepDecoderData:
if (!level) {
if (DURATION_DIFF(duration, te_short) < te_delta) {
event = ManchesterEventShortLow;
} else if (
DURATION_DIFF(duration, te_long) < te_delta) {
event = ManchesterEventLongLow;
} else if (
duration >= (te_long + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) {
// check crc
uint64_t data_tmp = decode_data ^ (decode_data >> 8);
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_telis_crc(data_tmp)) {
data = decode_data;
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
}
decode_data = 0;
decode_count_bit = 0;
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventReset, &manchester_saved_state, NULL);
FProtoGeneral::manchester_advance(manchester_saved_state, ManchesterEventLongHigh, &manchester_saved_state, NULL);
parser_step = SomfyTelisDecoderStepReset;
} else {
parser_step = SomfyTelisDecoderStepReset;
}
} else {
if (DURATION_DIFF(duration, te_short) < te_delta) {
event = ManchesterEventShortHigh;
} else if (
DURATION_DIFF(duration, te_long) < te_delta) {
event = ManchesterEventLongHigh;
} else {
parser_step = SomfyTelisDecoderStepReset;
}
}
if (event != ManchesterEventReset) {
bool data;
bool data_ok = FProtoGeneral::manchester_advance(manchester_saved_state, event, &manchester_saved_state, &data);
if (data_ok) {
decode_data = (decode_data << 1) | data;
decode_count_bit++;
}
}
break;
}
}
protected:
ManchesterState manchester_saved_state = ManchesterStateMid1;
uint8_t subghz_protocol_somfy_telis_crc(uint64_t data) {
uint8_t crc = 0;
data &= 0xFFF0FFFFFFFFFF;
for (uint8_t i = 0; i < 56; i += 8) {
crc = crc ^ data >> i ^ (data >> (i + 4));
}
return crc & 0xf;
}
};
#endif

View File

@@ -25,10 +25,7 @@ class FProtoSubGhzDBase {
// General data holder, these will be passed
uint8_t sensorType = FPS_Invalid;
uint8_t btn = SD_NO_BTN;
uint16_t data_count_bit = 0;
uint32_t cnt = SD_NO_CNT;
uint32_t serial = SD_NO_SERIAL;
uint64_t data = 0;
protected:

View File

@@ -47,6 +47,10 @@ So include here the .hpp, and add a new element to the protos vector in the cons
#include "s-smc5326.hpp"
#include "s-star_line.hpp"
#include "s-x10.hpp"
// #include "s-hormannbisecure.hpp" //fm
#include "s-legrand.hpp"
#include "s-somify_keytis.hpp"
#include "s-somify_telis.hpp"
// GENIE FROM PR
@@ -94,11 +98,12 @@ class SubGhzDProtos : public FProtoListGeneral {
protos[FPS_SECPLUSV1] = new FProtoSubGhzDSecPlusV1();
protos[FPS_SECPLUSV2] = new FProtoSubGhzDSecPlusV2();
protos[FPS_SMC5326] = new FProtoSubGhzDSmc5326();
// somify keytis skipped
// somify telis skipped
protos[FPS_SOMIFY_KEYTIS] = new FProtoSubGhzDSomifyKeytis();
protos[FPS_SOMIFY_TELIS] = new FProtoSubGhzDSomifyTelis();
protos[FPS_STARLINE] = new FProtoSubGhzDStarLine();
protos[FPS_X10] = new FProtoSubGhzDX10();
// genie skipped
// protos[FPS_HORMANNBISECURE] = new FProtoSubGhzDHormannBiSecure(); //fm
protos[FPS_LEGRAND] = new FProtoSubGhzDLegrand();
for (uint8_t i = 0; i < FPS_COUNT; ++i) {
if (protos[i] != NULL) protos[i]->setCallback(callbackTarget);
@@ -115,7 +120,7 @@ class SubGhzDProtos : public FProtoListGeneral {
};
static void callbackTarget(FProtoSubGhzDBase* instance) {
SubGhzDDataMessage packet_message{instance->sensorType, instance->btn, instance->data_count_bit, instance->serial, instance->data, instance->cnt};
SubGhzDDataMessage packet_message{instance->sensorType, instance->data_count_bit, instance->data};
shared_memory.application_queue.push(packet_message);
}

View File

@@ -11,10 +11,6 @@ Also it must have a switch-case element in the getSubGhzDSensorTypeName() functi
#define FPM_AM 0
#define FPM_FM 1
#define SD_NO_SERIAL 0xFFFFFFFF
#define SD_NO_BTN 0xFF
#define SD_NO_CNT 0xFF
enum FPROTO_SUBGHZD_SENSOR : uint8_t {
FPS_Invalid = 0,
FPS_PRINCETON,
@@ -35,10 +31,12 @@ enum FPROTO_SUBGHZD_SENSOR : uint8_t {
FPS_HONEYWELL,
FPS_HONEYWELLWDB,
FPS_HORMANN,
// FPS_HORMANNBISECURE,
FPS_IDO,
FPS_INTERTECHNOV3,
FPS_KEELOQ,
FPS_KINGGATESSTYLO4K,
FPS_LEGRAND,
FPS_LINEAR,
FPS_LINEARDELTA3,
FPS_MAGELLAN,
@@ -56,7 +54,8 @@ enum FPROTO_SUBGHZD_SENSOR : uint8_t {
FPS_SMC5326,
FPS_STARLINE,
FPS_X10,
FPS_SOMIFY_KEYTIS,
FPS_SOMIFY_TELIS,
FPS_COUNT
};