rtl_433 icon indicating copy to clipboard operation
rtl_433 copied to clipboard

Add support for Vauno EN8822C

Open gumbald opened this issue 2 years ago • 13 comments

Some work to be done on CRC and humidity needs moving to 7 bits. Have commented out battery while we're unsure where it is (copied from Esperanza EWS).

gumbald avatar Sep 13 '22 20:09 gumbald

Humidity should be b[3] >> 1 (top 7 bits from byte 3), right? And checksum was nibble addition IIRC?

int chk = ((b[4] & 0x0f) << 2) | (b[5] & 0x03);
if (add_nibbles(b, 4) != chk) {
   // checksum error
}

zuckschwerdt avatar Sep 13 '22 21:09 zuckschwerdt

Made updates as above - is there an easy way for me to check that it works with the output? I'm also a bit confused at the width/limit values, different message captures had similar but different values!

gumbald avatar Sep 14 '22 19:09 gumbald

  • The uint8_t b[5]; needs to be uint8_t b[6];
  • "mic", "Integrity", DATA_STRING, "CRC", needs to be "mic", "Integrity", DATA_STRING, "CHECKSUM",
  • You need to change r_device esperanza_ews to r_device vauno_en8822c
  • Approximate timings are ok. E.g. here 2000, 4000, 5000, 9500

zuckschwerdt avatar Sep 14 '22 19:09 zuckschwerdt

  • I'd say 4200, 9100 is too narrow. Round up by 10-20%, e.g. 5000, 9500.
  • Fix the trailing whitespace error (line 29)
  • There is no bit offset, right? Remove uint8_t b[6]; and replace bitbuffer_extract_bytes(); by uint8_t *b = bitbuffer->bb[row];
  • The row selection seems wrong (L50 to 66), a bitbuffer looks like below. You'll want int row = bitbuffer_find_repeated_prefix(bitbuffer, 4, 42), see https://github.com/merbanan/rtl_433/blob/master/include/bitbuffer.h#L139-L142 and other devices how it's used to get and check row.
bitbuffer:: Number of rows: 13
[00] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[01] { 0}                   :
[02] { 0}                   :
[03] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[04] { 1} 00                : 0
[05] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[06] { 1} 00                : 0
[07] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[08] { 1} 00                : 0
[09] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[10] { 1} 00                : 0
[11] {42} 85 10 f9 74 0c 40 : 10000101 00010000 11111001 01110100 00001100 01
[12] { 0}                   :

zuckschwerdt avatar Sep 15 '22 08:09 zuckschwerdt

Thanks - these are all making sense! Had tried to work out what the whitespace error was myself but couldn't track that down.

I've set the minimum as 4 as per your suggestion - could this vary? I think I've always seen 6, but guess we're happy with less if they're the same length.

gumbald avatar Sep 15 '22 17:09 gumbald

I've set the minimum as 4 as per your suggestion - could this vary? I think I've always seen 6

The idea is to require (only) a majority: 6/2+1 -- this allows for bad reception of some packets

I guess you can now remove if (bitbuffer->num_rows != 13) as that might vary with bad reception and just the (minimum 4 identical rows with valid checksum look solid enough.

Line 59 uint8_t *b = bitbuffer->bb[row] needs a ; at the end ;)

zuckschwerdt avatar Sep 15 '22 18:09 zuckschwerdt

Much more Python than C recently!

gumbald avatar Sep 15 '22 20:09 gumbald

Much more Python than C recently!

;) Your identation was spot on!

zuckschwerdt avatar Sep 15 '22 20:09 zuckschwerdt

