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:
Totoo 2024-07-24 11:53:09 +02:00 committed by GitHub
parent 2fdd531fe7
commit 5d9428e568
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 493 additions and 60 deletions

View File

@ -203,7 +203,12 @@ const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) {
return "Wendox W6726"; return "Wendox W6726";
case FPW_Acurite986: case FPW_Acurite986:
return "Acurite986"; return "Acurite986";
case FPW_KEDSUM:
return "Kedsum";
case FPW_Acurite5in1:
return "Acurite5in1";
case FPW_EmosE601x:
return "EmosE601x";
case FPW_Invalid: case FPW_Invalid:
default: default:
return "Unknown"; return "Unknown";

View File

@ -148,7 +148,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
humidity = (data >> 24) & 0x7F; humidity = (data >> 24) & 0x7F;
uint16_t temp_raw = ((data >> 9) & 0xF80) | ((data >> 8) & 0x7F); uint16_t temp_raw = ((data >> 9) & 0xF80) | ((data >> 8) & 0x7F);
temp = ((float)(temp_raw)-1000) / 10.0f; temp = ((float)(temp_raw)-1000) / 10.0f;
btn = WS_NO_BTN;
} }
}; };

View 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

View File

@ -92,7 +92,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
} else { } else {
temp = (float)((~(data >> 8) & 0x07FF) + 1) / -10.0f; temp = (float)((~(data >> 8) & 0x07FF) + 1) / -10.0f;
} }
btn = WS_NO_BTN;
humidity = WS_NO_HUMIDITY; humidity = WS_NO_HUMIDITY;
} }
bool ws_protocol_acurite_606tx_check() { bool ws_protocol_acurite_606tx_check() {

View File

@ -39,16 +39,11 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
case Acurite_609TXCDecoderStepCheckDuration: case Acurite_609TXCDecoderStepCheckDuration:
if (!level) { if (!level) {
if (DURATION_DIFF(te_last, te_short) < if (DURATION_DIFF(te_last, te_short) < te_delta) {
te_delta) { if ((DURATION_DIFF(duration, te_short) < te_delta) || (duration > te_long * 3)) {
if ((DURATION_DIFF(duration, te_short) <
te_delta) ||
(duration > te_long * 3)) {
// Found syncPostfix // Found syncPostfix
parser_step = Acurite_609TXCDecoderStepReset; parser_step = Acurite_609TXCDecoderStepReset;
if ((decode_count_bit == if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_609txc_check()) {
min_count_bit_for_found) &&
ws_protocol_acurite_609txc_check()) {
data = decode_data; data = decode_data;
data_count_bit = decode_count_bit; data_count_bit = decode_count_bit;
ws_protocol_acurite_609txc_remote_controller(); ws_protocol_acurite_609txc_remote_controller();
@ -56,14 +51,10 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
} }
decode_data = 0; decode_data = 0;
decode_count_bit = 0; decode_count_bit = 0;
} else if ( } else if (DURATION_DIFF(duration, te_long) < te_delta * 2) {
DURATION_DIFF(duration, te_long) <
te_delta * 2) {
subghz_protocol_blocks_add_bit(0); subghz_protocol_blocks_add_bit(0);
parser_step = Acurite_609TXCDecoderStepSaveDuration; parser_step = Acurite_609TXCDecoderStepSaveDuration;
} else if ( } else if (DURATION_DIFF(duration, te_long * 2) < te_delta * 4) {
DURATION_DIFF(duration, te_long * 2) <
te_delta * 4) {
subghz_protocol_blocks_add_bit(1); subghz_protocol_blocks_add_bit(1);
parser_step = Acurite_609TXCDecoderStepSaveDuration; parser_step = Acurite_609TXCDecoderStepSaveDuration;
} else { } else {
@ -81,7 +72,7 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
protected: protected:
uint32_t te_short = 500; uint32_t te_short = 500;
uint32_t te_long = 2000; uint32_t te_long = 1000;
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;
@ -97,7 +88,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
(int16_t)(((data >> 12) & 0xf000) | ((data >> 16) << 4)); (int16_t)(((data >> 12) & 0xf000) | ((data >> 16) << 4));
temp = (temp_raw >> 4) * 0.1f; temp = (temp_raw >> 4) * 0.1f;
humidity = (data >> 8) & 0xff; humidity = (data >> 8) & 0xff;
btn = WS_NO_BTN;
} }
bool ws_protocol_acurite_609txc_check() { bool ws_protocol_acurite_609txc_check() {
if (!decode_data) return false; if (!decode_data) return false;

View File

@ -118,7 +118,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
temp = -(temp & 0x7F); temp = -(temp & 0x7F);
} }
temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp); temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp);
btn = WS_NO_BTN;
humidity = WS_NO_HUMIDITY; humidity = WS_NO_HUMIDITY;
} }

View File

@ -62,7 +62,7 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
uint32_t te_long = 1000; uint32_t te_long = 1000;
uint32_t te_delta = 120; uint32_t te_delta = 120;
uint32_t min_count_bit_for_found = 48; uint32_t min_count_bit_for_found = 48;
ManchesterState manchester_saved_state = ManchesterStateMid1;
bool ws_protocol_ambient_weather_check_crc() { bool ws_protocol_ambient_weather_check_crc() {
uint8_t msg[] = { uint8_t msg[] = {
static_cast<uint8_t>(decode_data >> 40), static_cast<uint8_t>(decode_data >> 40),
@ -81,7 +81,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
channel = ((data >> 28) & 0x07) + 1; channel = ((data >> 28) & 0x07) + 1;
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f); temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
humidity = (data >> 8) & 0xFF; humidity = (data >> 8) & 0xFF;
btn = WS_NO_BTN;
} }
}; };

