Has anyone had any luck in decoding Acurite 3N1 / 5N1 devices via Weather Station?
Since rtl_433 can already decode these I’m thinking this would be simple to add.
Has anyone had any luck in decoding Acurite 3N1 / 5N1 devices via Weather Station?
Since rtl_433 can already decode these I’m thinking this would be simple to add.
Look in Applications/tools/Weather app. I think it might already be on the Flipper. It works but I don’t think the range is great.
That is where I have been trying. The protocol is not yet implemented.
From rtl_433/acurite.c at master · merbanan/rtl_433 · GitHub
The following needs to be ported?
/**
Acurite 3n1 Weather Station decoder
*/
static int acurite_3n1_decode(r_device *decoder, bitbuffer_t *bitbuffer, uint8_t *bb)
{
// MIC (checkum, parity) validated in calling function
(void)bitbuffer;
char const* channel_str = acurite_getChannel(bb[0]);
// 3n1 sensor ID is 14 bits
uint16_t sensor_id = ((bb[0] & 0x3f) << 8) | bb[1];
uint8_t message_type = bb[2] & 0x3f;
if (*channel_str == 'E') {
decoder_logf(decoder, 1, __func__,
"bad channel Ch %s, msg type 0x%02x",
channel_str, message_type);
return DECODE_FAIL_SANITY;
}
/*
@todo bug, 3n1 data format includes sequence_num
which was copied from 5n1, but existing code 3n1 uses
14 bits for ID. so these bits are used twice.
Leaving for compatibility, but probaby sequence_num
doesn't exist and should be deleted. If the 3n1 did use
a sequence number, the ID would change on each output.
*/
uint8_t sequence_num = (bb[0] & 0x30) >> 4;
int battery_low = (bb[2] & 0x40) == 0;
uint8_t humidity = (bb[3] & 0x7f); // 1-99 %rH
if (humidity > 100) {
decoder_logf(decoder, 1, __func__, "3n1 0x%04X Ch %s : invalid humidity: %d %%rH",
sensor_id, channel_str, humidity);
return DECODE_FAIL_SANITY;
}
// note the 3n1 seems to have one more high bit than 5n1
// Spec: -40 to 158 F
int temp_raw = (bb[4] & 0x1F) << 7 | (bb[5] & 0x7F);
float tempf = (temp_raw - 1480) * 0.1f; // regression yields (rawtemp-1480)*0.1
if (tempf < -40.0 || tempf > 158.0) {
decoder_logf(decoder, 1, __func__, "3n1 0x%04X Ch %s, invalid temperature: %0.1f F",
sensor_id, channel_str, tempf);
return DECODE_FAIL_SANITY;
}
/*
@todo bug from original decoder
This can't be a float, must be uint8
leaving for compatibility
*/
float wind_speed_mph = bb[6] & 0x7f; // seems to be plain MPH
/* clang-format off */
data_t *data;
data = data_make(
"model", "", DATA_STRING, "Acurite-3n1",
"message_type", NULL, DATA_INT, message_type,
"id", NULL, DATA_FORMAT, "0x%02X", DATA_INT, sensor_id,
"channel", NULL, DATA_STRING, channel_str,
"sequence_num", NULL, DATA_INT, sequence_num,
"battery_ok", "Battery", DATA_INT, !battery_low,
"wind_avg_mi_h", "wind_speed", DATA_FORMAT, "%.1f mi/h", DATA_DOUBLE, wind_speed_mph,
"temperature_F", "temperature", DATA_FORMAT, "%.1f F", DATA_DOUBLE, tempf,
"humidity", NULL, DATA_FORMAT, "%u %%", DATA_INT, humidity,
"mic", "Integrity", DATA_STRING, "CHECKSUM",
NULL);
/* clang-format on */
decoder_output_data(decoder, data);
return 1; // If we got here 1 valid message was output
}
It works fine on the stand alone Acurite temperature sensors I have but I don’t have the 3in1. It doesn’t seem to work with Ecowhitt sensors yet either. It would be cool if we could get more of the RTL_433 stuff added.
Just looking at the two repositories. I wonder if the whole thing wasn’t implemented due to resources. The corresponding file in the weather station .fap is much smaller. I might try to write one myself and see what happens. My C is very rusty though.
EDIT: Since I don’t have that sensor to test I won’t be trying to implement the 3 in 1. Maybe if I have luck with a different protocol I’ll try it at a later time.
I have a lot to figure out before I get anywhere with this so don’t get your hopes up on me personally adding anything useful any time soon. I haven’t touched C in a very long time and when I did it was Objective C which is a bit different then what the Flipper uses.