Line 59 needs to be data_t *data = data_make( -- should be all good then.

zuckschwerdt avatar Sep 15 '22 20:09 zuckschwerdt

Looks good (ignore the "symbol errors", that's another decoder).

zuckschwerdt avatar Sep 15 '22 21:09 zuckschwerdt

LGTM

merbanan avatar Sep 16 '22 07:09 merbanan

By reading in temp_raw as int, will this handle the Two's complement? Or do I need to declare as signed int, or convert...?

gumbald avatar Sep 17 '22 06:09 gumbald

Yes, you will need to align the bits to 16 bit, then use the sign extend to go from 16 bit to int width.

int temp_raw   = (int16_t)(((b[2] & 0x0f) << 12) | ((b[2] & 0xf0) << 4) | ((b[1] & 0x0f) << 4)); // use sign extend
float temp_c  = (temp_raw >> 4) * 0.1f;

or for legibility perhaps

int temp_raw   = ((b[2] & 0x0f) << 8) | (b[2] & 0xf0) | (b[1] & 0x0f);
temp_raw   = (int16_t)(temp_raw << 4); // use sign extend
float temp_c  = (temp_raw >> 4) * 0.1f;

zuckschwerdt avatar Sep 17 '22 09:09 zuckschwerdt

Just wanted to make sure, is there anything else I need to do on this? Is the simplest way for me to test it to build myself presumably?

gumbald avatar Oct 03 '22 12:10 gumbald

Just giving other people the chance to weight in. Good for merge, and will do so shortly.

zuckschwerdt avatar Oct 03 '22 15:10 zuckschwerdt

As someone who coincidentally bought one of these sensors pretty much the same day that this pull request was submitted I would just like to say thank you to everyone who worked on adding support for it. I look forward to it being merged so I can test it out. Any guess on how long it might take for this change to filter down into the Home Assistant RTL_433 add-on? In the mean time what is the best way to make it work? Will I need to download the source and compile it? Anyway, thanks again.

stefanhra avatar Oct 05 '22 22:10 stefanhra

Thanks for your efforts on this! Unfortunately, I do not think it is correct for my EN8822C device from amazon labelled on the front "EN8822 Model T21".

I tried this pull and ran into some problems where I think the alignment is off. See attached analysis files:

This one kind of works, but the temp is not correct. Actual temp/humidity = approximately 75F / 55% (sorry, do not have the display) vs. reported 177.6C: g005_433.92M_250k.cu8.analysis.txt

Placed it in the freezer at 8F. This one is shifted somehow and does not decode/report: g116_433.92M_250k.cu8.analysis.txt

loopy321 avatar Nov 02 '22 22:11 loopy321

Your first example: {42} 6d 00 f6 66 0d 00 - this would be 24.6C, which is 76.3F...?

gumbald avatar Nov 03 '22 15:11 gumbald

Not sure where the problem lies, but the first file has: [00] {42} 6d 00 f6 66 0d 00 : 01101101 00000000 11110110 01100110 00001101 00 with the output of decoder as: Channel : 1 Temperature: 177.6 C Humidity : 12 % Integrity : CHECKSUM The second file has: [00] {42} 6d 0f 78 5e 01 00 : 01101101 00001111 01111000 01011110 00000001 00

I am a noob at this, but following the ~/docs/Analysis.md using BitBench I think the structure might be more like:

ID:109 CH:0 TEMP_C:  246 HUM:052 CRC:00
ID:109 CH:0 TEMP_C: -136 HUM:004 CRC:00

https://triq.net/bitbench#c=6d%2000%20f6%2066%200d%2000&c=6d%200f%2078%205e%2001%2000&f=ID%3Ad%20CH%3Ah%20TEMP_C%3A12s%20xxxxxxxxxx%20HUM%3Ad%20CRC%3A8h%20%7C%208h%2016h%2016h%20&cw=4

That gives me a consistent id, channel (0, actually 0+1), temp (24.6C, -13.6C), and humidity (52%, 4%) with what I would expect from the two above data points. Not sure what is in all of those x's, but at least probably battery.

Maybe that is what you already have identified, but my compiled version gives incorrect decoding.

loopy321 avatar Nov 03 '22 17:11 loopy321

Not sure where the problem lies, but the first file has: [00] {42} 6d 00 f6 66 0d 00 : 01101101 00000000 11110110 01100110 00001101 00 with the output of decoder as: Channel : 1 Temperature: 177.6 C Humidity : 12 % Integrity : CHECKSUM The second file has: [00] {42} 6d 0f 78 5e 01 00 : 01101101 00001111 01111000 01011110 00000001 00

I am a noob at this, but following the ~/docs/Analysis.md using BitBench I think the structure might be more like:

ID:109 CH:0 TEMP_C:  246 HUM:052 CRC:00
ID:109 CH:0 TEMP_C: -136 HUM:004 CRC:00

https://triq.net/bitbench#c=6d%2000%20f6%2066%200d%2000&c=6d%200f%2078%205e%2001%2000&f=ID%3Ad%20CH%3Ah%20TEMP_C%3A12s%20xxxxxxxxxx%20HUM%3Ad%20CRC%3A8h%20%7C%208h%2016h%2016h%20&cw=4

That gives me a consistent id, channel (0, actually 0+1), temp (24.6C, -13.6C), and humidity (52%, 4%) with what I would expect from the two above data points. Not sure what is in all of those x's, but at least probably battery.

Maybe that is what you already have identified, but my compiled version gives incorrect decoding.

Adding more data points with a different analysis (row 4 is from the pull .c file).
ID and Chan and temp are definitely correct. Is the humidity 2x the measurement? (i.e. row 4: 124/2=62% same as in .c file)

https://triq.net/bitbench#c=6d%2000%20f6%2066%200d%2000&c=6d%200f%2078%205e%2001%2000&c=af%200f%20a2%207c%2001%20c0&c=6d%2000%20bf%207c%2000%2000&c=9b%2001%2011%2062%2007%20c0&c=9b%2011%2011%2062%2008%2000&c=9b%2021%2011%2062%2008%2040&f=ID%3Ad%20CH%3Ah%20TEMP_C%3A12s%20HUM%3Ad%20CRC%3A8h%20%7C%208h&cw=4

loopy321 avatar Nov 03 '22 17:11 loopy321

At a quick glance I'd say int humidity = ((b[3] & 0xf0) >> 3); is a typo, it should be int humidity = ((b[3] & 0xfe) >> 1); (or simply int humidity = (b[3] >> 1);)

zuckschwerdt avatar Nov 03 '22 18:11 zuckschwerdt

Is there a good resource/tutorial for coding the results from the bitbench? i.e.: ID:d CH:h TEMP_C:12s HUM:d xxxxxxxx xxxxxxxx

Trying to use as a learning exercise. Thanks!

loopy321 avatar Nov 03 '22 19:11 loopy321

We have the template https://github.com/merbanan/rtl_433/blob/master/src/devices/new_template.c Not much about converting bits in there though.

zuckschwerdt avatar Nov 04 '22 07:11 zuckschwerdt

I'll have another go and compile tonight, unless you get there with the fix first!

gumbald avatar Nov 04 '22 09:11 gumbald

I got the temperature and humidity working with the following replacing lines 64-67. Thanks for the suggestions!

    int temp_raw   = (((b[1] & 0x0f) <<8) | (b[2] & 0xff)); // combine bits
    float temp_c  = (int16_t)(temp_raw - ((temp_raw & 0x800) <<1)) * 0.1f ; // sign bit
    int humidity  = (b[3] >> 1);

or following the example from here: https://github.com/merbanan/rtl_433/blob/master/src/devices/generic_temperature_sensor.c

    temp_raw = (int16_t)(((b[1] & 0x0f) << 12) | ((b[2] & 0xff) << 4));
    temp_c  = (temp_raw >> 4) * 0.1f;
    int humidity  = (b[3] >> 1);

Seems like there remains some problems in checksum.

loopy321 avatar Nov 04 '22 14:11 loopy321

Any idea how to get the checksum working properly?
In bitbench here I see that the ID, CH, TEMP_C, HUM all work out nicely with this scheme:

ID:8d CH:4h TEMP_C:12s HUM:7d x xxxx CRC:6d xxxxxx according to the presumed structure:

    Byte:      0        1        2        3        4
    Nibble:    1   2    3   4    5   6    7   8    9   10   11
    Type:      IIIIIIII ??CCTTTT TTTTTTTT HHHHHHH? FFFFXXXX XX

6d	0	f6	66	0d	0		ID:109	CH:0	TEMP_C:246	HUM:051	CRC:52	=	65
6d	0f	78	5e	1	0		ID:109	CH:0	TEMP_C:-136	HUM:047	CRC:04	=	69
af	0f	a2	7c	1	c0		ID:175	CH:0	TEMP_C:-94	HUM:062	CRC:07	=	84
6d	0	bf	7c	0	0		ID:109	CH:0	TEMP_C:191	HUM:062	CRC:00	=	64
9b	1	11	62	7	c0		ID:155	CH:0	TEMP_C:273	HUM:049	CRC:31	=	50
9b	11	11	62	8	0		ID:155	CH:1	TEMP_C:273	HUM:049	CRC:32	=	40
9b	21	11	62	8	40		ID:155	CH:2	TEMP_C:273	HUM:049	CRC:33	=	45

But, as you can see the CRC add result does not work out. Any idea based on experience how to fix this? Thanks!

loopy321 avatar Nov 07 '22 00:11 loopy321

I see this works now (based on your issue - missed that) :

ID:8d CH:4h TEMP_C:12s HUM:7d ?5b CRC:6h xxxxxx

loopy321 avatar Nov 07 '22 00:11 loopy321

side note: CRC is a specific kind of checksum, here it's not a CRC but a plain sum (addition with carry).

zuckschwerdt avatar Nov 07 '22 09:11 zuckschwerdt

I am finding a lot of missed decodes due to miscalculation of the checksum. Based on a lot of samples, it looks like decoding only works where the last two bits are 00.

For example the following gets decoded properly (presumably because the last two bits are zero):

{42} 4b 0f 6e 64 0f 00 : 01001011 00001111 01101110 01100100 00001111 00 ==> ID:075 CH:0 TEMP_C: -146 HUM:050

While the following had add_nibbles(b,4)=59 and chk=((b[4] & 0x0f) << 2) | (b[5] & 0x03)=56 and does not get processed (possibly because of the last two bits not being zero):

{42} 4b 0f 6d 64 0e c0 : 01001011 00001111 01101101 01100100 00001110 11 ==> ID:075 CH:0 TEMP_C: -147 HUM:050

Anyone see how to change the calculations so that it works in both circumstances?

loopy321 avatar Nov 07 '22 18:11 loopy321

A typo, that should really be int chk = ((b[4] & 0x0f) << 2) | (b[5] >> 6); i.e. the top 2 bit, not the bottom ones.

zuckschwerdt avatar Nov 07 '22 18:11 zuckschwerdt