View File

@ -91,7 +91,7 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
void ws_protocol_auriol_ahfl_remote_controller() { void ws_protocol_auriol_ahfl_remote_controller() {
id = data >> 34; id = data >> 34;
battery_low = (data >> 33) & 1; battery_low = (data >> 33) & 1;
btn = (data >> 32) & 1; // btn = (data >> 32) & 1;
channel = ((data >> 30) & 0x3) + 1; channel = ((data >> 30) & 0x3) + 1;
if (!((data >> 29) & 1)) { if (!((data >> 29) & 1)) {
temp = (float)((data >> 18) & 0x07FF) / 10.0f; temp = (float)((data >> 18) & 0x07FF) / 10.0f;

View File

@ -91,7 +91,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
id = (data >> 31) & 0xFF; id = (data >> 31) & 0xFF;
battery_low = ((data >> 30) & 1); battery_low = ((data >> 30) & 1);
channel = ((data >> 25) & 0x03) + 1; channel = ((data >> 25) & 0x03) + 1;
btn = WS_NO_BTN;
if (!((data >> 23) & 1)) { if (!((data >> 23) & 1)) {
temp = (float)((data >> 13) & 0x07FF) / 10.0f; temp = (float)((data >> 13) & 0x07FF) / 10.0f;
} else { } else {

View 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

View File

@ -91,7 +91,7 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
void ws_protocol_gt_wt_02_remote_controller() { void ws_protocol_gt_wt_02_remote_controller() {
id = (data >> 29) & 0xFF; id = (data >> 29) & 0xFF;
battery_low = (data >> 28) & 1; battery_low = (data >> 28) & 1;
btn = (data >> 27) & 1; // btn = (data >> 27) & 1;
channel = ((data >> 25) & 0x3) + 1; channel = ((data >> 25) & 0x3) + 1;
if (!((data >> 24) & 1)) { if (!((data >> 24) & 1)) {

View File

@ -124,7 +124,7 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
} }
battery_low = (data >> 24) & 1; battery_low = (data >> 24) & 1;
btn = (data >> 23) & 1; // (data >> 23) & 1;
channel = ((data >> 21) & 0x03) + 1; channel = ((data >> 21) & 0x03) + 1;
if (!((data >> 20) & 1)) { if (!((data >> 20) & 1)) {

View File

@ -125,7 +125,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
void ws_protocol_infactory_remote_controller() { void ws_protocol_infactory_remote_controller() {
id = data >> 32; id = data >> 32;
battery_low = (data >> 26) & 1; battery_low = (data >> 26) & 1;
btn = WS_NO_BTN;
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 12) & 0x0FFF) - 900.0f) / 10.0f); 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 humidity = (((data >> 8) & 0x0F) * 10) + ((data >> 4) & 0x0F); // BCD, 'A0'=100%rH
channel = data & 0x03; channel = data & 0x03;

View 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

View File

@ -137,7 +137,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
// furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type."); // furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type.");
} }
btn = WS_NO_BTN;
battery_low = WS_NO_BATT; battery_low = WS_NO_BATT;
channel = WS_NO_CHANNEL; channel = WS_NO_CHANNEL;
} }

View File

@ -113,7 +113,7 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
} }
id = data >> 32; id = data >> 32;
battery_low = (data >> 31) & 1; battery_low = (data >> 31) & 1;
btn = (data >> 30) & 1; // btn = (data >> 30) & 1;
channel = ((data >> 28) & 0x03) + 1; channel = ((data >> 28) & 0x03) + 1;
temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f; temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
humidity = (data >> 8) & 0xFF; humidity = (data >> 8) & 0xFF;

View File

@ -104,7 +104,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
id = (data >> 28) & 0xFF; id = (data >> 28) & 0xFF;
battery_low = !((data >> 27) & 1); battery_low = !((data >> 27) & 1);
channel = ((data >> 24) & 0x03) + 1; channel = ((data >> 24) & 0x03) + 1;
btn = WS_NO_BTN;
if (!((data >> 23) & 1)) { if (!((data >> 23) & 1)) {
temp = (float)((data >> 12) & 0x07FF) / 10.0f; temp = (float)((data >> 12) & 0x07FF) / 10.0f;
} else { } else {

View File

@ -160,7 +160,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
bool prev_bit = 0; bool prev_bit = 0;
uint8_t var_bits{0}; uint8_t var_bits{0};
uint32_t var_data{0}; uint32_t var_data{0};
ManchesterState manchester_saved_state = ManchesterStateMid1;
void ws_protocol_decoder_oregon2_reset() { void ws_protocol_decoder_oregon2_reset() {
parser_step = Oregon2DecoderStepReset; parser_step = Oregon2DecoderStepReset;
decode_data = 0UL; decode_data = 0UL;

View File

@ -117,7 +117,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
bool prev_bit = false; bool prev_bit = false;
uint8_t var_bits{0}; uint8_t var_bits{0};
uint64_t var_data{0}; uint64_t var_data{0};
ManchesterState manchester_saved_state = ManchesterStateMid1;
ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) { ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) {
bool is_long = false; bool is_long = false;

View File

@ -137,7 +137,7 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
uint32_t min_count_bit_for_found = 32; uint32_t min_count_bit_for_found = 32;
uint8_t first_bit{0}; uint8_t first_bit{0};
ManchesterState manchester_saved_state = ManchesterStateMid1;
bool ws_protocol_oregon_v1_check() { bool ws_protocol_oregon_v1_check() {
if (!decode_data) return false; if (!decode_data) return false;
uint64_t data = FProtoGeneral::subghz_protocol_blocks_reverse_key(decode_data, 32); uint64_t data = FProtoGeneral::subghz_protocol_blocks_reverse_key(decode_data, 32);
@ -159,7 +159,6 @@ class FProtoWeatherOregonV1 : public FProtoWeatherBase {
temp = -temp_raw; temp = -temp_raw;
} }
battery_low = !((data2 >> 23) & 1ULL); battery_low = !((data2 >> 23) & 1ULL);
btn = WS_NO_BTN;
humidity = WS_NO_HUMIDITY; humidity = WS_NO_HUMIDITY;
} }
}; };

View File

@ -96,7 +96,7 @@ class FProtoWeatherThermoProTx4 : public FProtoWeatherBase {
void ws_protocol_thermopro_tx4_remote_controller() { void ws_protocol_thermopro_tx4_remote_controller() {
id = (data >> 25) & 0xFF; id = (data >> 25) & 0xFF;
battery_low = (data >> 24) & 1; battery_low = (data >> 24) & 1;
btn = (data >> 23) & 1; // btn = (data >> 23) & 1;
channel = ((data >> 21) & 0x03) + 1; channel = ((data >> 21) & 0x03) + 1;
if (!((data >> 20) & 1)) { if (!((data >> 20) & 1)) {
temp = (float)((data >> 9) & 0x07FF) / 10.0f; temp = (float)((data >> 9) & 0x07FF) / 10.0f;

View File

@ -120,7 +120,6 @@ class FProtoWeatherTX8300 : public FProtoWeatherBase {
} }
void ws_protocol_tx_8300_remote_controller() { void ws_protocol_tx_8300_remote_controller() {
humidity = (((data >> 28) & 0x0F) * 10) + ((data >> 24) & 0x0F); humidity = (((data >> 28) & 0x0F) * 10) + ((data >> 24) & 0x0F);
btn = WS_NO_BTN;
if (!((data >> 22) & 0x03)) if (!((data >> 22) & 0x03))
battery_low = 0; battery_low = 0;
else else

View File

@ -147,8 +147,6 @@ class FProtoWeatherWendoxW6726 : public FProtoWeatherBase {
} else if (temp > 70.0f) { } else if (temp > 70.0f) {
temp = 70.0f; temp = 70.0f;
} }
btn = WS_NO_BTN;
humidity = WS_NO_HUMIDITY; humidity = WS_NO_HUMIDITY;
} }
}; };

View File

@ -24,12 +24,11 @@ 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; }
uint32_t getSensorId() { return id; }
float getTemp() { return temp; }
uint8_t getHumidity() { return humidity; } uint8_t getHumidity() { return humidity; }
uint8_t getBattLow() { return battery_low; } uint8_t getBattLow() { return battery_low; }
uint8_t getChannel() { return channel; } uint8_t getChannel() { return channel; }
uint8_t getButton() { return btn; } 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.
@ -38,25 +37,27 @@ class FProtoWeatherBase {
decode_count_bit++; 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; uint8_t sensorType = FPW_Invalid;
uint32_t id = WS_NO_ID;
float temp = WS_NO_TEMPERATURE;
uint8_t humidity = WS_NO_HUMIDITY; uint8_t humidity = WS_NO_HUMIDITY;
uint8_t battery_low = WS_NO_BATT; uint8_t battery_low = WS_NO_BATT;
uint8_t channel = WS_NO_CHANNEL; uint8_t channel = WS_NO_CHANNEL;
uint8_t btn = WS_NO_BTN; // inner logic stuff
// inner logic stuff, also for flipper compatibility.
SubGhzProtocolDecoderBaseRxCallback callback = NULL;
uint16_t header_count = 0;
uint8_t parser_step = 0; 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; uint32_t te_last = 0;
uint64_t data = 0;
uint32_t data_count_bit = 0; uint32_t data_count_bit = 0;
uint64_t decode_data = 0;
uint32_t decode_count_bit = 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 #endif

View File

@ -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-tx8300.hpp"
#include "w-wendox-w6726.hpp" #include "w-wendox-w6726.hpp"
#include "w-acurite986.hpp" #include "w-acurite986.hpp"
#include "w-kedsum.hpp"
#include "w-acurite5in1.hpp"
#include "w-emose601x.hpp"
#include <vector> #include <vector>
#include <memory> #include <memory>
#include "portapack_shared_memory.hpp" #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<FProtoWeatherTX8300>()); // 17
protos.push_back(std::make_unique<FProtoWeatherWendoxW6726>()); // 18 protos.push_back(std::make_unique<FProtoWeatherWendoxW6726>()); // 18
protos.push_back(std::make_unique<FProtoWeatherAcurite986>()); // 19 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 // set callback for them
for (const auto& obj : protos) { for (const auto& obj : protos) {
@ -65,7 +72,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->getSensorId(),
instance->getTemp(), instance->getHumidity(), instance->getBattLow(), instance->getTemp(), instance->getHumidity(), instance->getBattLow(),
instance->getChannel(), instance->getButton()}; instance->getChannel()};
shared_memory.application_queue.push(packet_message); shared_memory.application_queue.push(packet_message);
} }

View File

@ -11,7 +11,7 @@ Also it must have a switch-case element in the getWeatherSensorTypeName() functi
#define WS_NO_BATT 0xFF #define WS_NO_BATT 0xFF
#define WS_NO_HUMIDITY 0xFF #define WS_NO_HUMIDITY 0xFF
#define WS_NO_CHANNEL 0xFF #define WS_NO_CHANNEL 0xFF
#define WS_NO_BTN 0xFF // #define WS_NO_BTN 0xFF
#define WS_NO_TEMPERATURE -273.0f #define WS_NO_TEMPERATURE -273.0f
enum FPROTO_WEATHER_SENSOR { enum FPROTO_WEATHER_SENSOR {
@ -34,7 +34,11 @@ enum FPROTO_WEATHER_SENSOR {
FPW_THERMOPROTX4 = 16, FPW_THERMOPROTX4 = 16,
FPW_TX_8300 = 17, FPW_TX_8300 = 17,
FPW_WENDOX_W6726 = 18, FPW_WENDOX_W6726 = 18,
FPW_Acurite986 = 19 FPW_Acurite986 = 19,
FPW_KEDSUM = 20,
FPW_Acurite5in1 = 21,
FPW_EmosE601x = 22
}; };
#endif #endif

View File

@ -1267,16 +1267,14 @@ class WeatherDataMessage : public Message {
float temp = -273.0f, float temp = -273.0f,
uint8_t humidity = 0xFF, uint8_t humidity = 0xFF,
uint8_t battery_low = 0xFF, uint8_t battery_low = 0xFF,
uint8_t channel = 0xFF, uint8_t channel = 0xFF)
uint8_t btn = 0xFF)
: Message{ID::WeatherData}, : Message{ID::WeatherData},
sensorType{sensorType}, sensorType{sensorType},
id{id}, id{id},
temp{temp}, temp{temp},
humidity{humidity}, humidity{humidity},
battery_low{battery_low}, battery_low{battery_low},
channel{channel}, channel{channel} {
btn{btn} {
} }
uint8_t sensorType = 0; uint8_t sensorType = 0;
uint32_t id = 0xFFFFFFFF; uint32_t id = 0xFFFFFFFF;
@ -1284,7 +1282,6 @@ class WeatherDataMessage : public Message {
uint8_t humidity = 0xFF; uint8_t humidity = 0xFF;
uint8_t battery_low = 0xFF; uint8_t battery_low = 0xFF;
uint8_t channel = 0xFF; uint8_t channel = 0xFF;
uint8_t btn = 0xFF;
}; };
class SubGhzDDataMessage : public Message { class SubGhzDDataMessage : public Message {