mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-04 23:45:26 +00:00
Weather station update (#2209)
* Acurite609txc fix * Added Kedsum * Add auriol 5in1 * prev was: FPW_Acurite5in1, this is EmosE601x * Remove BTN from weather Saved flash space by creating chaos. Fix EmosE601
This commit is contained in:
parent
2fdd531fe7
commit
5d9428e568
@ -203,7 +203,12 @@ const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) {
|
||||
return "Wendox W6726";
|
||||
case FPW_Acurite986:
|
||||
return "Acurite986";
|
||||
|
||||
case FPW_KEDSUM:
|
||||
return "Kedsum";
|
||||
case FPW_Acurite5in1:
|
||||
return "Acurite5in1";
|
||||
case FPW_EmosE601x:
|
||||
return "EmosE601x";
|
||||
case FPW_Invalid:
|
||||
default:
|
||||
return "Unknown";
|
||||
|
@ -148,7 +148,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
|
||||
humidity = (data >> 24) & 0x7F;
|
||||
uint16_t temp_raw = ((data >> 9) & 0xF80) | ((data >> 8) & 0x7F);
|
||||
temp = ((float)(temp_raw)-1000) / 10.0f;
|
||||
btn = WS_NO_BTN;
|
||||
}
|
||||
};
|
||||
|
||||
|
149
firmware/baseband/fprotos/w-acurite5in1.hpp
Normal file
149
firmware/baseband/fprotos/w-acurite5in1.hpp
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
#ifndef __FPROTO_Acurite_5in1_H__
|
||||
#define __FPROTO_Acurite_5in1_H__
|
||||
|
||||
#include "weatherbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
Acurite_5n1DecoderStepReset = 0,
|
||||
Acurite_5n1DecoderStepCheckPreambule,
|
||||
Acurite_5n1DecoderStepSaveDuration,
|
||||
Acurite_5n1DecoderStepCheckDuration,
|
||||
} Acurite_5n1DecoderStep;
|
||||
|
||||
class FProtoWeatherAcurite5in1 : public FProtoWeatherBase {
|
||||
public:
|
||||
FProtoWeatherAcurite5in1() {
|
||||
sensorType = FPW_Acurite5in1;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case Acurite_5n1DecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 3) < te_delta * 2)) {
|
||||
parser_step = Acurite_5n1DecoderStepCheckPreambule;
|
||||
te_last = duration;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case Acurite_5n1DecoderStepCheckPreambule:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
if ((DURATION_DIFF(te_last, te_short * 3) < te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short * 3) < te_delta * 2)) {
|
||||
// Found preambule
|
||||
header_count++;
|
||||
} else if ((header_count > 2) && (header_count < 5)) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Acurite_5n1DecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = Acurite_5n1DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Acurite_5n1DecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = Acurite_5n1DecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case Acurite_5n1DecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 5)) {
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
ws_protocol_acurite_5n1_check_crc() &&
|
||||
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);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
break;
|
||||
} else if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Acurite_5n1DecoderStepSaveDuration;
|
||||
} 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 = Acurite_5n1DecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = Acurite_5n1DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t te_short = 200;
|
||||
uint32_t te_long = 400;
|
||||
uint32_t te_delta = 90;
|
||||
uint32_t min_count_bit_for_found = 64;
|
||||
|
||||
bool ws_protocol_acurite_5n1_check_message_type() {
|
||||
if (((decode_data >> 40) & 0x3F) == 0x38) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ws_protocol_acurite_5n1_check_crc() {
|
||||
uint8_t msg[] = {
|
||||
(uint8_t)(decode_data >> 56),
|
||||
(uint8_t)(decode_data >> 48),
|
||||
(uint8_t)(decode_data >> 40),
|
||||
(uint8_t)(decode_data >> 32),
|
||||
(uint8_t)(decode_data >> 24),
|
||||
(uint8_t)(decode_data >> 16),
|
||||
(uint8_t)(decode_data >> 8)};
|
||||
|
||||
if ((FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 7) ==
|
||||
(uint8_t)(decode_data & 0xFF)) &&
|
||||
(!FProtoGeneral::subghz_protocol_blocks_parity_bytes(&msg[2], 5))) {
|
||||
return true;
|
||||
} else {
|
||||
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
|
@ -92,7 +92,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
|
||||
} else {
|
||||
temp = (float)((~(data >> 8) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
btn = WS_NO_BTN;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
bool ws_protocol_acurite_606tx_check() {
|
||||
|
@ -39,16 +39,11 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
|
||||
case Acurite_609TXCDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(te_last, te_short) <
|
||||
te_delta) {
|
||||
if ((DURATION_DIFF(duration, te_short) <
|
||||
te_delta) ||
|
||||
(duration > te_long * 3)) {
|
||||
if (DURATION_DIFF(te_last, te_short) < te_delta) {
|
||||
if ((DURATION_DIFF(duration, te_short) < te_delta) || (duration > te_long * 3)) {
|
||||
// Found syncPostfix
|
||||
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();
|
||||
@ -56,14 +51,10 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long) <
|
||||
te_delta * 2) {
|
||||
} else if (DURATION_DIFF(duration, te_long) < te_delta * 2) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Acurite_609TXCDecoderStepSaveDuration;
|
||||
} else if (
|
||||
DURATION_DIFF(duration, te_long * 2) <
|
||||
te_delta * 4) {
|
||||
} else if (DURATION_DIFF(duration, te_long * 2) < te_delta * 4) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = Acurite_609TXCDecoderStepSaveDuration;
|
||||
} else {
|
||||
@ -81,7 +72,7 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
|
||||
protected:
|
||||
uint32_t te_short = 500;
|
||||
uint32_t te_long = 2000;
|
||||
uint32_t te_long = 1000;
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
|
||||
@ -97,7 +88,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
(int16_t)(((data >> 12) & 0xf000) | ((data >> 16) << 4));
|
||||
temp = (temp_raw >> 4) * 0.1f;
|
||||
humidity = (data >> 8) & 0xff;
|
||||
btn = WS_NO_BTN;
|
||||
}
|
||||
bool ws_protocol_acurite_609txc_check() {
|
||||
if (!decode_data) return false;
|
||||
|
@ -118,7 +118,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
|
||||
temp = -(temp & 0x7F);
|
||||
}
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp);
|
||||
btn = WS_NO_BTN;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
||||
uint32_t te_long = 1000;
|
||||
uint32_t te_delta = 120;
|
||||
uint32_t min_count_bit_for_found = 48;
|
||||
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
bool ws_protocol_ambient_weather_check_crc() {
|
||||
uint8_t msg[] = {
|
||||
static_cast<uint8_t>(decode_data >> 40),
|
||||
@ -81,7 +81,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
||||
channel = ((data >> 28) & 0x07) + 1;
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
humidity = (data >> 8) & 0xFF;
|
||||
btn = WS_NO_BTN;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
|
||||
void ws_protocol_auriol_ahfl_remote_controller() {
|
||||
id = data >> 34;
|
||||
battery_low = (data >> 33) & 1;
|
||||
btn = (data >> 32) & 1;
|
||||
// btn = (data >> 32) & 1;
|
||||
channel = ((data >> 30) & 0x3) + 1;
|
||||
if (!((data >> 29) & 1)) {
|
||||
temp = (float)((data >> 18) & 0x07FF) / 10.0f;
|
||||
|
@ -91,7 +91,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
|
||||
id = (data >> 31) & 0xFF;
|
||||
battery_low = ((data >> 30) & 1);
|
||||
channel = ((data >> 25) & 0x03) + 1;
|
||||
btn = WS_NO_BTN;
|
||||
if (!((data >> 23) & 1)) {
|
||||
temp = (float)((data >> 13) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
|
146
firmware/baseband/fprotos/w-emose601x.hpp
Normal file
146
firmware/baseband/fprotos/w-emose601x.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
#ifndef __FPROTO_EmosE601x_H__
|
||||
#define __FPROTO_EmosE601x_H__
|
||||
|
||||
#include "weatherbase.hpp"
|
||||
|
||||
#define EmosE601xMAGIC_HEADER 0xaaa583
|
||||
|
||||
typedef enum {
|
||||
EmosE601xDecoderStepReset = 0,
|
||||
EmosE601xDecoderStepCheckPreamble,
|
||||
EmosE601xDecoderStepSaveDuration,
|
||||
EmosE601xDecoderStepCheckDuration,
|
||||
} EmosE601xDecoderStep;
|
||||
|
||||
class FProtoWeatherEmosE601x : public FProtoWeatherBase {
|
||||
public:
|
||||
FProtoWeatherEmosE601x() {
|
||||
sensorType = FPW_EmosE601x;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case EmosE601xDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short * 7) <
|
||||
te_delta * 2)) {
|
||||
parser_step = EmosE601xDecoderStepCheckPreamble;
|
||||
te_last = duration;
|
||||
}
|
||||
break;
|
||||
|
||||
case EmosE601xDecoderStepCheckPreamble:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
if ((DURATION_DIFF(te_last, te_short * 7) <
|
||||
te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, te_short) <
|
||||
te_delta)) {
|
||||
// Found preamble
|
||||
parser_step = EmosE601xDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
} else {
|
||||
parser_step = EmosE601xDecoderStepReset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EmosE601xDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = EmosE601xDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = EmosE601xDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case EmosE601xDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_to_128_bit(0, &upper_decode_data);
|
||||
parser_step = EmosE601xDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_to_128_bit(1, &upper_decode_data);
|
||||
parser_step = EmosE601xDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = EmosE601xDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bail out if the header doesn't match */
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
if (decode_data != EmosE601xMAGIC_HEADER) {
|
||||
parser_step = EmosE601xDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (decode_count_bit == 120) {
|
||||
data_count_bit = decode_count_bit;
|
||||
if (ws_protocol_emose601x_check()) {
|
||||
ws_protocol_emose601x_extract_data();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
parser_step = EmosE601xDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t te_short = 260;
|
||||
uint32_t te_long = 800;
|
||||
uint32_t te_delta = 100;
|
||||
uint32_t min_count_bit_for_found = 24;
|
||||
|
||||
uint64_t upper_decode_data = 0;
|
||||
void subghz_protocol_blocks_add_to_128_bit(uint8_t bit, uint64_t* head_64_bit) {
|
||||
if (++decode_count_bit > 64) {
|
||||
(*head_64_bit) = ((*head_64_bit) << 1) | (decode_data >> 63);
|
||||
}
|
||||
decode_data = decode_data << 1 | bit;
|
||||
}
|
||||
bool ws_protocol_emose601x_check() {
|
||||
uint8_t msg[] = {
|
||||
static_cast<uint8_t>(upper_decode_data >> 48),
|
||||
static_cast<uint8_t>(upper_decode_data >> 40),
|
||||
static_cast<uint8_t>(upper_decode_data >> 32),
|
||||
static_cast<uint8_t>(upper_decode_data >> 24),
|
||||
static_cast<uint8_t>(upper_decode_data >> 16),
|
||||
static_cast<uint8_t>(upper_decode_data >> 8),
|
||||
static_cast<uint8_t>(upper_decode_data),
|
||||
static_cast<uint8_t>(decode_data >> 56),
|
||||
static_cast<uint8_t>(decode_data >> 48),
|
||||
static_cast<uint8_t>(decode_data >> 40),
|
||||
static_cast<uint8_t>(decode_data >> 32),
|
||||
static_cast<uint8_t>(decode_data >> 24),
|
||||
static_cast<uint8_t>(decode_data >> 16)};
|
||||
|
||||
uint8_t sum = FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 13);
|
||||
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
|
@ -91,7 +91,7 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
|
||||
void ws_protocol_gt_wt_02_remote_controller() {
|
||||
id = (data >> 29) & 0xFF;
|
||||
battery_low = (data >> 28) & 1;
|
||||
btn = (data >> 27) & 1;
|
||||
// btn = (data >> 27) & 1;
|
||||
channel = ((data >> 25) & 0x3) + 1;
|
||||
|
||||
if (!((data >> 24) & 1)) {
|
||||
|
@ -124,7 +124,7 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
|
||||
}
|
||||
|
||||
battery_low = (data >> 24) & 1;
|
||||
btn = (data >> 23) & 1;
|
||||
// (data >> 23) & 1;
|
||||
channel = ((data >> 21) & 0x03) + 1;
|
||||
|
||||
if (!((data >> 20) & 1)) {
|
||||
|
@ -125,7 +125,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
|
||||
void ws_protocol_infactory_remote_controller() {
|
||||
id = data >> 32;
|
||||
battery_low = (data >> 26) & 1;
|
||||
btn = WS_NO_BTN;
|
||||
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;
|
||||
|
146
firmware/baseband/fprotos/w-kedsum.hpp
Normal file
146
firmware/baseband/fprotos/w-kedsum.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
#ifndef __FPROTO_Kedsum_H__
|
||||
#define __FPROTO_Kedsum_H__
|
||||
|
||||
#include "weatherbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
KedsumTHDecoderStepReset = 0,
|
||||
KedsumTHDecoderStepCheckPreambule,
|
||||
KedsumTHDecoderStepSaveDuration,
|
||||
KedsumTHDecoderStepCheckDuration,
|
||||
} KedsumTHDecoderStep;
|
||||
|
||||
class FProtoWeatherKedsum : public FProtoWeatherBase {
|
||||
public:
|
||||
FProtoWeatherKedsum() {
|
||||
sensorType = FPW_KEDSUM;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case KedsumTHDecoderStepReset:
|
||||
if ((level) && (DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
parser_step = KedsumTHDecoderStepCheckPreambule;
|
||||
te_last = duration;
|
||||
header_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case KedsumTHDecoderStepCheckPreambule:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
} else {
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 4) < te_delta * 4)) {
|
||||
// Found preambule
|
||||
header_count++;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(duration < (te_long * 2 + te_delta * 2))) {
|
||||
// Found syncPrefix
|
||||
if (header_count > 0) {
|
||||
parser_step = KedsumTHDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = KedsumTHDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 2) < te_delta * 4)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = KedsumTHDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KedsumTHDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = KedsumTHDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case KedsumTHDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
if (DURATION_DIFF(duration, te_long * 4) < te_delta * 4) {
|
||||
// Found syncPostfix
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
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);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
break;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta * 2)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = KedsumTHDecoderStepSaveDuration;
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) <
|
||||
te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 2) <
|
||||
te_delta * 4)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = KedsumTHDecoderStepSaveDuration;
|
||||
} else {
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = KedsumTHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t te_short = 500;
|
||||
uint32_t te_long = 2000;
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 42;
|
||||
|
||||
bool ws_protocol_kedsum_th_check_crc() {
|
||||
uint8_t msg[] = {
|
||||
static_cast<uint8_t>(decode_data >> 32),
|
||||
static_cast<uint8_t>(decode_data >> 24),
|
||||
static_cast<uint8_t>(decode_data >> 16),
|
||||
static_cast<uint8_t>(decode_data >> 8),
|
||||
static_cast<uint8_t>(decode_data)};
|
||||
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_crc4(msg, 4, 0x03, 0); // CRC-4 poly 0x3 init 0x0 xor last 4 bits
|
||||
crc ^= msg[4] >> 4; // last nibble is only XORed
|
||||
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
|
@ -137,7 +137,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
|
||||
// furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type.");
|
||||
}
|
||||
|
||||
btn = WS_NO_BTN;
|
||||
battery_low = WS_NO_BATT;
|
||||
channel = WS_NO_CHANNEL;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
|
||||
}
|
||||
id = data >> 32;
|
||||
battery_low = (data >> 31) & 1;
|
||||
btn = (data >> 30) & 1;
|
||||
// btn = (data >> 30) & 1;
|
||||
channel = ((data >> 28) & 0x03) + 1;
|
||||
temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
|
||||
humidity = (data >> 8) & 0xFF;
|
||||
|
@ -104,7 +104,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
|
||||
id = (data >> 28) & 0xFF;
|
||||
battery_low = !((data >> 27) & 1);
|
||||
channel = ((data >> 24) & 0x03) + 1;
|
||||
btn = WS_NO_BTN;
|
||||
if (!((data >> 23) & 1)) {
|
||||
temp = (float)((data >> 12) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
|
@ -160,7 +160,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
bool prev_bit = 0;
|
||||
uint8_t var_bits{0};
|
||||
uint32_t var_data{0};
|
||||
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
void ws_protocol_decoder_oregon2_reset() {
|
||||
parser_step = Oregon2DecoderStepReset;
|
||||
decode_data = 0UL;
|
||||
|
@ -117,7 +117,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
bool prev_bit = false;
|
||||
uint8_t var_bits{0};
|
||||
uint64_t var_data{0};
|
||||
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) {
|
||||
bool is_long = false;
|
||||
|
||||
|
@ -137,7 +137,7 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
|
||||
uint8_t first_bit{0};
|
||||
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
bool ws_protocol_oregon_v1_check() {
|
||||
if (!decode_data) return false;
|
||||
uint64_t data = FProtoGeneral::subghz_protocol_blocks_reverse_key(decode_data, 32);
|
||||
@ -159,7 +159,6 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
|
||||
temp = -temp_raw;
|
||||
}
|
||||
battery_low = !((data2 >> 23) & 1ULL);
|
||||
btn = WS_NO_BTN;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
};
|
||||
|
@ -96,7 +96,7 @@ class FProtoWeatherThermoProTx4 : public FProtoWeatherBase {
|
||||
void ws_protocol_thermopro_tx4_remote_controller() {
|
||||
id = (data >> 25) & 0xFF;
|
||||
battery_low = (data >> 24) & 1;
|
||||
btn = (data >> 23) & 1;
|
||||
// btn = (data >> 23) & 1;
|
||||
channel = ((data >> 21) & 0x03) + 1;
|
||||
if (!((data >> 20) & 1)) {
|
||||
temp = (float)((data >> 9) & 0x07FF) / 10.0f;
|
||||
|
@ -120,7 +120,6 @@ class FProtoWeatherTX8300 : public FProtoWeatherBase {
|
||||
}
|
||||
void ws_protocol_tx_8300_remote_controller() {
|
||||
humidity = (((data >> 28) & 0x0F) * 10) + ((data >> 24) & 0x0F);
|
||||
btn = WS_NO_BTN;
|
||||
if (!((data >> 22) & 0x03))
|
||||
battery_low = 0;
|
||||
else
|
||||
|
@ -147,8 +147,6 @@ class FProtoWeatherWendoxW6726 : public FProtoWeatherBase {
|
||||
} else if (temp > 70.0f) {
|
||||
temp = 70.0f;
|
||||
}
|
||||
|
||||
btn = WS_NO_BTN;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
};
|
||||
|
@ -24,12 +24,11 @@ class FProtoWeatherBase {
|
||||
void setCallback(SubGhzProtocolDecoderBaseRxCallback cb) { callback = cb; } // this is called when there is a hit.
|
||||
|
||||
uint8_t getSensorType() { return sensorType; }
|
||||
uint32_t getSensorId() { return id; }
|
||||
float getTemp() { return temp; }
|
||||
uint8_t getHumidity() { return humidity; }
|
||||
uint8_t getBattLow() { return battery_low; }
|
||||
uint8_t getChannel() { return channel; }
|
||||
uint8_t getButton() { return btn; }
|
||||
uint32_t getSensorId() { return id; }
|
||||
float getTemp() { return temp; }
|
||||
|
||||
protected:
|
||||
// Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy.
|
||||
@ -38,25 +37,27 @@ class FProtoWeatherBase {
|
||||
decode_count_bit++;
|
||||
}
|
||||
|
||||
// General weather data holder
|
||||
// needs to be in this chaotic order, to save flash!
|
||||
// General weather data holder
|
||||
uint8_t sensorType = FPW_Invalid;
|
||||
uint32_t id = WS_NO_ID;
|
||||
float temp = WS_NO_TEMPERATURE;
|
||||
uint8_t humidity = WS_NO_HUMIDITY;
|
||||
uint8_t battery_low = WS_NO_BATT;
|
||||
uint8_t channel = WS_NO_CHANNEL;
|
||||
uint8_t btn = WS_NO_BTN;
|
||||
|
||||
// inner logic stuff, also for flipper compatibility.
|
||||
SubGhzProtocolDecoderBaseRxCallback callback = NULL;
|
||||
uint16_t header_count = 0;
|
||||
// inner logic stuff
|
||||
uint8_t parser_step = 0;
|
||||
// inner logic stuff, also for flipper compatibility.
|
||||
uint16_t header_count = 0;
|
||||
// General weather data holder
|
||||
float temp = WS_NO_TEMPERATURE;
|
||||
uint32_t id = WS_NO_ID;
|
||||
// inner logic stuff,
|
||||
|
||||
uint32_t te_last = 0;
|
||||
uint64_t data = 0;
|
||||
uint32_t data_count_bit = 0;
|
||||
uint64_t decode_data = 0;
|
||||
uint32_t decode_count_bit = 0;
|
||||
ManchesterState manchester_saved_state = ManchesterStateMid1;
|
||||
uint64_t decode_data = 0;
|
||||
uint64_t data = 0;
|
||||
SubGhzProtocolDecoderBaseRxCallback callback = NULL;
|
||||
};
|
||||
|
||||
#endif
|
@ -25,6 +25,10 @@ So include here the .hpp, and add a new element to the protos vector in the cons
|
||||
#include "w-tx8300.hpp"
|
||||
#include "w-wendox-w6726.hpp"
|
||||
#include "w-acurite986.hpp"
|
||||
#include "w-kedsum.hpp"
|
||||
#include "w-acurite5in1.hpp"
|
||||
#include "w-emose601x.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "portapack_shared_memory.hpp"
|
||||
@ -55,6 +59,9 @@ class WeatherProtos : public FProtoListGeneral {
|
||||
protos.push_back(std::make_unique<FProtoWeatherTX8300>()); // 17
|
||||
protos.push_back(std::make_unique<FProtoWeatherWendoxW6726>()); // 18
|
||||
protos.push_back(std::make_unique<FProtoWeatherAcurite986>()); // 19
|
||||
protos.push_back(std::make_unique<FProtoWeatherKedsum>()); // 20
|
||||
protos.push_back(std::make_unique<FProtoWeatherAcurite5in1>()); // 21
|
||||
protos.push_back(std::make_unique<FProtoWeatherEmosE601x>()); // 22
|
||||
|
||||
// set callback for them
|
||||
for (const auto& obj : protos) {
|
||||
@ -65,7 +72,7 @@ class WeatherProtos : public FProtoListGeneral {
|
||||
static void callbackTarget(FProtoWeatherBase* instance) {
|
||||
WeatherDataMessage packet_message{instance->getSensorType(), instance->getSensorId(),
|
||||
instance->getTemp(), instance->getHumidity(), instance->getBattLow(),
|
||||
instance->getChannel(), instance->getButton()};
|
||||
instance->getChannel()};
|
||||
shared_memory.application_queue.push(packet_message);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ Also it must have a switch-case element in the getWeatherSensorTypeName() functi
|
||||
#define WS_NO_BATT 0xFF
|
||||
#define WS_NO_HUMIDITY 0xFF
|
||||
#define WS_NO_CHANNEL 0xFF
|
||||
#define WS_NO_BTN 0xFF
|
||||
// #define WS_NO_BTN 0xFF
|
||||
#define WS_NO_TEMPERATURE -273.0f
|
||||
|
||||
enum FPROTO_WEATHER_SENSOR {
|
||||
@ -34,7 +34,11 @@ enum FPROTO_WEATHER_SENSOR {
|
||||
FPW_THERMOPROTX4 = 16,
|
||||
FPW_TX_8300 = 17,
|
||||
FPW_WENDOX_W6726 = 18,
|
||||
FPW_Acurite986 = 19
|
||||
FPW_Acurite986 = 19,
|
||||
FPW_KEDSUM = 20,
|
||||
FPW_Acurite5in1 = 21,
|
||||
FPW_EmosE601x = 22
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1267,16 +1267,14 @@ class WeatherDataMessage : public Message {
|
||||
float temp = -273.0f,
|
||||
uint8_t humidity = 0xFF,
|
||||
uint8_t battery_low = 0xFF,
|
||||
uint8_t channel = 0xFF,
|
||||
uint8_t btn = 0xFF)
|
||||
uint8_t channel = 0xFF)
|
||||
: Message{ID::WeatherData},
|
||||
sensorType{sensorType},
|
||||
id{id},
|
||||
temp{temp},
|
||||
humidity{humidity},
|
||||
battery_low{battery_low},
|
||||
channel{channel},
|
||||
btn{btn} {
|
||||
channel{channel} {
|
||||
}
|
||||
uint8_t sensorType = 0;
|
||||
uint32_t id = 0xFFFFFFFF;
|
||||
@ -1284,7 +1282,6 @@ class WeatherDataMessage : public Message {
|
||||
uint8_t humidity = 0xFF;
|
||||
uint8_t battery_low = 0xFF;
|
||||
uint8_t channel = 0xFF;
|
||||
uint8_t btn = 0xFF;
|
||||
};
|
||||
|
||||
class SubGhzDDataMessage : public Message {
|
||||
|
Loading…
Reference in New Issue
Block a user