SubghzD & Weather improvments (#2237)

* Weather restructure

* Added Solight TE44 protocol

* Add disabled Marantec24, and GangQi

* More opt in subghzd
This commit is contained in:
Totoo 2024-09-06 20:23:11 +02:00 committed by GitHub
parent 76763b9bab
commit e6afd7744d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 687 additions and 512 deletions

View File

@ -212,7 +212,10 @@ const char* SubGhzDView::getSensorTypeName(FPROTO_SUBGHZD_SENSOR type) {
return "Somify Keytis"; return "Somify Keytis";
case FPS_SOMIFY_TELIS: case FPS_SOMIFY_TELIS:
return "Somify Telis"; return "Somify Telis";
case FPS_GANGQI:
return "GangQi";
case FPS_MARANTEC24:
return "Marantec24";
case FPS_Invalid: case FPS_Invalid:
default: default:
return "Unknown"; return "Unknown";
@ -717,5 +720,18 @@ void SubGhzDRecentEntryDetailView::parseProtocol() {
serial = dataa & 0xFFFFFF; // address} serial = dataa & 0xFFFFFF; // address}
return; return;
} }
if (entry_.sensorType == FPS_GANGQI) {
btn = 0; // parser needs some time i think in flipper side.
cnt = (uint8_t)(entry_.data >> 32);
serial = (entry_.data & 0xFFFFFFFF);
return;
}
if (entry_.sensorType == FPS_MARANTEC24) {
serial = (entry_.data >> 4);
btn = entry_.data & 0xf;
return;
}
} }
} // namespace ui } // namespace ui

View File

@ -26,6 +26,7 @@
#include "baseband_api.hpp" #include "baseband_api.hpp"
#include "string_format.hpp" #include "string_format.hpp"
#include "portapack_persistent_memory.hpp" #include "portapack_persistent_memory.hpp"
#include "../baseband/fprotos/fprotogeneral.hpp"
using namespace portapack; using namespace portapack;
using namespace ui; using namespace ui;
@ -138,7 +139,8 @@ void WeatherView::on_tick_second() {
} }
void WeatherView::on_data(const WeatherDataMessage* data) { void WeatherView::on_data(const WeatherDataMessage* data) {
WeatherRecentEntry key{data->sensorType, data->id, data->temp, data->humidity, data->channel, data->battery_low}; WeatherRecentEntry key = process_data(data);
// WeatherRecentEntry key{data->sensorType, data->id, data->temp, data->humidity, data->channel, data->battery_low};
auto matching_recent = find(recent, key.key()); auto matching_recent = find(recent, key.key());
if (matching_recent != std::end(recent)) { if (matching_recent != std::end(recent)) {
// Found within. Move to front of list, increment counter. // Found within. Move to front of list, increment counter.
@ -209,6 +211,8 @@ const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) {
return "Acurite5in1"; return "Acurite5in1";
case FPW_EmosE601x: case FPW_EmosE601x:
return "EmosE601x"; return "EmosE601x";
case FPW_SolightTE44:
return "SolightTE44";
case FPW_Invalid: case FPW_Invalid:
default: default:
return "Unknown"; return "Unknown";
@ -254,4 +258,287 @@ void RecentEntriesTable<ui::WeatherRecentEntries>::draw(
painter.draw_string(target_rect.location(), style, line); painter.draw_string(target_rect.location(), style, line);
} }
#define LACROSSE_TX_MSG_TYPE_TEMP 0x00
#define LACROSSE_TX_MSG_TYPE_HUM 0x0E
WeatherRecentEntry WeatherView::process_data(const WeatherDataMessage* data) {
WeatherRecentEntry ret = {};
ret.sensorType = data->sensorType;
int16_t i16 = 0;
uint16_t u16 = 0;
uint64_t u64 = 0;
uint8_t u8 = 0;
uint8_t channel_3021[] = {3, 0, 2, 1};
float flo = 0.0;
switch (data->sensorType) {
case FPW_NexusTH:
ret.id = (data->decode_data >> 28) & 0xFF;
ret.battery_low = !((data->decode_data >> 27) & 1);
ret.channel = ((data->decode_data >> 24) & 0x03) + 1;
if (!((data->decode_data >> 23) & 1)) {
ret.temp = (float)((data->decode_data >> 12) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 12) & 0x07FF) + 1) / -10.0f;
}
ret.humidity = data->decode_data & 0xFF;
if (ret.humidity > 95)
ret.humidity = 95;
else if (ret.humidity < 20)
ret.humidity = 20;
break;
case FPW_Acurite592TXR:
u8 = ((data->decode_data >> 54) & 0x03);
ret.channel = channel_3021[u8];
ret.id = (data->decode_data >> 40) & 0x3FFF;
ret.battery_low = !((data->decode_data >> 38) & 1);
ret.humidity = (data->decode_data >> 24) & 0x7F;
u16 = ((data->decode_data >> 9) & 0xF80) | ((data->decode_data >> 8) & 0x7F);
ret.temp = ((float)(u16)-1000) / 10.0f;
break;
case FPW_Acurite606TX:
ret.id = (data->decode_data >> 24) & 0xFF;
ret.battery_low = (data->decode_data >> 23) & 1;
if (!((data->decode_data >> 19) & 1)) {
ret.temp = (float)((data->decode_data >> 8) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 8) & 0x07FF) + 1) / -10.0f;
}
break;
case FPW_Acurite609TX:
ret.id = (data->decode_data >> 32) & 0xFF;
ret.battery_low = (data->decode_data >> 31) & 1;
ret.channel = WS_NO_CHANNEL;
// Temperature in Celsius is encoded as a 12 bit integer value
// multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
// negative values are recovered by sign extend from int16_t.
i16 = (int16_t)(((data->decode_data >> 12) & 0xf000) | ((data->decode_data >> 16) << 4));
ret.temp = (i16 >> 4) * 0.1f;
ret.humidity = (data->decode_data >> 8) & 0xff;
break;
case FPW_Ambient:
id = (data->decode_data >> 32) & 0xFF;
ret.battery_low = (data->decode_data >> 31) & 1;
ret.channel = ((data->decode_data >> 28) & 0x07) + 1;
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data->decode_data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
ret.humidity = (data->decode_data >> 8) & 0xFF;
break;
case FPW_AuriolAhfl:
ret.id = data->decode_data >> 34;
ret.battery_low = (data->decode_data >> 33) & 1;
// btn = (data >> 32) & 1;
ret.channel = ((data->decode_data >> 30) & 0x3) + 1;
if (!((data->decode_data >> 29) & 1)) {
ret.temp = (float)((data->decode_data >> 18) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 18) & 0x07FF) + 1) / -10.0f;
}
ret.humidity = (data->decode_data >> 11) & 0x7F;
break;
case FPW_AuriolTH:
ret.id = (data->decode_data >> 31) & 0xFF;
ret.battery_low = ((data->decode_data >> 30) & 1);
ret.channel = ((data->decode_data >> 25) & 0x03) + 1;
if (!((data->decode_data >> 23) & 1)) {
ret.temp = (float)((data->decode_data >> 13) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 13) & 0x07FF) + 1) / -10.0f;
}
ret.humidity = (data->decode_data >> 1) & 0x7F;
break;
case FPW_GTWT02:
ret.id = (data->decode_data >> 29) & 0xFF;
ret.battery_low = (data->decode_data >> 28) & 1;
// btn = (data->decode_data >> 27) & 1;
ret.channel = ((data->decode_data >> 25) & 0x3) + 1;
if (!((data->decode_data >> 24) & 1)) {
ret.temp = (float)((data->decode_data >> 13) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 13) & 0x07FF) + 1) / -10.0f;
}
ret.humidity = (data->decode_data >> 6) & 0x7F;
if (ret.humidity <= 10) // actually the sensors sends 10 below working range of 20%
ret.humidity = 0;
else if (ret.humidity > 90) // actually the sensors sends 110 above working range of 90%
ret.humidity = 100;
break;
case FPW_GTWT03:
ret.id = data->decode_data >> 33;
ret.humidity = (data->decode_data >> 25) & 0xFF;
if (ret.humidity <= 10) { // actually the sensors sends 10 below working range of 20%
ret.humidity = 0;
} else if (ret.humidity > 95) { // actually the sensors sends 110 above working range of 90%
ret.humidity = 100;
}
ret.battery_low = (data->decode_data >> 24) & 1;
// (data->decode_data >> 23) & 1;
ret.channel = ((data->decode_data >> 21) & 0x03) + 1;
if (!((data->decode_data >> 20) & 1)) {
ret.temp = (float)((data->decode_data >> 9) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 9) & 0x07FF) + 1) / -10.0f;
}
break;
case FPW_INFACTORY:
ret.id = data->decode_data >> 32;
ret.battery_low = (data->decode_data >> 26) & 1;
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data->decode_data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
ret.humidity = (((data->decode_data >> 8) & 0x0F) * 10) + ((data->decode_data >> 4) & 0x0F); // BCD, 'A0'=100%rH
ret.channel = data->decode_data & 0x03;
break;
case FPW_LACROSSETX:
u8 = (data->decode_data >> 32) & 0x0F;
ret.id = (((data->decode_data >> 28) & 0x0F) << 3) | (((data->decode_data >> 24) & 0x0F) >> 1);
flo = (float)((data->decode_data >> 20) & 0x0F) * 10.0f + (float)((data->decode_data >> 16) & 0x0F) + (float)((data->decode_data >> 12) & 0x0F) * 0.1f;
if (u8 == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051
ret.temp = flo - 50.0f;
ret.humidity = WS_NO_HUMIDITY;
} else if (u8 == LACROSSE_TX_MSG_TYPE_HUM) {
// ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard
ret.humidity = (uint8_t)flo;
}
break;
case FPW_LACROSSETX141thbv2:
ret.id = data->decode_data >> 32;
ret.battery_low = (data->decode_data >> 31) & 1;
// btn = (data->decode_data >> 30) & 1;
ret.channel = ((data->decode_data >> 28) & 0x03) + 1;
ret.temp = ((float)((data->decode_data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
ret.humidity = (data->decode_data >> 8) & 0xFF;
break;
case FPW_OREGON2:
i16 = ((data->decode_data >> 4) & 0xF) * 10 + (((data->decode_data >> 4) >> 4) & 0xF);
i16 *= 10;
i16 += (data->decode_data >> 12) & 0xF;
if (data->decode_data & 0xF) i16 = -i16;
ret.temp = (float)i16 / 10.0;
// todo fix missing parts.
break;
case FPW_OREGON3:
// todo check
ret.humidity = ((data->decode_data >> 4) & 0xF) * 10 + (((data->decode_data >> 4) >> 4) & 0xF);
i16 = (((data->decode_data >> 12) >> 4) & 0xF) * 10 + ((((data->decode_data >> 12) >> 4) >> 4) & 0xF); // ws_oregon3_bcd_decode_short((data->decode_data >> 12) >> 4);
i16 *= 10;
i16 += ((data->decode_data >> 12) >> 12) & 0xF;
if ((data->decode_data >> 12) & 0xF) i16 = -i16;
ret.temp = (float)i16 / 10.0;
break;
case FPW_OREGONv1:
u64 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data, 32);
id = u64 & 0xFF;
ret.channel = ((u64 >> 6) & 0x03) + 1;
ret.temp = ((u64 >> 8) & 0x0F) * 0.1f + ((u64 >> 12) & 0x0F) + ((u64 >> 16) & 0x0F) * 10.0f;
if (!((u64 >> 21) & 1)) {
ret.temp = ret.temp;
} else {
ret.temp = -ret.temp;
}
ret.battery_low = !((u64 >> 23) & 1ULL);
break;
case FPW_THERMOPROTX4:
ret.id = (data->decode_data >> 25) & 0xFF;
ret.battery_low = (data->decode_data >> 24) & 1;
// btn = (data->decode_data >> 23) & 1;
ret.channel = ((data->decode_data >> 21) & 0x03) + 1;
if (!((data->decode_data >> 20) & 1)) {
ret.temp = (float)((data->decode_data >> 9) & 0x07FF) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 9) & 0x07FF) + 1) / -10.0f;
}
ret.humidity = (data->decode_data >> 1) & 0xFF;
break;
case FPW_TX_8300:
ret.humidity = (((data->decode_data >> 28) & 0x0F) * 10) + ((data->decode_data >> 24) & 0x0F);
if (!((data->decode_data >> 22) & 0x03))
ret.battery_low = 0;
else
ret.battery_low = 1;
ret.channel = (data->decode_data >> 20) & 0x03;
ret.id = (data->decode_data >> 12) & 0x7F;
ret.temp = ((data->decode_data >> 8) & 0x0F) * 10.0f + ((data->decode_data >> 4) & 0x0F) +
(data->decode_data & 0x0F) * 0.1f;
if (!((data->decode_data >> 19) & 1)) {
ret.temp = ret.temp;
} else {
ret.temp = -ret.temp;
}
break;
case FPW_WENDOX_W6726:
ret.id = (data->decode_data >> 24) & 0xFF;
ret.battery_low = (data->decode_data >> 6) & 1;
if (((data->decode_data >> 23) & 1)) {
ret.temp = (float)(((data->decode_data >> 14) & 0x1FF) + 12) / 10.0f;
} else {
ret.temp = (float)((~(data->decode_data >> 14) & 0x1FF) + 1 - 12) / -10.0f;
}
if (ret.temp < -50.0f) {
ret.temp = -50.0f;
} else if (ret.temp > 70.0f) {
ret.temp = 70.0f;
}
break;
case FPW_Acurite986:
ret.id = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 24, 8);
ret.id = (id << 8) | FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 16, 8);
ret.battery_low = (data->decode_data >> 14) & 1;
ret.channel = ((data->decode_data >> 15) & 1) + 1;
i16 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 32, 8);
if (i16 & 0x80) {
i16 = -(i16 & 0x7F);
}
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)i16);
break;
case FPW_KEDSUM:
ret.id = data->decode_data >> 32;
if ((data->decode_data >> 30) & 0x3) {
ret.battery_low = 0;
} else {
ret.battery_low = 1;
}
ret.channel = ((data->decode_data >> 28) & 0x3) + 1;
u16 = ((data->decode_data >> 16) & 0x0f) << 8 | ((data->decode_data >> 20) & 0x0f) << 4 | ((data->decode_data >> 24) & 0x0f);
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)u16 - 900.0f) / 10.0f);
ret.humidity = ((data->decode_data >> 8) & 0x0f) << 4 | ((data->decode_data >> 12) & 0x0f);
break;
case FPW_Acurite5in1:
u8 = ((data->decode_data >> 62) & 0x03);
ret.channel = channel_3021[u8];
ret.id = (data->decode_data >> 48) & 0x3FFF;
ret.battery_low = !((data->decode_data >> 46) & 1);
ret.humidity = (data->decode_data >> 8) & 0x7F;
u16 = ((data->decode_data >> (24 - 7)) & 0x780) | ((data->decode_data >> 16) & 0x7F);
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)(u16)-400) / 10.0f);
break;
case FPW_EmosE601x:
ret.id = 0xffff; //(upper_decode_data >> 24) & 0xff; //todo maybe with oregon, and +64bit usage/message
ret.battery_low = (data->decode_data >> 10) & 1;
i16 = (data->decode_data >> 40) & 0xfff;
/* Handle signed data */
if (i16 & 0x800) {
i16 |= 0xf000;
}
ret.temp = (float)i16 / 10.0;
ret.humidity = (data->decode_data >> 32) & 0xff;
ret.channel = (data->decode_data >> 52) & 0x03;
break;
case FPW_SolightTE44:
ret.id = (data->decode_data >> 28) & 0xff;
ret.battery_low = !(data->decode_data >> 27) & 0x01;
ret.channel = ((data->decode_data >> 24) & 0x03) + 1;
i16 = (data->decode_data >> 12) & 0x0fff;
/* Handle signed data */
if (i16 & 0x0800) {
i16 |= 0xf000;
}
ret.temp = (float)i16 / 10.0;
break;
case FPW_Invalid:
default:
break;
}
return ret;
}
} // namespace ui } // namespace ui

