rtl_433/src/devices/auriol_afw2a1.c

131 lines
4.5 KiB
C

/** @file
Auriol AFW 2 A1 sensor.
Copyright (C) 2019 LiberationFrequency
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
/**
Lidl Auriol AFW 2 A1 sensor (IAN 311588).
Technical data for the external sensor:
- Temperature measuring range/accuracy: -20 to +65°C (-4 to +149°F) / ±1.5 °C (± 2.7 °F)
- Relative humidity measuring range/accuracy: 20 to 99% / ± 5%
- Relative humidity resolution: 1%
- Transmission frequencies: 433 MHz (ch1:~433919300,ch2:~433915200,ch3:~433918000, various?)
- Transmission output: < 10 dBm / < 10 mW
The ID is retained even if the batteries are changed.
The device has three channels and a transmit button.
Data layout:
The sensor transmits 12 identical messages of 36 bits in a single package each ~60 seconds, depending on the temperature.
e.g.:
[00] {36} 90 80 ba a3 a0 : 10010000 10000000 10111010 10100011 1010
...
[11] {36} 90 80 ba a3 a0 : ...
0 1 2 3 4
9 0 8 0 b a a 3 a 0
|1001|0000| |1000|0000| |1011|1010| |1010|0011| |1010|
|id | |chan|temp | |fix |hum |
--------------------------------------------------------
10010000 = id=0x90=144; 8 bit
1 = battery_ok; 1 bit
0 = tx_button; 1 bit
00 = channel; 2 bit
0000 = temperature leading sign,
1110=0xe(-51.1°C to -25.7°C),
1111=0xf(-25.6°C to - 0.1°C),
0000=0x0( 0.0°C to 25,5°C),
0001=0x1( 25.6°C to 51.1°C),
0010=0x2( 51.2°C to 76.7°C); 4 bit
10111010 = temperature=0xba=186=18,6°C; 8 bit
1010 = fixed; 4 bit
0011 1010 = humidity=0x3a=58%; 8 bit
*/
#include "decoder.h"
static int auriol_afw2a1_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
data_t *data;
uint8_t *b;
int row;
int id;
int channel;
int battery_ok;
int tx_button;
int temp_raw;
float temp_c;
int humidity;
row = bitbuffer_find_repeated_row(bitbuffer, 12, 36);
if (row < 0) {
return DECODE_ABORT_EARLY; // no repeated row found
}
b = bitbuffer->bb[row];
id = b[0];
battery_ok = b[1] >> 7;
tx_button = (b[1] & 0x40) >> 6;
channel = (b[1] & 0x30) >> 4;
temp_raw = (int16_t)(((b[1] & 0x0f) << 12) | (b[2] << 4)); // uses sign extend
temp_c = (temp_raw >> 4) * 0.1f;
// 0xa is fixed. If it differs, it is a wrong device. Could anyone confirm that?
if ((b[3] >> 4) != 0xa) {
decoder_log(decoder, 1, __func__, "Not an Auriol-AFW2A1 device");
return DECODE_FAIL_SANITY;
}
humidity = (((b[3] & 0x0f) << 4) | (b[4] >> 4));
if ((humidity > 0x64) || (humidity < 0x00) || (temp_c < -51.1) || (temp_c > 76.7)) {
decoder_log(decoder, 1, __func__, "Auriol-AFW2A1 data error");
return DECODE_FAIL_SANITY;
}
/* clang-format off */
data = data_make(
"model", "", DATA_STRING, "Auriol-AFW2A1",
"id", "", DATA_INT, id,
"channel", "Channel", DATA_INT, channel + 1,
"battery_ok", "Battery", DATA_INT, battery_ok,
"button", "Button", DATA_INT, tx_button,
"temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
"humidity", "Humidity", DATA_FORMAT, "%.0f %%", DATA_DOUBLE, (float)humidity,
NULL);
/* clang-format on */
decoder_output_data(decoder, data);
return 1;
}
static char const *const output_fields[] = {
"model",
"id",
"channel",
"battery_ok",
"button",
"temperature_C",
"humidity",
NULL,
};
// ToDo: The timings have come about through trial and error. Audit this against weak signals!
r_device const auriol_afw2a1 = {
.name = "Auriol AFW2A1 temperature/humidity sensor",
.modulation = OOK_PULSE_PPM,
.short_width = 576,
.long_width = 1536,
.sync_width = 0, // No sync bit used
.gap_limit = 2012,
.reset_limit = 3954,
.decode_fn = &auriol_afw2a1_decode,
.fields = output_fields,
};