|
|
@@ -1,14 +1,17 @@
|
|
|
#include "oregon2.h"
|
|
|
-#include "../blocks/const.h"
|
|
|
-#include "../blocks/decoder.h"
|
|
|
-#include "../blocks/generic.h"
|
|
|
-#include "../blocks/math.h"
|
|
|
+
|
|
|
+#include <lib/subghz/blocks/const.h>
|
|
|
+#include <lib/subghz/blocks/decoder.h>
|
|
|
+#include <lib/subghz/blocks/encoder.h>
|
|
|
+#include <lib/subghz/blocks/math.h>
|
|
|
+#include "ws_generic.h"
|
|
|
+
|
|
|
#include <lib/toolbox/manchester_decoder.h>
|
|
|
#include <lib/flipper_format/flipper_format_i.h>
|
|
|
|
|
|
-#define TAG "SubGhzProtocolOregon2"
|
|
|
+#define TAG "WSProtocolOregon2"
|
|
|
|
|
|
-static const SubGhzBlockConst oregon2_const = {
|
|
|
+static const SubGhzBlockConst ws_oregon2_const = {
|
|
|
.te_long = 1000,
|
|
|
.te_short = 500,
|
|
|
.te_delta = 200,
|
|
|
@@ -26,11 +29,11 @@ static const SubGhzBlockConst oregon2_const = {
|
|
|
// bit indicating the low battery
|
|
|
#define OREGON2_FLAG_BAT_LOW 0x4
|
|
|
|
|
|
-struct SubGhzProtocolDecoderOregon2 {
|
|
|
+struct WSProtocolDecoderOregon2 {
|
|
|
SubGhzProtocolDecoderBase base;
|
|
|
|
|
|
SubGhzBlockDecoder decoder;
|
|
|
- SubGhzBlockGeneric generic;
|
|
|
+ WSBlockGeneric generic;
|
|
|
ManchesterState manchester_state;
|
|
|
bool prev_bit;
|
|
|
bool have_bit;
|
|
|
@@ -39,7 +42,7 @@ struct SubGhzProtocolDecoderOregon2 {
|
|
|
uint32_t var_data;
|
|
|
};
|
|
|
|
|
|
-typedef struct SubGhzProtocolDecoderOregon2 SubGhzProtocolDecoderOregon2;
|
|
|
+typedef struct WSProtocolDecoderOregon2 WSProtocolDecoderOregon2;
|
|
|
|
|
|
typedef enum {
|
|
|
Oregon2DecoderStepReset = 0,
|
|
|
@@ -47,23 +50,29 @@ typedef enum {
|
|
|
Oregon2DecoderStepVarData,
|
|
|
} Oregon2DecoderStep;
|
|
|
|
|
|
-void* subghz_protocol_decoder_oregon2_alloc(SubGhzEnvironment* environment) {
|
|
|
+void* ws_protocol_decoder_oregon2_alloc(SubGhzEnvironment* environment) {
|
|
|
UNUSED(environment);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = malloc(sizeof(SubGhzProtocolDecoderOregon2));
|
|
|
- instance->base.protocol = &subghz_protocol_oregon2;
|
|
|
+ WSProtocolDecoderOregon2* instance = malloc(sizeof(WSProtocolDecoderOregon2));
|
|
|
+ instance->base.protocol = &ws_protocol_oregon2;
|
|
|
instance->generic.protocol_name = instance->base.protocol->name;
|
|
|
+ instance->generic.humidity = WS_NO_HUMIDITY;
|
|
|
+ instance->generic.temp = WS_NO_TEMPERATURE;
|
|
|
+ instance->generic.btn = WS_NO_BTN;
|
|
|
+ instance->generic.channel = WS_NO_CHANNEL;
|
|
|
+ instance->generic.battery_low = WS_NO_BATT;
|
|
|
+ instance->generic.id = WS_NO_ID;
|
|
|
return instance;
|
|
|
}
|
|
|
|
|
|
-void subghz_protocol_decoder_oregon2_free(void* context) {
|
|
|
+void ws_protocol_decoder_oregon2_free(void* context) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
free(instance);
|
|
|
}
|
|
|
|
|
|
-void subghz_protocol_decoder_oregon2_reset(void* context) {
|
|
|
+void ws_protocol_decoder_oregon2_reset(void* context) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
instance->decoder.parser_step = Oregon2DecoderStepReset;
|
|
|
instance->decoder.decode_data = 0UL;
|
|
|
instance->decoder.decode_count_bit = 0;
|
|
|
@@ -77,9 +86,9 @@ void subghz_protocol_decoder_oregon2_reset(void* context) {
|
|
|
static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) {
|
|
|
bool is_long = false;
|
|
|
|
|
|
- if(DURATION_DIFF(duration, oregon2_const.te_long) < oregon2_const.te_delta) {
|
|
|
+ if(DURATION_DIFF(duration, ws_oregon2_const.te_long) < ws_oregon2_const.te_delta) {
|
|
|
is_long = true;
|
|
|
- } else if(DURATION_DIFF(duration, oregon2_const.te_short) < oregon2_const.te_delta) {
|
|
|
+ } else if(DURATION_DIFF(duration, ws_oregon2_const.te_short) < ws_oregon2_const.te_delta) {
|
|
|
is_long = false;
|
|
|
} else {
|
|
|
return ManchesterEventReset;
|
|
|
@@ -97,9 +106,36 @@ static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) {
|
|
|
+static void ws_oregon2_decode_const_data(WSBlockGeneric* ws_block) {
|
|
|
+ ws_block->id = OREGON2_SENSOR_ID(ws_block->data);
|
|
|
+
|
|
|
+ uint8_t ch_bits = (ws_block->data >> 12) & 0xF;
|
|
|
+ ws_block->channel = 1;
|
|
|
+ while(ch_bits > 1) {
|
|
|
+ ws_block->channel++;
|
|
|
+ ch_bits >>= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ws_block->battery_low = (ws_block->data & OREGON2_FLAG_BAT_LOW) ? 1 : 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ ws_oregon2_decode_var_data(WSBlockGeneric* ws_block, uint16_t sensor_id, uint32_t var_data) {
|
|
|
+ int16_t temp_val;
|
|
|
+ if(sensor_id == 0xEC40) {
|
|
|
+ temp_val = ((var_data >> 4) & 0xF) * 10 + ((var_data >> 8) & 0xF);
|
|
|
+ temp_val *= 10;
|
|
|
+ temp_val += (var_data >> 12) & 0xF;
|
|
|
+ if(var_data & 0xF) temp_val = -temp_val;
|
|
|
+ } else
|
|
|
+ return;
|
|
|
+
|
|
|
+ ws_block->temp = (float)temp_val / 10.0;
|
|
|
+}
|
|
|
+
|
|
|
+void ws_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
// oregon v2.1 signal is inverted
|
|
|
ManchesterEvent event = level_and_duration_to_event(!level, duration);
|
|
|
bool data;
|
|
|
@@ -118,7 +154,7 @@ void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t du
|
|
|
} else if(instance->prev_bit && !data) {
|
|
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
|
|
} else {
|
|
|
- subghz_protocol_decoder_oregon2_reset(context);
|
|
|
+ ws_protocol_decoder_oregon2_reset(context);
|
|
|
}
|
|
|
instance->have_bit = false;
|
|
|
} else {
|
|
|
@@ -151,6 +187,7 @@ void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t du
|
|
|
instance->generic.data = (instance->generic.data & 0x33333333) << 2 |
|
|
|
(instance->generic.data & 0xCCCCCCCC) >> 2;
|
|
|
|
|
|
+ ws_oregon2_decode_const_data(&instance->generic);
|
|
|
instance->var_bits =
|
|
|
oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(instance->generic.data));
|
|
|
|
|
|
@@ -175,6 +212,11 @@ void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t du
|
|
|
instance->var_data = (instance->var_data & 0x33333333) << 2 |
|
|
|
(instance->var_data & 0xCCCCCCCC) >> 2;
|
|
|
|
|
|
+ ws_oregon2_decode_var_data(
|
|
|
+ &instance->generic,
|
|
|
+ OREGON2_SENSOR_ID(instance->generic.data),
|
|
|
+ instance->var_data >> OREGON2_CHECKSUM_BITS);
|
|
|
+
|
|
|
instance->decoder.parser_step = Oregon2DecoderStepReset;
|
|
|
if(instance->base.callback)
|
|
|
instance->base.callback(&instance->base, instance->base.context);
|
|
|
@@ -183,20 +225,20 @@ void subghz_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t du
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-uint8_t subghz_protocol_decoder_oregon2_get_hash_data(void* context) {
|
|
|
+uint8_t ws_protocol_decoder_oregon2_get_hash_data(void* context) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
return subghz_protocol_blocks_get_hash_data(
|
|
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
|
|
}
|
|
|
|
|
|
-bool subghz_protocol_decoder_oregon2_serialize(
|
|
|
+bool ws_protocol_decoder_oregon2_serialize(
|
|
|
void* context,
|
|
|
FlipperFormat* flipper_format,
|
|
|
SubGhzRadioPreset* preset) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
- if(!subghz_block_generic_serialize(&instance->generic, flipper_format, preset)) return false;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
+ if(!ws_block_generic_serialize(&instance->generic, flipper_format, preset)) return false;
|
|
|
uint32_t temp = instance->var_bits;
|
|
|
if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) {
|
|
|
FURI_LOG_E(TAG, "Error adding VarBits");
|
|
|
@@ -213,13 +255,13 @@ bool subghz_protocol_decoder_oregon2_serialize(
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool subghz_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) {
|
|
|
+bool ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
bool ret = false;
|
|
|
uint32_t temp_data;
|
|
|
do {
|
|
|
- if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
|
|
+ if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
|
|
break;
|
|
|
}
|
|
|
if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) {
|
|
|
@@ -235,7 +277,7 @@ bool subghz_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* f
|
|
|
FURI_LOG_E(TAG, "Missing VarData");
|
|
|
break;
|
|
|
}
|
|
|
- if(instance->generic.data_count_bit != oregon2_const.min_count_bit_for_found) {
|
|
|
+ if(instance->generic.data_count_bit != ws_oregon2_const.min_count_bit_for_found) {
|
|
|
FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit);
|
|
|
break;
|
|
|
}
|
|
|
@@ -244,22 +286,6 @@ bool subghz_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* f
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-// append string of the variable data
|
|
|
-static void
|
|
|
- oregon2_var_data_append_string(uint16_t sensor_id, uint32_t var_data, FuriString* output) {
|
|
|
- uint32_t val;
|
|
|
-
|
|
|
- if(sensor_id == 0xEC40) {
|
|
|
- val = ((var_data >> 4) & 0xF) * 10 + ((var_data >> 8) & 0xF);
|
|
|
- furi_string_cat_printf(
|
|
|
- output,
|
|
|
- "Temp: %s%ld.%ld C\r\n",
|
|
|
- (var_data & 0xF) ? "-" : "+",
|
|
|
- val,
|
|
|
- (uint32_t)(var_data >> 12) & 0xF);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, FuriString* output) {
|
|
|
uint8_t sum = fix_data & 0xF;
|
|
|
uint8_t ref_sum = var_data & 0xFF;
|
|
|
@@ -279,45 +305,50 @@ static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, FuriS
|
|
|
furi_string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum);
|
|
|
}
|
|
|
|
|
|
-void subghz_protocol_decoder_oregon2_get_string(void* context, FuriString* output) {
|
|
|
+void ws_protocol_decoder_oregon2_get_string(void* context, FuriString* output) {
|
|
|
furi_assert(context);
|
|
|
- SubGhzProtocolDecoderOregon2* instance = context;
|
|
|
- uint16_t sensor_id = OREGON2_SENSOR_ID(instance->generic.data);
|
|
|
+ WSProtocolDecoderOregon2* instance = context;
|
|
|
furi_string_cat_printf(
|
|
|
output,
|
|
|
"%s\r\n"
|
|
|
- "ID: 0x%04lX, ch: %ld%s, rc: 0x%02lX\r\n",
|
|
|
+ "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n",
|
|
|
instance->generic.protocol_name,
|
|
|
- (uint32_t)sensor_id,
|
|
|
- (uint32_t)(instance->generic.data >> 12) & 0xF,
|
|
|
- ((instance->generic.data & OREGON2_FLAG_BAT_LOW) ? ", low bat" : ""),
|
|
|
+ instance->generic.id,
|
|
|
+ instance->generic.channel,
|
|
|
+ instance->generic.battery_low,
|
|
|
(uint32_t)(instance->generic.data >> 4) & 0xFF);
|
|
|
|
|
|
if(instance->var_bits > 0) {
|
|
|
- oregon2_var_data_append_string(
|
|
|
- sensor_id, instance->var_data >> OREGON2_CHECKSUM_BITS, output);
|
|
|
+ furi_string_cat_printf(
|
|
|
+ output,
|
|
|
+ "Temp:%d.%d C Hum:%d%%",
|
|
|
+ (int16_t)instance->generic.temp,
|
|
|
+ abs(
|
|
|
+ ((int16_t)(instance->generic.temp * 10) -
|
|
|
+ (((int16_t)instance->generic.temp) * 10))),
|
|
|
+ instance->generic.humidity);
|
|
|
oregon2_append_check_sum((uint32_t)instance->generic.data, instance->var_data, output);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const SubGhzProtocolDecoder subghz_protocol_oregon2_decoder = {
|
|
|
- .alloc = subghz_protocol_decoder_oregon2_alloc,
|
|
|
- .free = subghz_protocol_decoder_oregon2_free,
|
|
|
+const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = {
|
|
|
+ .alloc = ws_protocol_decoder_oregon2_alloc,
|
|
|
+ .free = ws_protocol_decoder_oregon2_free,
|
|
|
|
|
|
- .feed = subghz_protocol_decoder_oregon2_feed,
|
|
|
- .reset = subghz_protocol_decoder_oregon2_reset,
|
|
|
+ .feed = ws_protocol_decoder_oregon2_feed,
|
|
|
+ .reset = ws_protocol_decoder_oregon2_reset,
|
|
|
|
|
|
- .get_hash_data = subghz_protocol_decoder_oregon2_get_hash_data,
|
|
|
- .serialize = subghz_protocol_decoder_oregon2_serialize,
|
|
|
- .deserialize = subghz_protocol_decoder_oregon2_deserialize,
|
|
|
- .get_string = subghz_protocol_decoder_oregon2_get_string,
|
|
|
+ .get_hash_data = ws_protocol_decoder_oregon2_get_hash_data,
|
|
|
+ .serialize = ws_protocol_decoder_oregon2_serialize,
|
|
|
+ .deserialize = ws_protocol_decoder_oregon2_deserialize,
|
|
|
+ .get_string = ws_protocol_decoder_oregon2_get_string,
|
|
|
};
|
|
|
|
|
|
-const SubGhzProtocol subghz_protocol_oregon2 = {
|
|
|
- .name = SUBGHZ_PROTOCOL_OREGON2_NAME,
|
|
|
+const SubGhzProtocol ws_protocol_oregon2 = {
|
|
|
+ .name = WS_PROTOCOL_OREGON2_NAME,
|
|
|
.type = SubGhzProtocolTypeStatic,
|
|
|
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
|
|
|
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save,
|
|
|
|
|
|
- .decoder = &subghz_protocol_oregon2_decoder,
|
|
|
+ .decoder = &ws_protocol_oregon2_decoder,
|
|
|
};
|