View File

@ -96,7 +96,7 @@ class WeatherView : public View {
private: private:
void on_tick_second(); void on_tick_second();
void on_data(const WeatherDataMessage* data); void on_data(const WeatherDataMessage* data);
WeatherRecentEntry process_data(const WeatherDataMessage* data);
NavigationView& nav_; NavigationView& nav_;
RxRadioState radio_state_{ RxRadioState radio_state_{
433'920'000 /* frequency */, 433'920'000 /* frequency */,

View File

@ -36,7 +36,6 @@ class FProtoSubGhzDBett : public FProtoSubGhzDBase {
(te_delta * 15)) { (te_delta * 15)) {
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
// dip decoder needed // dip decoder needed
if (callback) callback(this); if (callback) callback(this);

View File

@ -53,7 +53,6 @@ class FProtoSubGhzDCame : public FProtoSubGhzDBase {
parser_step = CameDecoderStepFoundStartBit; parser_step = CameDecoderStepFoundStartBit;
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == AIRFORCE_COUNT_BIT) || 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)) { (decode_count_bit == PRASTEL_COUNT_BIT) || (decode_count_bit == CAME_24_COUNT_BIT)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
// if flippa hacky, i hacky // if flippa hacky, i hacky
sensorType = FPS_CAME; sensorType = FPS_CAME;

View File

@ -43,7 +43,6 @@ class FProtoSubGhzDCameAtomo : public FProtoSubGhzDBase {
duration >= ((uint32_t)te_long * 2 + te_delta)) { duration >= ((uint32_t)te_long * 2 + te_delta)) {
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -43,7 +43,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
} else if ( } else if (
duration >= ((uint32_t)te_long * 2 + te_delta)) { duration >= ((uint32_t)te_long * 2 + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -58,7 +58,6 @@ class FProtoSubGhzDChambCode : public FProtoSubGhzDBase {
if (duration > te_short * 5) { if (duration > te_short * 5) {
if (decode_count_bit >= min_count_bit_for_found) { if (decode_count_bit >= min_count_bit_for_found) {
if (subghz_protocol_decoder_chamb_code_check_mask_and_parse()) { if (subghz_protocol_decoder_chamb_code_check_mask_and_parse()) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -62,7 +62,6 @@ class FProtoSubGhzDClemsa : public FProtoSubGhzDBase {
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -44,7 +44,6 @@ class FProtoSubGhzDDoitrand : public FProtoSubGhzDBase {
if (duration >= ((uint32_t)te_short * 10 + te_delta)) { if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
parser_step = DoitrandDecoderStepFoundStartBit; parser_step = DoitrandDecoderStepFoundStartBit;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -72,7 +72,6 @@ class FProtoSubGhzDDooya : public FProtoSubGhzDBase {
parser_step = DooyaDecoderStepFoundStartBit; parser_step = DooyaDecoderStepFoundStartBit;
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -43,7 +43,6 @@ class FProtoSubGhzDFaac : public FProtoSubGhzDBase {
if (duration >= ((uint32_t)te_short * 3 + te_delta)) { if (duration >= ((uint32_t)te_short * 3 + te_delta)) {
parser_step = FaacSLHDecoderStepFoundPreambula; parser_step = FaacSLHDecoderStepFoundPreambula;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
// remark controller skipped // remark controller skipped
if (callback) callback(this); if (callback) callback(this);

View File

@ -0,0 +1,86 @@
#ifndef __FPROTO_GANGQI_H__
#define __FPROTO_GANGQI_H__
#include "subghzdbase.hpp"
typedef enum {
GangQiDecoderStepReset = 0,
GangQiDecoderStepSaveDuration,
GangQiDecoderStepCheckDuration,
} GangQiDecoderStep;
class FProtoSubGhzDGangqi : public FProtoSubGhzDBase {
public:
FProtoSubGhzDGangqi() {
sensorType = FPS_GANGQI;
te_short = 500;
te_long = 1200;
te_delta = 200;
min_count_bit_for_found = 34;
}
void feed(bool level, uint32_t duration) {
switch (parser_step) {
case GangQiDecoderStepReset:
if ((!level) && (DURATION_DIFF(duration, te_long * 2) < te_delta * 3)) {
// Found GAP
decode_data = 0;
decode_count_bit = 0;
parser_step = GangQiDecoderStepSaveDuration;
}
break;
case GangQiDecoderStepSaveDuration:
if (level) {
te_last = duration;
parser_step = GangQiDecoderStepCheckDuration;
} else {
parser_step = GangQiDecoderStepReset;
}
break;
case GangQiDecoderStepCheckDuration:
if (!level) {
// Bit 0 is short and long timing
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
(DURATION_DIFF(duration, te_long) < te_delta)) {
subghz_protocol_blocks_add_bit(0);
parser_step = GangQiDecoderStepSaveDuration;
// Bit 1 is long and short timing
} else if (
(DURATION_DIFF(te_last, te_long) < te_delta) &&
(DURATION_DIFF(duration, te_short) < te_delta)) {
subghz_protocol_blocks_add_bit(1);
parser_step = GangQiDecoderStepSaveDuration;
} else if (
// End of the key
DURATION_DIFF(duration, te_short * 4) <
te_delta) {
// Found next GAP and add bit 0 or 1 (only bit 0 was found on the remotes)
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
subghz_protocol_blocks_add_bit(0);
}
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
subghz_protocol_blocks_add_bit(1);
}
// If got 34 bits key reading is finished
if (decode_count_bit == min_count_bit_for_found) {
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
decode_data = 0;
decode_count_bit = 0;
parser_step = GangQiDecoderStepReset;
} else {
parser_step = GangQiDecoderStepReset;
}
} else {
parser_step = GangQiDecoderStepReset;
}
break;
}
}
};
#endif

View File

@ -44,7 +44,6 @@ class FProtoSubGhzDGateTx : public FProtoSubGhzDBase {
if (duration >= ((uint32_t)te_short * 10 + te_delta)) { if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
parser_step = GateTXDecoderStepFoundStartBit; parser_step = GateTXDecoderStepFoundStartBit;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -49,7 +49,6 @@ class FProtoSubGhzDHoltek : public FProtoSubGhzDBase {
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
if ((decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) { if ((decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -44,11 +44,8 @@ class FProtoSubGhzDHoltekHt12x : public FProtoSubGhzDBase {
if (!level) { if (!level) {
if (duration >= ((uint32_t)te_short * 10 + te_delta)) { if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
if (data != decode_data) { data_count_bit = decode_count_bit;
data = decode_data; if (callback) callback(this);
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
} }
decode_data = 0; decode_data = 0;
decode_count_bit = 0; decode_count_bit = 0;

View File

@ -71,7 +71,6 @@ class FProtoSubGhzDHoneywell : public FProtoSubGhzDBase {
uint16_t crc = decode_data & 0xFFFF; uint16_t crc = decode_data & 0xFFFF;
if (crc == crc_calc) { if (crc == crc_calc) {
// the data is good. process it. // 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 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
if (callback) callback(this); if (callback) callback(this);
decode_data = 0; decode_data = 0;

View File

@ -36,7 +36,6 @@ class FProtoSubGhzDHoneywellWdb : public FProtoSubGhzDBase {
if (DURATION_DIFF(duration, te_short * 3) < te_delta) { if (DURATION_DIFF(duration, te_short * 3) < te_delta) {
if ((decode_count_bit == min_count_bit_for_found) && if ((decode_count_bit == min_count_bit_for_found) &&
((decode_data & 0x01) == FProtoGeneral::subghz_protocol_blocks_get_parity(decode_data >> 1, min_count_bit_for_found - 1))) { ((decode_data & 0x01) == FProtoGeneral::subghz_protocol_blocks_get_parity(decode_data >> 1, min_count_bit_for_found - 1))) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
// controller has too much, should be done on ui side // controller has too much, should be done on ui side
if (callback) callback(this); if (callback) callback(this);

View File

@ -47,7 +47,6 @@ class FProtoSubGhzDHormann : public FProtoSubGhzDBase {
parser_step = HormannDecoderStepFoundStartBit; parser_step = HormannDecoderStepFoundStartBit;
if (decode_count_bit >= if (decode_count_bit >=
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -24,7 +24,6 @@ class FProtoSubGhzDHormannBiSecure : public FProtoSubGhzDBase {
void subghz_protocol_decoder_hormann_bisecur_reset() { void subghz_protocol_decoder_hormann_bisecur_reset() {
parser_step = HormannBiSecurDecoderStepReset; parser_step = HormannBiSecurDecoderStepReset;
data = 0;
for (uint8_t i = 0; i < 22; ++i) dataa[i] = 0; for (uint8_t i = 0; i < 22; ++i) dataa[i] = 0;
data_count_bit = 0; data_count_bit = 0;
manchester_saved_state = ManchesterStateStart1; manchester_saved_state = ManchesterStateStart1;

View File

@ -44,7 +44,6 @@ class FProtoSubGhzDIdo : public FProtoSubGhzDBase {
parser_step = IDoDecoderStepFoundPreambula; parser_step = IDoDecoderStepFoundPreambula;
if (decode_count_bit >= if (decode_count_bit >=
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -66,7 +66,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
parser_step = IntertechnoV3DecoderStepStartSync; parser_step = IntertechnoV3DecoderStepStartSync;
if ((decode_count_bit == min_count_bit_for_found) || if ((decode_count_bit == min_count_bit_for_found) ||
(decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) { (decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -57,11 +57,8 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
parser_step = KeeloqDecoderStepReset; parser_step = KeeloqDecoderStepReset;
if ((decode_count_bit >= min_count_bit_for_found) && if ((decode_count_bit >= min_count_bit_for_found) &&
(decode_count_bit <= min_count_bit_for_found + 2)) { (decode_count_bit <= min_count_bit_for_found + 2)) {
if (data != decode_data) { data_count_bit = min_count_bit_for_found;
data = decode_data; if (callback) callback(this);
data_count_bit = min_count_bit_for_found;
if (callback) callback(this);
}
decode_data = 0; decode_data = 0;
decode_count_bit = 0; decode_count_bit = 0;
header_count = 0; header_count = 0;
@ -96,6 +93,8 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
break; break;
} }
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -50,7 +50,8 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
DURATION_DIFF(duration, te_short * 2) < te_delta * 2) { DURATION_DIFF(duration, te_short * 2) < te_delta * 2) {
parser_step = KingGates_stylo_4kDecoderStepSaveDuration; parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
decode_data = 0; decode_data = 0;
data_2 = 0; // data_2 = 0;
// data = 0;
decode_count_bit = 0; decode_count_bit = 0;
header_count = 0; header_count = 0;
} }
@ -58,17 +59,17 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
case KingGates_stylo_4kDecoderStepSaveDuration: case KingGates_stylo_4kDecoderStepSaveDuration:
if (!level) { if (!level) {
if (duration >= ((uint32_t)te_long * 3)) { if (duration >= ((uint32_t)te_long * 3)) {
if (decode_count_bit == if (decode_count_bit == min_count_bit_for_found) {
min_count_bit_for_found) { // data = data_2;
data = data_2; // data_2 = decode_data; // TODO DATA2
data_2 = decode_data; // TODO DATA2
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
// decode_data = data;
if (callback) callback(this); if (callback) callback(this);
} }
parser_step = KingGates_stylo_4kDecoderStepReset; parser_step = KingGates_stylo_4kDecoderStepReset;
decode_data = 0; decode_data = 0;
data_2 = 0; // data_2 = 0;
decode_count_bit = 0; decode_count_bit = 0;
header_count = 0; header_count = 0;
break; break;
@ -101,7 +102,7 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
header_count = 0; header_count = 0;
} }
if (decode_count_bit == 53) { if (decode_count_bit == 53) {
data_2 = decode_data; // data_2 = decode_data;
decode_data = 0; decode_data = 0;
} }
} else { } else {
@ -113,7 +114,9 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
} }
protected: protected:
uint64_t data_2 = 0; // uint64_t data_2 = 0;
// uint64_t data = 0;
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -79,23 +79,17 @@ class FProtoSubGhzDLegrand : public FProtoSubGhzDBase {
if (found) { if (found) {
te += duration; te += duration;
if (decode_count_bit < if (decode_count_bit < min_count_bit_for_found) {
min_count_bit_for_found) {
parser_step = LegrandDecoderStepSaveDuration; parser_step = LegrandDecoderStepSaveDuration;
break; break;
} }
// enough bits for a packet found, save it only if there was a previous packet // enough bits for a packet found, save it only if there was a previous packet
// with the same data // with the same data
if (data && (data != decode_data)) { te /= decode_count_bit * 4;
te /= decode_count_bit * 4; data_count_bit = decode_count_bit;
if (callback) {
data = decode_data; callback(this);
data_count_bit = decode_count_bit;
if (callback) {
callback(this);
}
} }
// fallthrough to reset, the next bit is expected to be a sync // fallthrough to reset, the next bit is expected to be a sync
// it also takes care of resetting the decoder state // it also takes care of resetting the decoder state

View File

@ -54,7 +54,6 @@ class FProtoSubGhzDLinear : public FProtoSubGhzDBase {
subghz_protocol_blocks_add_bit(1); subghz_protocol_blocks_add_bit(1);
} }
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -49,11 +49,8 @@ class FProtoSubGhzDLinearDelta3 : public FProtoSubGhzDBase {
subghz_protocol_blocks_add_bit(0); subghz_protocol_blocks_add_bit(0);
} }
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
if ((data == decode_data) && data) { data_count_bit = decode_count_bit;
data = decode_data; if (callback) callback(this);
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
parser_step = LinearD3DecoderStepSaveDuration; parser_step = LinearD3DecoderStepSaveDuration;
} }
break; break;

View File

@ -90,7 +90,6 @@ class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
// Found stop bit // Found stop bit
if ((decode_count_bit == min_count_bit_for_found) && if ((decode_count_bit == min_count_bit_for_found) &&
subghz_protocol_magellan_check_crc()) { subghz_protocol_magellan_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }
@ -129,6 +128,7 @@ class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
} }
return crc; return crc;
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -43,7 +43,6 @@ class FProtoSubGhzDMarantec : public FProtoSubGhzDBase {
} else if ( } else if (
duration >= ((uint32_t)te_long * 2 + te_delta)) { duration >= ((uint32_t)te_long * 2 + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -0,0 +1,93 @@
#ifndef __FPROTO_MARANTEC24_H__
#define __FPROTO_MARANTEC24_H__
#include "subghzdbase.hpp"
typedef enum {
Marantec24DecoderStepReset = 0,
Marantec24DecoderStepSaveDuration,
Marantec24DecoderStepCheckDuration,
} Marantec24DecoderStep;
class FProtoSubGhzDMarantec24 : public FProtoSubGhzDBase {
public:
FProtoSubGhzDMarantec24() {
sensorType = FPS_MARANTEC24;
te_short = 800;
te_long = 1600;
te_delta = 200;
min_count_bit_for_found = 24;
}
void feed(bool level, uint32_t duration) {
// Key samples
// 101011000000010111001000 = AC05C8
// 101011000000010111000100 = AC05C4
// 101011000000010111001100 = AC05CC
// 101011000000010111000000 = AC05C0
switch (parser_step) {
case Marantec24DecoderStepReset:
if ((!level) && (DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
// Found GAP
decode_data = 0;
decode_count_bit = 0;
parser_step = Marantec24DecoderStepSaveDuration;
}
break;
case Marantec24DecoderStepSaveDuration:
if (level) {
te_last = duration;
parser_step = Marantec24DecoderStepCheckDuration;
} else {
parser_step = Marantec24DecoderStepReset;
}
break;
case Marantec24DecoderStepCheckDuration:
if (!level) {
// Bit 0 is long and short x2 timing = 1600us HIGH (te_last) and 2400us LOW
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
(DURATION_DIFF(duration, te_short * 3) < te_delta)) {
subghz_protocol_blocks_add_bit(0);
parser_step = Marantec24DecoderStepSaveDuration;
// Bit 1 is short and long x2 timing = 800us HIGH (te_last) and 3200us LOW
} else if (
(DURATION_DIFF(te_last, te_short) < te_delta) &&
(DURATION_DIFF(duration, te_long * 2) < te_delta)) {
subghz_protocol_blocks_add_bit(1);
parser_step = Marantec24DecoderStepSaveDuration;
} else if (
// End of the key
DURATION_DIFF(duration, te_long * 9) < te_delta * 4) {
// Found next GAP and add bit 0 or 1 (only bit 0 was found on the remotes)
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
(DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
subghz_protocol_blocks_add_bit(0);
}
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
(DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
subghz_protocol_blocks_add_bit(1);
}
// If got 24 bits key reading is finished
if (decode_count_bit == min_count_bit_for_found) {
data_count_bit = decode_count_bit;
if (callback) callback(this);
}
decode_data = 0;
decode_count_bit = 0;
parser_step = Marantec24DecoderStepReset;
} else {
parser_step = Marantec24DecoderStepReset;
}
} else {
parser_step = Marantec24DecoderStepReset;
}
break;
}
}
protected:
};
#endif

View File

@ -61,7 +61,6 @@ class FProtoSubGhzDMastercode : public FProtoSubGhzDBase {
} }
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);

View File

@ -48,7 +48,6 @@ class FProtoSubGhzDMegacode : public FProtoSubGhzDBase {
parser_step = MegaCodeDecoderStepReset; parser_step = MegaCodeDecoderStepReset;
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);

View File

@ -67,7 +67,6 @@ class FProtoSubGhzDNeroSketch : public FProtoSubGhzDBase {
// Found stop bit // Found stop bit
parser_step = NeroSketchDecoderStepReset; parser_step = NeroSketchDecoderStepReset;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }
@ -103,6 +102,7 @@ class FProtoSubGhzDNeroSketch : public FProtoSubGhzDBase {
break; break;
} }
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -82,7 +82,6 @@ class FProtoSubGhzDNeroRadio : public FProtoSubGhzDBase {
parser_step = NeroRadioDecoderStepReset; parser_step = NeroRadioDecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) || if ((decode_count_bit == min_count_bit_for_found) ||
(decode_count_bit == min_count_bit_for_found + 1)) { (decode_count_bit == min_count_bit_for_found + 1)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
@ -110,6 +109,7 @@ class FProtoSubGhzDNeroRadio : public FProtoSubGhzDBase {
break; break;
} }
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

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

View File

@ -56,10 +56,9 @@ class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
// Found STOP bit // Found STOP bit
parser_step = NiceFlorSDecoderStepReset; parser_step = NiceFlorSDecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == NICE_ONE_COUNT_BIT)) { 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; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
decode_data = 0;
} }
break; break;
} else { } else {
@ -86,8 +85,8 @@ class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
parser_step = NiceFlorSDecoderStepReset; parser_step = NiceFlorSDecoderStepReset;
} }
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data; // data = decode_data;
decode_data = 0; // decode_data = 0;
} }
break; break;
} }

View File

@ -45,7 +45,6 @@ class FProtoSubGhzDPhoenixV2 : public FProtoSubGhzDBase {
parser_step = Phoenix_V2DecoderStepFoundStartBit; parser_step = Phoenix_V2DecoderStepFoundStartBit;
if (decode_count_bit == if (decode_count_bit ==
min_count_bit_for_found) { min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -49,7 +49,6 @@ class FProtoSubGhzDPowerSmart : public FProtoSubGhzDBase {
} }
if ((decode_data & POWER_SMART_PACKET_HEADER_MASK) == POWER_SMART_PACKET_HEADER) { if ((decode_data & POWER_SMART_PACKET_HEADER_MASK) == POWER_SMART_PACKET_HEADER) {
if (subghz_protocol_power_smart_chek_valid(decode_data)) { if (subghz_protocol_power_smart_chek_valid(decode_data)) {
data = decode_data;
data_count_bit = min_count_bit_for_found; data_count_bit = min_count_bit_for_found;
if (callback) callback(this); if (callback) callback(this);

View File

@ -42,7 +42,6 @@ class FProtoSubGhzDPrinceton : public FProtoSubGhzDBase {
if (duration >= ((uint32_t)te_long * 2)) { if (duration >= ((uint32_t)te_long * 2)) {
parser_step = PrincetonDecoderStepSaveDuration; parser_step = PrincetonDecoderStepSaveDuration;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -50,7 +50,6 @@ class FProtoSubGhzDSecPlusV2 : public FProtoSubGhzDBase {
} else if ( } else if (
duration >= (te_long * 2UL + te_delta)) { duration >= (te_long * 2UL + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (subghz_protocol_secplus_v2_check_packet()) { if (subghz_protocol_secplus_v2_check_packet()) {
// controller too big // controller too big

View File

@ -42,7 +42,6 @@ class FProtoSubGhzDSmc5326 : public FProtoSubGhzDBase {
if (duration >= ((uint32_t)te_long * 2)) { if (duration >= ((uint32_t)te_long * 2)) {
parser_step = SMC5326DecoderStepSaveDuration; parser_step = SMC5326DecoderStepSaveDuration;
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }

View File

@ -68,11 +68,9 @@ class FProtoSubGhzDSomifyKeytis : public FProtoSubGhzDBase {
duration >= (te_long + te_delta)) { duration >= (te_long + te_delta)) {
if (decode_count_bit == min_count_bit_for_found) { if (decode_count_bit == min_count_bit_for_found) {
// check crc // check crc
uint64_t data_tmp = data ^ (data >> 8); uint64_t data_tmp = decode_data ^ (decode_data >> 8);
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_keytis_crc(data_tmp)) { if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_keytis_crc(data_tmp)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
} }
} }
@ -124,6 +122,8 @@ class FProtoSubGhzDSomifyKeytis : public FProtoSubGhzDBase {
} }
return crc & 0xf; return crc & 0xf;
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -71,7 +71,6 @@ class FProtoSubGhzDSomifyTelis : public FProtoSubGhzDBase {
// check crc // check crc
uint64_t data_tmp = decode_data ^ (decode_data >> 8); uint64_t data_tmp = decode_data ^ (decode_data >> 8);
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_telis_crc(data_tmp)) { if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_telis_crc(data_tmp)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);
@ -118,6 +117,7 @@ class FProtoSubGhzDSomifyTelis : public FProtoSubGhzDBase {
} }
return crc & 0xf; return crc & 0xf;
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -53,11 +53,8 @@ class FProtoSubGhzDStarLine : public FProtoSubGhzDBase {
parser_step = StarLineDecoderStepReset; parser_step = StarLineDecoderStepReset;
if ((decode_count_bit >= min_count_bit_for_found) && if ((decode_count_bit >= min_count_bit_for_found) &&
(decode_count_bit <= min_count_bit_for_found + 2)) { (decode_count_bit <= min_count_bit_for_found + 2)) {
if (data != decode_data) { data_count_bit = min_count_bit_for_found;
data = decode_data; if (callback) callback(this);
data_count_bit = min_count_bit_for_found;
if (callback) callback(this);
}
} }
decode_data = 0; decode_data = 0;
decode_count_bit = 0; decode_count_bit = 0;
@ -101,6 +98,7 @@ class FProtoSubGhzDStarLine : public FProtoSubGhzDBase {
break; break;
} }
} }
uint16_t header_count = 0;
}; };
#endif #endif

View File

@ -47,7 +47,6 @@ class FProtoSubGhzDX10 : public FProtoSubGhzDBase {
if (decode_count_bit >= min_count_bit_for_found && if (decode_count_bit >= min_count_bit_for_found &&
((((decode_data >> 24) ^ (decode_data >> 16)) & 0xFF) == 0xFF) && ((((decode_data >> 24) ^ (decode_data >> 16)) & 0xFF) == 0xFF) &&
((((decode_data >> 8) ^ (decode_data)) & 0xFF) == 0xFF)) { ((((decode_data >> 8) ^ (decode_data)) & 0xFF) == 0xFF)) {
data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
if (callback) callback(this); if (callback) callback(this);

View File

@ -26,7 +26,7 @@ class FProtoSubGhzDBase {
// General data holder, these will be passed // General data holder, these will be passed
uint8_t sensorType = FPS_Invalid; uint8_t sensorType = FPS_Invalid;
uint16_t data_count_bit = 0; uint16_t data_count_bit = 0;
uint64_t data = 0; uint64_t decode_data = 0;
protected: protected:
// Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy. // Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy.
@ -42,11 +42,11 @@ class FProtoSubGhzDBase {
uint32_t min_count_bit_for_found = UINT32_MAX; uint32_t min_count_bit_for_found = UINT32_MAX;
SubGhzDProtocolDecoderBaseRxCallback callback = NULL; SubGhzDProtocolDecoderBaseRxCallback callback = NULL;
uint16_t header_count = 0;
uint8_t parser_step = 0; uint8_t parser_step = 0;
uint32_t te_last = 0; uint32_t te_last = 0;
uint32_t decode_count_bit = 0; uint32_t decode_count_bit = 0;
uint64_t decode_data = 0;
// //
}; };

View File

@ -51,7 +51,8 @@ So include here the .hpp, and add a new element to the protos vector in the cons
#include "s-legrand.hpp" #include "s-legrand.hpp"
#include "s-somify_keytis.hpp" #include "s-somify_keytis.hpp"
#include "s-somify_telis.hpp" #include "s-somify_telis.hpp"
#include "s-gangqi.hpp"
#include "s-marantec24.hpp"
// GENIE FROM PR // GENIE FROM PR
#ifndef __FPROTO_PROTOLISTSGZ_H__ #ifndef __FPROTO_PROTOLISTSGZ_H__
@ -104,6 +105,8 @@ class SubGhzDProtos : public FProtoListGeneral {
protos[FPS_X10] = new FProtoSubGhzDX10(); protos[FPS_X10] = new FProtoSubGhzDX10();
// protos[FPS_HORMANNBISECURE] = new FProtoSubGhzDHormannBiSecure(); //fm // protos[FPS_HORMANNBISECURE] = new FProtoSubGhzDHormannBiSecure(); //fm
protos[FPS_LEGRAND] = new FProtoSubGhzDLegrand(); protos[FPS_LEGRAND] = new FProtoSubGhzDLegrand();
protos[FPS_GANGQI] = new FProtoSubGhzDGangqi();
protos[FPS_MARANTEC24] = new FProtoSubGhzDMarantec24();
for (uint8_t i = 0; i < FPS_COUNT; ++i) { for (uint8_t i = 0; i < FPS_COUNT; ++i) {
if (protos[i] != NULL) protos[i]->setCallback(callbackTarget); if (protos[i] != NULL) protos[i]->setCallback(callbackTarget);
@ -120,7 +123,7 @@ class SubGhzDProtos : public FProtoListGeneral {
}; };
static void callbackTarget(FProtoSubGhzDBase* instance) { static void callbackTarget(FProtoSubGhzDBase* instance) {
SubGhzDDataMessage packet_message{instance->sensorType, instance->data_count_bit, instance->data}; SubGhzDDataMessage packet_message{instance->sensorType, instance->data_count_bit, instance->decode_data};
shared_memory.application_queue.push(packet_message); shared_memory.application_queue.push(packet_message);
} }

View File

@ -56,6 +56,8 @@ enum FPROTO_SUBGHZD_SENSOR : uint8_t {
FPS_X10, FPS_X10,
FPS_SOMIFY_KEYTIS, FPS_SOMIFY_KEYTIS,
FPS_SOMIFY_TELIS, FPS_SOMIFY_TELIS,
FPS_GANGQI,
FPS_MARANTEC24,
FPS_COUNT FPS_COUNT
}; };

View File

@ -80,9 +80,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_acurite_592txr_check_crc()) { ws_protocol_acurite_592txr_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_acurite_592txr_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -138,17 +135,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
return false; return false;
} }
} }
void ws_protocol_acurite_592txr_remote_controller() {
uint8_t channel_[] = {3, 0, 2, 1};
uint8_t channel_raw = ((data >> 54) & 0x03);
channel = channel_[channel_raw];
id = (data >> 40) & 0x3FFF;
battery_low = !((data >> 38) & 1);
humidity = (data >> 24) & 0x7F;
uint16_t temp_raw = ((data >> 9) & 0xF80) | ((data >> 8) & 0x7F);
temp = ((float)(temp_raw)-1000) / 10.0f;
}
}; };
#endif #endif

View File

@ -73,9 +73,6 @@ class FProtoWeatherAcurite5in1 : public FProtoWeatherBase {
if ((decode_count_bit == min_count_bit_for_found) && if ((decode_count_bit == min_count_bit_for_found) &&
ws_protocol_acurite_5n1_check_crc() && ws_protocol_acurite_5n1_check_crc() &&
ws_protocol_acurite_5n1_check_message_type()) { ws_protocol_acurite_5n1_check_message_type()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_acurite_5n1_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -133,17 +130,6 @@ class FProtoWeatherAcurite5in1 : public FProtoWeatherBase {
return false; return false;
} }
} }
void ws_protocol_acurite_5n1_remote_controller() {
uint8_t channell[] = {3, 0, 2, 1};
uint8_t channel_raw = ((data >> 62) & 0x03);
channel = channell[channel_raw];
id = (data >> 48) & 0x3FFF;
battery_low = !((data >> 46) & 1);
humidity = (data >> 8) & 0x7F;
uint16_t temp_raw = ((data >> (24 - 7)) & 0x780) | ((data >> 16) & 0x7F);
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)(temp_raw)-400) / 10.0f);
};
}; };
#endif #endif

View File

@ -48,9 +48,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_acurite_606tx_check()) { ws_protocol_acurite_606tx_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_acurite_606tx_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -83,17 +80,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
uint32_t te_delta = 150; uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 32; uint32_t min_count_bit_for_found = 32;
void ws_protocol_acurite_606tx_remote_controller() {
id = (data >> 24) & 0xFF;
battery_low = (data >> 23) & 1;
channel = WS_NO_CHANNEL;
if (!((data >> 19) & 1)) {
temp = (float)((data >> 8) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 8) & 0x07FF) + 1) / -10.0f;
}
humidity = WS_NO_HUMIDITY;
}
bool ws_protocol_acurite_606tx_check() { bool ws_protocol_acurite_606tx_check() {
if (!decode_data) return false; if (!decode_data) return false;
uint8_t msg[] = { uint8_t msg[] = {

View File

@ -44,9 +44,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
// Found syncPostfix // Found syncPostfix
parser_step = Acurite_609TXCDecoderStepReset; parser_step = Acurite_609TXCDecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_609txc_check()) { if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_609txc_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_acurite_609txc_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -76,19 +73,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
uint32_t te_delta = 150; uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 32; uint32_t min_count_bit_for_found = 32;
void ws_protocol_acurite_609txc_remote_controller() {
id = (data >> 32) & 0xFF;
battery_low = (data >> 31) & 1;
channel = WS_NO_CHANNEL;
// Temperature in Celsius is encoded as a 12 bit integer value
// multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
// negative values are recovered by sign extend from int16_t.
int16_t temp_raw =
(int16_t)(((data >> 12) & 0xf000) | ((data >> 16) << 4));
temp = (temp_raw >> 4) * 0.1f;
humidity = (data >> 8) & 0xff;
}
bool ws_protocol_acurite_609txc_check() { bool ws_protocol_acurite_609txc_check() {
if (!decode_data) return false; if (!decode_data) return false;
uint8_t crc = (uint8_t)(decode_data >> 32) + uint8_t crc = (uint8_t)(decode_data >> 32) +

View File

@ -84,9 +84,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
// Found syncPostfix // Found syncPostfix
parser_step = Acurite_986DecoderStepReset; parser_step = Acurite_986DecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_986_check()) { if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_986_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_acurite_986_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -105,22 +102,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
uint32_t te_delta = 50; uint32_t te_delta = 50;
uint32_t min_count_bit_for_found = 40; uint32_t min_count_bit_for_found = 40;
void ws_protocol_acurite_986_remote_controller() {
int temp;
id = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 24, 8);
id = (id << 8) | FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 16, 8);
battery_low = (data >> 14) & 1;
channel = ((data >> 15) & 1) + 1;
temp = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 32, 8);
if (temp & 0x80) {
temp = -(temp & 0x7F);
}
temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp);
humidity = WS_NO_HUMIDITY;
}
bool ws_protocol_acurite_986_check() { bool ws_protocol_acurite_986_check() {
if (!decode_data) return false; if (!decode_data) return false;
uint8_t msg[] = { uint8_t msg[] = {

View File

@ -42,9 +42,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
if (((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_1) || if (((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_1) ||
((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_2)) { ((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_2)) {
if (ws_protocol_ambient_weather_check_crc()) { if (ws_protocol_ambient_weather_check_crc()) {
data = decode_data;
data_count_bit = min_count_bit_for_found;
ws_protocol_ambient_weather_remote_controller();
if (callback) callback(this); if (callback) callback(this);
decode_data = 0; decode_data = 0;
decode_count_bit = 0; decode_count_bit = 0;
@ -74,14 +71,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64; uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64;
return (crc == (uint8_t)(decode_data & 0xFF)); return (crc == (uint8_t)(decode_data & 0xFF));
} }
void ws_protocol_ambient_weather_remote_controller() {
id = (data >> 32) & 0xFF;
battery_low = (data >> 31) & 1;
channel = ((data >> 28) & 0x07) + 1;
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
humidity = (data >> 8) & 0xFF;
}
}; };
#endif #endif

View File

@ -48,9 +48,6 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_auriol_ahfl_check()) { ws_protocol_auriol_ahfl_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_auriol_ahfl_remote_controller();
if (callback) { if (callback) {
callback(this); callback(this);
} }
@ -88,19 +85,6 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
uint32_t te_delta = 150; uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 42; uint32_t min_count_bit_for_found = 42;
void ws_protocol_auriol_ahfl_remote_controller() {
id = data >> 34;
battery_low = (data >> 33) & 1;
// btn = (data >> 32) & 1;
channel = ((data >> 30) & 0x3) + 1;
if (!((data >> 29) & 1)) {
temp = (float)((data >> 18) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 18) & 0x07FF) + 1) / -10.0f;
}
humidity = (data >> 11) & 0x7F;
}
bool ws_protocol_auriol_ahfl_check() { bool ws_protocol_auriol_ahfl_check() {
uint8_t type = (decode_data >> 6) & 0x0F; uint8_t type = (decode_data >> 6) & 0x0F;
if (type != AURIOL_AHFL_CONST_DATA) { if (type != AURIOL_AHFL_CONST_DATA) {

View File

@ -47,9 +47,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_auriol_th_check()) { ws_protocol_auriol_th_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_auriol_th_remote_controller();
if (callback) callback(this); if (callback) callback(this);
parser_step = auriol_THDecoderStepCheckDuration; parser_step = auriol_THDecoderStepCheckDuration;
} }
@ -87,18 +84,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
uint32_t te_delta = 150; uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 37; uint32_t min_count_bit_for_found = 37;
void ws_protocol_auriol_th_remote_controller() {
id = (data >> 31) & 0xFF;
battery_low = ((data >> 30) & 1);
channel = ((data >> 25) & 0x03) + 1;
if (!((data >> 23) & 1)) {
temp = (float)((data >> 13) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 13) & 0x07FF) + 1) / -10.0f;
}
humidity = (data >> 1) & 0x7F;
}
bool ws_protocol_auriol_th_check() { bool ws_protocol_auriol_th_check() {
uint8_t type = (decode_data >> 8) & 0x0F; uint8_t type = (decode_data >> 8) & 0x0F;

View File

@ -81,9 +81,7 @@ class FProtoWeatherEmosE601x : public FProtoWeatherBase {
} }
if (decode_count_bit == 120) { if (decode_count_bit == 120) {
data_count_bit = decode_count_bit;
if (ws_protocol_emose601x_check()) { if (ws_protocol_emose601x_check()) {
ws_protocol_emose601x_extract_data();
if (callback) callback(this); if (callback) callback(this);
} }
break; break;
@ -127,20 +125,6 @@ class FProtoWeatherEmosE601x : public FProtoWeatherBase {
uint8_t sum = FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 13); uint8_t sum = FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 13);
return (sum == ((decode_data >> 8) & 0xff)); return (sum == ((decode_data >> 8) & 0xff));
} }
void ws_protocol_emose601x_extract_data() {
id = (upper_decode_data >> 24) & 0xff;
battery_low = (decode_data >> 10) & 1;
int16_t temp = (decode_data >> 40) & 0xfff;
/* Handle signed data */
if (temp & 0x800) {
temp |= 0xf000;
}
temp = (float)temp / 10.0;
humidity = (decode_data >> 32) & 0xff;
channel = (decode_data >> 52) & 0x03;
data = (decode_data >> 16);
}
}; };
#endif #endif

View File

@ -50,9 +50,6 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_gt_wt_02_check()) { ws_protocol_gt_wt_02_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_gt_wt_02_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} else if (decode_count_bit == 1) { } else if (decode_count_bit == 1) {
parser_step = GT_WT02DecoderStepSaveDuration; parser_step = GT_WT02DecoderStepSaveDuration;
@ -88,25 +85,6 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
uint32_t te_delta = 150; uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 37; uint32_t min_count_bit_for_found = 37;
void ws_protocol_gt_wt_02_remote_controller() {
id = (data >> 29) & 0xFF;
battery_low = (data >> 28) & 1;
// btn = (data >> 27) & 1;
channel = ((data >> 25) & 0x3) + 1;
if (!((data >> 24) & 1)) {
temp = (float)((data >> 13) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 13) & 0x07FF) + 1) / -10.0f;
}
humidity = (data >> 6) & 0x7F;
if (humidity <= 10) // actually the sensors sends 10 below working range of 20%
humidity = 0;
else if (humidity > 90) // actually the sensors sends 110 above working range of 90%
humidity = 100;
}
bool ws_protocol_gt_wt_02_check() { bool ws_protocol_gt_wt_02_check() {
if (!decode_data) return false; if (!decode_data) return false;
uint8_t sum = (decode_data >> 5) & 0xe; uint8_t sum = (decode_data >> 5) & 0xe;

View File

@ -77,9 +77,6 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_gt_wt_03_check_crc()) { ws_protocol_gt_wt_03_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_gt_wt_03_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -113,27 +110,6 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
uint32_t te_delta = 120; uint32_t te_delta = 120;
uint32_t min_count_bit_for_found = 41; uint32_t min_count_bit_for_found = 41;
void ws_protocol_gt_wt_03_remote_controller() {
id = data >> 33;
humidity = (data >> 25) & 0xFF;
if (humidity <= 10) { // actually the sensors sends 10 below working range of 20%
humidity = 0;
} else if (humidity > 95) { // actually the sensors sends 110 above working range of 90%
humidity = 100;
}
battery_low = (data >> 24) & 1;
// (data >> 23) & 1;
channel = ((data >> 21) & 0x03) + 1;
if (!((data >> 20) & 1)) {
temp = (float)((data >> 9) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 9) & 0x07FF) + 1) / -10.0f;
}
}
bool ws_protocol_gt_wt_03_check_crc() { bool ws_protocol_gt_wt_03_check_crc() {
uint8_t msg[] = { uint8_t msg[] = {
static_cast<uint8_t>(decode_data >> 33), static_cast<uint8_t>(decode_data >> 33),

View File

@ -71,9 +71,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_infactory_check_crc()) { ws_protocol_infactory_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_infactory_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -122,13 +119,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
crc ^= msg[4] >> 4; // last nibble is only XORed crc ^= msg[4] >> 4; // last nibble is only XORed
return (crc == ((decode_data >> 28) & 0x0F)); return (crc == ((decode_data >> 28) & 0x0F));
} }
void ws_protocol_infactory_remote_controller() {
id = data >> 32;
battery_low = (data >> 26) & 1;
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
humidity = (((data >> 8) & 0x0F) * 10) + ((data >> 4) & 0x0F); // BCD, 'A0'=100%rH
channel = data & 0x03;
}
}; };
#endif #endif

View File

@ -78,9 +78,6 @@ class FProtoWeatherKedsum : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_kedsum_th_check_crc()) { ws_protocol_kedsum_th_check_crc()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_kedsum_th_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -127,20 +124,6 @@ class FProtoWeatherKedsum : public FProtoWeatherBase {
crc ^= msg[4] >> 4; // last nibble is only XORed crc ^= msg[4] >> 4; // last nibble is only XORed
return (crc == (msg[4] & 0x0F)); return (crc == (msg[4] & 0x0F));
} }
void ws_protocol_kedsum_th_remote_controller() {
id = data >> 32;
if ((data >> 30) & 0x3) {
battery_low = 0;
} else {
battery_low = 1;
}
channel = ((data >> 28) & 0x3) + 1;
uint16_t temp_raw = ((data >> 16) & 0x0f) << 8 |
((data >> 20) & 0x0f) << 4 | ((data >> 24) & 0x0f);
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)temp_raw - 900.0f) / 10.0f);
humidity = ((data >> 8) & 0x0f) << 4 | ((data >> 12) & 0x0f);
}
}; };
#endif #endif

View File

@ -79,9 +79,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
if ((decode_data & LACROSSE_TX_SUNC_MASK) == if ((decode_data & LACROSSE_TX_SUNC_MASK) ==
LACROSSE_TX_SUNC_PATTERN) { LACROSSE_TX_SUNC_PATTERN) {
if (ws_protocol_lacrosse_tx_check_crc()) { if (ws_protocol_lacrosse_tx_check_crc()) {
data = decode_data;
data_count_bit = LACROSSE_TX_BIT_SIZE;
ws_protocol_lacrosse_tx_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
} }
@ -119,28 +116,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
uint32_t te_delta = 120; uint32_t te_delta = 120;
uint32_t min_count_bit_for_found = 40; uint32_t min_count_bit_for_found = 40;
void ws_protocol_lacrosse_tx_remote_controller() {
uint8_t msg_type = (data >> 32) & 0x0F;
id = (((data >> 28) & 0x0F) << 3) | (((data >> 24) & 0x0F) >> 1);
float msg_value = (float)((data >> 20) & 0x0F) * 10.0f +
(float)((data >> 16) & 0x0F) +
(float)((data >> 12) & 0x0F) * 0.1f;
if (msg_type == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051
temp = msg_value - 50.0f;
humidity = WS_NO_HUMIDITY;
} else if (msg_type == LACROSSE_TX_MSG_TYPE_HUM) {
// ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard
humidity = (uint8_t)msg_value;
} else {
// furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type.");
}
battery_low = WS_NO_BATT;
channel = WS_NO_CHANNEL;
}
bool ws_protocol_lacrosse_tx_check_crc() { bool ws_protocol_lacrosse_tx_check_crc() {
if (!decode_data) return false; if (!decode_data) return false;
uint8_t msg[] = { uint8_t msg[] = {

View File

@ -67,9 +67,9 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
if ((decode_count_bit == min_count_bit_for_found) || if ((decode_count_bit == min_count_bit_for_found) ||
(decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT)) { (decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT)) {
if (ws_protocol_lacrosse_tx141thbv2_check_crc()) { if (ws_protocol_lacrosse_tx141thbv2_check_crc()) {
data = decode_data; if (decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) {
data_count_bit = decode_count_bit; decode_data >>= 1;
ws_protocol_lacrosse_tx141thbv2_remote_controller(); }
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -107,17 +107,7 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4); uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4);
return (crc == (data & 0xFF)); return (crc == (data & 0xFF));
} }
void ws_protocol_lacrosse_tx141thbv2_remote_controller() {
if (data_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) {
data >>= 1;
}
id = data >> 32;
battery_low = (data >> 31) & 1;
// btn = (data >> 30) & 1;
channel = ((data >> 28) & 0x03) + 1;
temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
humidity = (data >> 8) & 0xFF;
}
bool ws_protocol_decoder_lacrosse_tx141thbv2_add_bit(uint32_t te_last, uint32_t te_current) { bool ws_protocol_decoder_lacrosse_tx141thbv2_add_bit(uint32_t te_last, uint32_t te_current) {
bool ret = false; bool ret = false;
if (DURATION_DIFF(te_last + te_current, te_short + te_long) < te_delta * 2) { if (DURATION_DIFF(te_last + te_current, te_short + te_long) < te_delta * 2) {

View File

@ -51,9 +51,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
parser_step = Nexus_THDecoderStepReset; parser_step = Nexus_THDecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) && if ((decode_count_bit == min_count_bit_for_found) &&
ws_protocol_nexus_th_check()) { ws_protocol_nexus_th_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_nexus_th_remote_controller();
if (callback) callback((FProtoWeatherBase*)this); if (callback) callback((FProtoWeatherBase*)this);
parser_step = Nexus_THDecoderStepCheckDuration; parser_step = Nexus_THDecoderStepCheckDuration;
} }
@ -98,23 +95,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
} }
return true; return true;
} }
// fill the base class's variables before calling the callback
void ws_protocol_nexus_th_remote_controller() {
id = (data >> 28) & 0xFF;
battery_low = !((data >> 27) & 1);
channel = ((data >> 24) & 0x03) + 1;
if (!((data >> 23) & 1)) {
temp = (float)((data >> 12) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 12) & 0x07FF) + 1) / -10.0f;
}
humidity = data & 0xFF;
if (humidity > 95)
humidity = 95;
else if (humidity < 20)
humidity = 20;
}
}; };
#endif #endif

View File

@ -107,7 +107,6 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
// waiting for fixed oregon2 data // waiting for fixed oregon2 data
if (decode_count_bit == 32) { if (decode_count_bit == 32) {
data = decode_data; data = decode_data;
data_count_bit = decode_count_bit;
decode_data = 0UL; decode_data = 0UL;
decode_count_bit = 0; decode_count_bit = 0;
@ -117,13 +116,13 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
data = (data & 0x33333333) << 2 | data = (data & 0x33333333) << 2 |
(data & 0xCCCCCCCC) >> 2; (data & 0xCCCCCCCC) >> 2;
ws_oregon2_decode_const_data(); // ws_oregon2_decode_const_data();
var_bits = oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(data)); var_bits = oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(data));
if (!var_bits) { if (!var_bits) {
// sensor is not supported, stop decoding, but showing the decoded fixed part // sensor is not supported, stop decoding, so won't showing the decoded fixed part
parser_step = Oregon2DecoderStepReset; parser_step = Oregon2DecoderStepReset;
if (callback) callback(this); // if (callback) callback(this);
} else { } else {
parser_step = Oregon2DecoderStepVarData; parser_step = Oregon2DecoderStepVarData;
} }
@ -139,8 +138,8 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
(var_data & 0xAAAAAAAA) >> 1; (var_data & 0xAAAAAAAA) >> 1;
var_data = (var_data & 0x33333333) << 2 | var_data = (var_data & 0x33333333) << 2 |
(var_data & 0xCCCCCCCC) >> 2; (var_data & 0xCCCCCCCC) >> 2;
decode_data = var_data;
ws_oregon2_decode_var_data(OREGON2_SENSOR_ID(data), var_data >> OREGON2_CHECKSUM_BITS); // ws_oregon2_decode_var_data(OREGON2_SENSOR_ID(data), var_data >> OREGON2_CHECKSUM_BITS); //a bit stepback, but will work
parser_step = Oregon2DecoderStepReset; parser_step = Oregon2DecoderStepReset;
if (callback) callback(this); if (callback) callback(this);
@ -155,6 +154,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
uint32_t te_long = 1000; uint32_t te_long = 1000;
uint32_t te_delta = 200; uint32_t te_delta = 200;
uint32_t min_count_bit_for_found = 32; uint32_t min_count_bit_for_found = 32;
uint64_t data = 0;
bool have_bit = false; bool have_bit = false;
bool prev_bit = 0; bool prev_bit = 0;
@ -202,19 +202,21 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
return 0; return 0;
} }
} }
void ws_oregon2_decode_const_data() { /* void ws_oregon2_decode_const_data() {
id = OREGON2_SENSOR_ID(data); id = OREGON2_SENSOR_ID(data);
uint8_t ch_bits = (data >> 12) & 0xF; uint8_t ch_bits = (data >> 12) & 0xF;
channel = 1; channel = 1;
while (ch_bits > 1) { while (ch_bits > 1) {
channel++; channel++;
ch_bits >>= 1; ch_bits >>= 1;
} }
battery_low = (data & OREGON2_FLAG_BAT_LOW) ? 1 : 0; battery_low = (data & OREGON2_FLAG_BAT_LOW) ? 1 : 0;
} }
uint16_t bcd_decode_short(uint32_t data) { uint16_t bcd_decode_short(uint32_t data) {
return (data & 0xF) * 10 + ((data >> 4) & 0xF); return (data & 0xF) * 10 + ((data >> 4) & 0xF);
} }
float ws_oregon2_decode_temp(uint32_t data) { float ws_oregon2_decode_temp(uint32_t data) {
int32_t temp_val; int32_t temp_val;
temp_val = bcd_decode_short(data >> 4); temp_val = bcd_decode_short(data >> 4);
@ -241,7 +243,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
default: default:
break; break;
} }
} }*/
}; };
#endif #endif

View File

@ -66,7 +66,6 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
// waiting for fixed oregon3 data // waiting for fixed oregon3 data
if (decode_count_bit == OREGON3_FIXED_PART_BITS) { if (decode_count_bit == OREGON3_FIXED_PART_BITS) {
data = decode_data; data = decode_data;
data_count_bit = decode_count_bit;
decode_data = 0UL; decode_data = 0UL;
decode_count_bit = 0; decode_count_bit = 0;
@ -76,9 +75,8 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
data = (data & 0x33333333) << 2 | data = (data & 0x33333333) << 2 |
(data & 0xCCCCCCCC) >> 2; (data & 0xCCCCCCCC) >> 2;
ws_oregon3_decode_const_data(); // ws_oregon3_decode_const_data(); //todo fix somehow in the future
var_bits = var_bits = oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(data));
oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(data));
if (!var_bits) { if (!var_bits) {
// sensor is not supported, stop decoding // sensor is not supported, stop decoding
@ -98,8 +96,8 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
(var_data & 0xAAAAAAAAAAAAAAAA) >> 1; (var_data & 0xAAAAAAAAAAAAAAAA) >> 1;
var_data = (var_data & 0x3333333333333333) << 2 | var_data = (var_data & 0x3333333333333333) << 2 |
(var_data & 0xCCCCCCCCCCCCCCCC) >> 2; (var_data & 0xCCCCCCCCCCCCCCCC) >> 2;
decode_data = var_data;
ws_oregon3_decode_var_data(OREGON3_SENSOR_ID(data), var_data >> OREGON3_CHECKSUM_BITS); // ws_oregon3_decode_var_data(OREGON3_SENSOR_ID(data), var_data >> OREGON3_CHECKSUM_BITS);
parser_step = Oregon3DecoderStepReset; parser_step = Oregon3DecoderStepReset;
if (callback) callback(this); if (callback) callback(this);
} }
@ -113,6 +111,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
uint32_t te_long = 1100; uint32_t te_long = 1100;
uint32_t te_delta = 300; uint32_t te_delta = 300;
uint32_t min_count_bit_for_found = 32; uint32_t min_count_bit_for_found = 32;
uint64_t data = 0;
bool prev_bit = false; bool prev_bit = false;
uint8_t var_bits{0}; uint8_t var_bits{0};
@ -143,31 +142,31 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
return 0; return 0;
} }
} }
void ws_oregon3_decode_const_data() { /* void ws_oregon3_decode_const_data() {
id = OREGON3_SENSOR_ID(data); id = OREGON3_SENSOR_ID(data);
channel = (data >> 12) & 0xF; channel = (data >> 12) & 0xF;
battery_low = (data & OREGON3_FLAG_BAT_LOW) ? 1 : 0; battery_low = (data & OREGON3_FLAG_BAT_LOW) ? 1 : 0;
} }
uint16_t ws_oregon3_bcd_decode_short(uint32_t data) { uint16_t ws_oregon3_bcd_decode_short(uint32_t data) {
return (data & 0xF) * 10 + ((data >> 4) & 0xF); return (data & 0xF) * 10 + ((data >> 4) & 0xF);
} }
float ws_oregon3_decode_temp(uint32_t data) { float ws_oregon3_decode_temp(uint32_t data) {
int32_t temp_val; int32_t temp_val;
temp_val = ws_oregon3_bcd_decode_short(data >> 4); temp_val = ws_oregon3_bcd_decode_short(data >> 4);
temp_val *= 10; temp_val *= 10;
temp_val += (data >> 12) & 0xF; temp_val += (data >> 12) & 0xF;
if (data & 0xF) temp_val = -temp_val; if (data & 0xF) temp_val = -temp_val;
return (float)temp_val / 10.0; return (float)temp_val / 10.0;
} }
void ws_oregon3_decode_var_data(uint16_t sensor_id, uint32_t data) { void ws_oregon3_decode_var_data(uint16_t sensor_id, uint32_t data) {
switch (sensor_id) { switch (sensor_id) {
case ID_THGR221: case ID_THGR221:
default: default:
humidity = ws_oregon3_bcd_decode_short(data >> 4); humidity = ws_oregon3_bcd_decode_short(data >> 4);
temp = ws_oregon3_decode_temp(data >> 12); temp = ws_oregon3_decode_temp(data >> 12);
break; break;
} }
} }*/
}; };
#endif #endif

View File

@ -102,9 +102,6 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
decode_data = ~decode_data | (1 << 31); decode_data = ~decode_data | (1 << 31);
} }
if (ws_protocol_oregon_v1_check()) { if (ws_protocol_oregon_v1_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_oregon_v1_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
} }
@ -145,22 +142,6 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
crc = (crc & 0xff) + ((crc >> 8) & 0xff); crc = (crc & 0xff) + ((crc >> 8) & 0xff);
return (crc == ((data >> 24) & 0xFF)); return (crc == ((data >> 24) & 0xFF));
} }
void ws_protocol_oregon_v1_remote_controller() {
uint64_t data2 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data, 32);
id = data2 & 0xFF;
channel = ((data2 >> 6) & 0x03) + 1;
float temp_raw =
((data2 >> 8) & 0x0F) * 0.1f + ((data2 >> 12) & 0x0F) + ((data2 >> 16) & 0x0F) * 10.0f;
if (!((data2 >> 21) & 1)) {
temp = temp_raw;
} else {
temp = -temp_raw;
}
battery_low = !((data2 >> 23) & 1ULL);
humidity = WS_NO_HUMIDITY;
}
}; };
#endif #endif

View File

@ -0,0 +1,90 @@
#ifndef __FPROTO_SOLIGHT_TE44_H__
#define __FPROTO_SOLIGHT_TE44_H__
#include "weatherbase.hpp"
typedef enum {
SolightTE44DecoderStepReset = 0,
SolightTE44DecoderStepSaveDuration,
SolightTE44DecoderStepCheckDuration,
} SolightTE44DecoderStep;
class FProtoWeatherSolightTE44 : public FProtoWeatherBase {
public:
FProtoWeatherSolightTE44() {
sensorType = FPW_SolightTE44;
}
void feed(bool level, uint32_t duration) override {
switch (parser_step) {
case SolightTE44DecoderStepReset:
if ((!level) && duration >= te_long) {
parser_step = SolightTE44DecoderStepSaveDuration;
decode_data = 0;
decode_count_bit = 0;
}
break;
case SolightTE44DecoderStepSaveDuration:
if (level) {
te_last = duration;
parser_step = SolightTE44DecoderStepCheckDuration;
} else {
parser_step = SolightTE44DecoderStepReset;
}
break;
case SolightTE44DecoderStepCheckDuration:
if (!level) {
if (DURATION_DIFF(duration, te_short) < te_delta) {
if (decode_count_bit == min_count_bit_for_found &&
ws_protocol_solight_te44_check()) {
if (callback) {
callback(this);
}
}
decode_data = 0;
decode_count_bit = 0;
parser_step = SolightTE44DecoderStepReset;
} else if (
DURATION_DIFF(te_last, te_short) < te_delta) {
if (DURATION_DIFF(duration, te_short * 2) < te_delta) {
subghz_protocol_blocks_add_bit(0);
parser_step = SolightTE44DecoderStepSaveDuration;
} else if (
DURATION_DIFF(duration, te_short * 4) < te_delta) {
subghz_protocol_blocks_add_bit(1);
parser_step = SolightTE44DecoderStepSaveDuration;
} else
parser_step = SolightTE44DecoderStepReset;
} else
parser_step = SolightTE44DecoderStepReset;
} else
parser_step = SolightTE44DecoderStepReset;
break;
}
}
protected:
// timing values
uint32_t te_short = 490;
uint32_t te_long = 3000;
uint32_t te_delta = 150;
uint32_t min_count_bit_for_found = 36;
bool ws_protocol_solight_te44_check() {
if (((decode_data >> 8) & 0x0f) != 0x0f) return false; // const not 1111
// Rubicson CRC check
uint8_t msg_rubicson_crc[] = {
(uint8_t)(decode_data >> 28),
(uint8_t)(decode_data >> 20),
(uint8_t)(decode_data >> 12),
0xf0,
(uint8_t)(((uint8_t)decode_data & 0xf0) | ((uint8_t)decode_data & 0x0f))};
return FProtoGeneral::subghz_protocol_blocks_crc8(msg_rubicson_crc, 5, 0x31, 0x6c) == 0;
}
};
#endif

View File

@ -45,9 +45,6 @@ class FProtoWeatherThermoProTx4 : public FProtoWeatherBase {
parser_step = ThermoPRO_TX4DecoderStepReset; parser_step = ThermoPRO_TX4DecoderStepReset;
if ((decode_count_bit == min_count_bit_for_found) && if ((decode_count_bit == min_count_bit_for_found) &&
ws_protocol_thermopro_tx4_check()) { ws_protocol_thermopro_tx4_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_thermopro_tx4_remote_controller();
if (callback) callback(this); if (callback) callback(this);
parser_step = ThermoPRO_TX4DecoderStepCheckDuration; parser_step = ThermoPRO_TX4DecoderStepCheckDuration;
} }
@ -92,19 +89,6 @@ class FProtoWeatherThermoProTx4 : public FProtoWeatherBase {
return false; return false;
} }
} }
void ws_protocol_thermopro_tx4_remote_controller() {
id = (data >> 25) & 0xFF;
battery_low = (data >> 24) & 1;
// btn = (data >> 23) & 1;
channel = ((data >> 21) & 0x03) + 1;
if (!((data >> 20) & 1)) {
temp = (float)((data >> 9) & 0x07FF) / 10.0f;
} else {
temp = (float)((~(data >> 9) & 0x07FF) + 1) / -10.0f;
}
humidity = (data >> 1) & 0xFF;
}
}; };
#endif #endif

View File

@ -51,12 +51,8 @@ class FProtoWeatherTX8300 : public FProtoWeatherBase {
if (!level) { if (!level) {
if (duration >= ((uint32_t)te_short * 5)) { if (duration >= ((uint32_t)te_short * 5)) {
// Found syncPostfix // Found syncPostfix
if ((decode_count_bit == if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_tx_8300_check_crc()) {
min_count_bit_for_found) && decode_data = package_1;
ws_protocol_tx_8300_check_crc()) {
data = package_1;
data_count_bit = decode_count_bit;
ws_protocol_tx_8300_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
decode_data = 0; decode_data = 0;
@ -118,23 +114,6 @@ class FProtoWeatherTX8300 : public FProtoWeatherBase {
uint8_t crc = (~x & 0xF) << 4 | (~y & 0xF); uint8_t crc = (~x & 0xF) << 4 | (~y & 0xF);
return (crc == (decode_data & 0xFF)); return (crc == (decode_data & 0xFF));
} }
void ws_protocol_tx_8300_remote_controller() {
humidity = (((data >> 28) & 0x0F) * 10) + ((data >> 24) & 0x0F);
if (!((data >> 22) & 0x03))
battery_low = 0;
else
battery_low = 1;
channel = (data >> 20) & 0x03;
id = (data >> 12) & 0x7F;
float temp_raw = ((data >> 8) & 0x0F) * 10.0f + ((data >> 4) & 0x0F) +
(data & 0x0F) * 0.1f;
if (!((data >> 19) & 1)) {
temp = temp_raw;
} else {
temp = -temp_raw;
}
}
}; };
#endif #endif

View File

@ -82,9 +82,6 @@ class FProtoWeatherWendoxW6726 : public FProtoWeatherBase {
if ((decode_count_bit == if ((decode_count_bit ==
min_count_bit_for_found) && min_count_bit_for_found) &&
ws_protocol_wendox_w6726_check()) { ws_protocol_wendox_w6726_check()) {
data = decode_data;
data_count_bit = decode_count_bit;
ws_protocol_wendox_w6726_remote_controller();
if (callback) callback(this); if (callback) callback(this);
} }
@ -131,24 +128,6 @@ class FProtoWeatherWendoxW6726 : public FProtoWeatherBase {
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc4(msg, 4, 0x9, 0xD); uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc4(msg, 4, 0x9, 0xD);
return (crc == (decode_data & 0x0F)); return (crc == (decode_data & 0x0F));
} }
void ws_protocol_wendox_w6726_remote_controller() {
id = (data >> 24) & 0xFF;
battery_low = (data >> 6) & 1;
channel = WS_NO_CHANNEL;
if (((data >> 23) & 1)) {
temp = (float)(((data >> 14) & 0x1FF) + 12) / 10.0f;
} else {
temp = (float)((~(data >> 14) & 0x1FF) + 1 - 12) / -10.0f;
}
if (temp < -50.0f) {
temp = -50.0f;
} else if (temp > 70.0f) {
temp = 70.0f;
}
humidity = WS_NO_HUMIDITY;
}
}; };
#endif #endif

View File

@ -24,11 +24,7 @@ class FProtoWeatherBase {
void setCallback(SubGhzProtocolDecoderBaseRxCallback cb) { callback = cb; } // this is called when there is a hit. void setCallback(SubGhzProtocolDecoderBaseRxCallback cb) { callback = cb; } // this is called when there is a hit.
uint8_t getSensorType() { return sensorType; } uint8_t getSensorType() { return sensorType; }
uint8_t getHumidity() { return humidity; } uint64_t getData() { return decode_data; }
uint8_t getBattLow() { return battery_low; }
uint8_t getChannel() { return channel; }
uint32_t getSensorId() { return id; }
float getTemp() { return temp; }
protected: protected:
// Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy. // Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy.
@ -40,23 +36,16 @@ class FProtoWeatherBase {
// needs to be in this chaotic order, to save flash! // needs to be in this chaotic order, to save flash!
// General weather data holder // General weather data holder
uint8_t sensorType = FPW_Invalid; uint8_t sensorType = FPW_Invalid;
uint8_t humidity = WS_NO_HUMIDITY;
uint8_t battery_low = WS_NO_BATT;
uint8_t channel = WS_NO_CHANNEL;
// inner logic stuff // inner logic stuff
uint8_t parser_step = 0; uint8_t parser_step = 0;
// inner logic stuff, also for flipper compatibility. // inner logic stuff, also for flipper compatibility.
uint16_t header_count = 0; uint16_t header_count = 0;
// General weather data holder
float temp = WS_NO_TEMPERATURE;
uint32_t id = WS_NO_ID;
// inner logic stuff, // inner logic stuff,
uint32_t te_last = 0; uint32_t te_last = 0;
uint32_t data_count_bit = 0;
uint32_t decode_count_bit = 0; uint32_t decode_count_bit = 0;
uint64_t decode_data = 0; uint64_t decode_data = 0;
uint64_t data = 0;
SubGhzProtocolDecoderBaseRxCallback callback = NULL; SubGhzProtocolDecoderBaseRxCallback callback = NULL;
}; };

View File

@ -28,6 +28,7 @@ So include here the .hpp, and add a new element to the protos vector in the cons
#include "w-kedsum.hpp" #include "w-kedsum.hpp"
#include "w-acurite5in1.hpp" #include "w-acurite5in1.hpp"
#include "w-emose601x.hpp" #include "w-emose601x.hpp"
#include "w-solight_te44.hpp"
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -64,6 +65,7 @@ class WeatherProtos : public FProtoListGeneral {
protos[FPW_KEDSUM] = new FProtoWeatherKedsum(); protos[FPW_KEDSUM] = new FProtoWeatherKedsum();
protos[FPW_Acurite5in1] = new FProtoWeatherAcurite5in1(); protos[FPW_Acurite5in1] = new FProtoWeatherAcurite5in1();
protos[FPW_EmosE601x] = new FProtoWeatherEmosE601x(); protos[FPW_EmosE601x] = new FProtoWeatherEmosE601x();
protos[FPW_SolightTE44] = new FProtoWeatherSolightTE44();
// set callback for them // set callback for them
for (uint8_t i = 0; i < FPW_COUNT; ++i) { for (uint8_t i = 0; i < FPW_COUNT; ++i) {
@ -81,9 +83,7 @@ class WeatherProtos : public FProtoListGeneral {
}; };
static void callbackTarget(FProtoWeatherBase* instance) { static void callbackTarget(FProtoWeatherBase* instance) {
WeatherDataMessage packet_message{instance->getSensorType(), instance->getSensorId(), WeatherDataMessage packet_message{instance->getSensorType(), instance->getData()};
instance->getTemp(), instance->getHumidity(), instance->getBattLow(),
instance->getChannel()};
shared_memory.application_queue.push(packet_message); shared_memory.application_queue.push(packet_message);
} }

View File

@ -38,6 +38,7 @@ enum FPROTO_WEATHER_SENSOR {
FPW_KEDSUM = 20, FPW_KEDSUM = 20,
FPW_Acurite5in1 = 21, FPW_Acurite5in1 = 21,
FPW_EmosE601x = 22, FPW_EmosE601x = 22,
FPW_SolightTE44 = 23,
FPW_COUNT // this must be the last FPW_COUNT // this must be the last
}; };

View File

@ -1265,25 +1265,13 @@ class WeatherDataMessage : public Message {
public: public:
constexpr WeatherDataMessage( constexpr WeatherDataMessage(
uint8_t sensorType = 0, uint8_t sensorType = 0,
uint32_t id = 0xFFFFFFFF, uint64_t decode_data = 0xFFFFFFFF)
float temp = -273.0f,
uint8_t humidity = 0xFF,
uint8_t battery_low = 0xFF,
uint8_t channel = 0xFF)
: Message{ID::WeatherData}, : Message{ID::WeatherData},
sensorType{sensorType}, sensorType{sensorType},
id{id}, decode_data{decode_data} {
temp{temp},
humidity{humidity},
battery_low{battery_low},
channel{channel} {
} }
uint8_t sensorType = 0; uint8_t sensorType = 0;
uint32_t id = 0xFFFFFFFF; uint64_t decode_data = 0;
float temp = -273.0f;
uint8_t humidity = 0xFF;
uint8_t battery_low = 0xFF;
uint8_t channel = 0xFF;
}; };
class SubGhzDDataMessage : public Message { class SubGhzDDataMessage : public Message {