From 2e33d43bf495d2286ef22a9d45c17f715916249d Mon Sep 17 00:00:00 2001
From: "Christian W. Zuckschwerdt" <christian@zuckschwerdt.org>
Date: Wed, 13 May 2020 18:54:54 +0200
Subject: [PATCH] Add Eurochron EFTH-800 support (closes #1375)

---
 README.md                    |   1 +
 conf/rtl_433.example.conf    |   1 +
 include/rtl_433_devices.h    |   1 +
 man/man1/rtl_433.1           |   3 +
 src/CMakeLists.txt           |   1 +
 src/Makefile.am              |   1 +
 src/devices/efth800.c        | 105 +++++++++++++++++++++++++++++++++++
 vs15/rtl_433.vcxproj         |   1 +
 vs15/rtl_433.vcxproj.filters |   3 +
 9 files changed, 117 insertions(+)
 create mode 100644 src/devices/efth800.c

diff --git a/README.md b/README.md
index bdaac9a7..dd1da8ed 100644
--- a/README.md
+++ b/README.md
@@ -225,6 +225,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
     [149]  ERT
     [150]* Klimalogg
     [151]  Visonic powercode
+    [152]  Eurochron EFTH-800 temperature and humidity sensor
 
 * Disabled by default, use -R n or -G
 
diff --git a/conf/rtl_433.example.conf b/conf/rtl_433.example.conf
index 58c6863d..fb4d68d2 100644
--- a/conf/rtl_433.example.conf
+++ b/conf/rtl_433.example.conf
@@ -333,6 +333,7 @@ stop_after_successful_events false
   protocol 149 # ERT
 # protocol 150 # Klimalogg
   protocol 151 # Visonic powercode
+  protocol 152 # Eurochron EFTH-800 temperature and humidity sensor
 
 ## Flex devices (command line option "-X")
 
diff --git a/include/rtl_433_devices.h b/include/rtl_433_devices.h
index 9f6e9f7d..b0b70e8e 100644
--- a/include/rtl_433_devices.h
+++ b/include/rtl_433_devices.h
@@ -159,6 +159,7 @@
     DECL(ert_amr) \
     DECL(klimalogg) \
     DECL(visonic_powercode) \
+    DECL(eurochron_efth800) \
 
     /* Add new decoders here. */
 
diff --git a/man/man1/rtl_433.1 b/man/man1/rtl_433.1
index 0201cb08..88a042de 100644
--- a/man/man1/rtl_433.1
+++ b/man/man1/rtl_433.1
@@ -574,6 +574,9 @@ ERT
 .TP
 [ \fB151\fI\fP ]
 Visonic powercode
+.TP
+[ \fB152\fI\fP ]
+Eurochron EFTH\-800 temperature and humidity sensor
 
 * Disabled by default, use \-R n or \-G
 .SS "Input device selection"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cd57f6dc..22aac411 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,6 +57,7 @@ add_library(r_433 STATIC
     devices/ecowitt.c
     devices/efergy_e2_classic.c
     devices/efergy_optical.c
+    devices/efth800.c
     devices/elro_db286a.c
     devices/elv.c
     devices/emontx.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d756072a..00a3465f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,6 +56,7 @@ rtl_433_SOURCES      = abuf.c \
                        devices/ecowitt.c \
                        devices/efergy_e2_classic.c \
                        devices/efergy_optical.c \
+                       devices/efth800.c \
                        devices/elro_db286a.c \
                        devices/elv.c \
                        devices/emontx.c \
diff --git a/src/devices/efth800.c b/src/devices/efth800.c
new file mode 100644
index 00000000..d4c13693
--- /dev/null
+++ b/src/devices/efth800.c
@@ -0,0 +1,105 @@
+/** @file
+    Eurochron EFTH-800 temperature and humidity sensor.
+
+    Copyright (c) 2020 by Christian W. Zuckschwerdt <zany@triq.net>
+
+    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.
+*/
+/**
+Eurochron EFTH-800 temperature and humidity sensor.
+
+Wakeup of short pulse, 4x 970 us gap, 990 us pulse,
+packet gap of 4900 us,
+two packets of each
+4x 750 us pulse, 720 us gap, then
+(1-bit) 500 us pulse, 230 us gap or
+(0-bit) 250 us pulse, 480 us gap.
+
+Data layout:
+
+    ?ccc iiii  iiii iiii  bntt tttt  tttt ????  hhhh hhhh  xxxx xxxx
+
+- c:  3 bit channel valid channels are 0-7 (stands for channel 1-8)
+- i: 12 bit random id (changes on power-loss)
+- b:  1 bit battery indicator (0=>OK, 1=>LOW)
+- n:  1 bit temperature sign? (0=>negative, 1=>positive)
+- t: 10 bit signed temperature, scaled by 10
+- h:  8 bit relative humidity percentage (BCD)
+- x:  8 bit CRC-8, poly 0x31, init 0x00
+- ?: unknown (Bit 0, 28-31 always 0 ?)
+
+The sensor sends messages at intervals of about 57-58 seconds.
+*/
+
+#include "decoder.h"
+
+static int eurochron_efth800_decode(r_device *decoder, bitbuffer_t *bitbuffer)
+{
+    data_t *data;
+    int row;
+    uint8_t *b;
+    int id, channel, temp_raw, humidity, battery_low;
+    float temp_c;
+
+    /* Validation checks */
+    row = bitbuffer_find_repeated_row(bitbuffer, 2, 48);
+
+    if (row < 0) // repeated rows?
+        return DECODE_ABORT_EARLY;
+
+    if (bitbuffer->bits_per_row[row] > 49) // 48 bits per row?
+        return DECODE_ABORT_LENGTH;
+
+    b = bitbuffer->bb[row];
+    bitbuffer_invert(bitbuffer);
+
+    if (crc8(b, 6, 0x31, 0x00))
+        return DECODE_FAIL_MIC; // crc mismatch
+
+    /* Extract data */
+    channel     = (b[0] & 0x30) >> 4;
+    id          = ((b[0] & 0x0f) << 8) | b[1];
+    battery_low = b[2] >> 7;
+    temp_raw    = (int16_t)((b[2] & 0x3f) << 10) | ((b[3] & 0xf0) << 2); // sign-extend
+    temp_c      = (float)(temp_raw >> 6) * 0.1;
+    humidity    = (b[4] >> 4) * 10 + (b[4] & 0xf); // BCD
+
+    /* clang-format off */
+    data = data_make(
+            "model",            "",             DATA_STRING, "Eurochron-EFTH800",
+            "id",               "",             DATA_INT,    id,
+            "channel",          "",             DATA_INT,    channel + 1,
+            "battery_ok",       "Battery",      DATA_INT,    !battery_low,
+            "temperature_C",    "Temperature",  DATA_FORMAT, "%.01f C", DATA_DOUBLE, temp_c,
+            "humidity",         "Humidity",     DATA_INT,    humidity,
+            NULL);
+    /* clang-format on */
+
+    decoder_output_data(decoder, data);
+    return 1;
+}
+
+static char *output_fields[] = {
+        "model",
+        "id",
+        "channel",
+        "battery_ok",
+        "temperature_C",
+        "humidity",
+        NULL,
+};
+
+r_device eurochron_efth800 = {
+        .name          = "Eurochron EFTH-800 temperature and humidity sensor",
+        .modulation    = OOK_PULSE_PWM,
+        .short_width   = 250,
+        .long_width    = 500,
+        .sync_width    = 750,
+        .gap_limit     = 900,
+        .reset_limit   = 5500,
+        .decode_fn     = &eurochron_efth800_decode,
+        .fields        = output_fields,
+};
diff --git a/vs15/rtl_433.vcxproj b/vs15/rtl_433.vcxproj
index 3c5573a7..7c483432 100644
--- a/vs15/rtl_433.vcxproj
+++ b/vs15/rtl_433.vcxproj
@@ -180,6 +180,7 @@ COPY ..\..\libusb\MS64\dll\libusb*.dll $(TargetDir)</Command>
     <ClCompile Include="..\src\devices\ecowitt.c" />
     <ClCompile Include="..\src\devices\efergy_e2_classic.c" />
     <ClCompile Include="..\src\devices\efergy_optical.c" />
+    <ClCompile Include="..\src\devices\efth800.c" />
     <ClCompile Include="..\src\devices\elro_db286a.c" />
     <ClCompile Include="..\src\devices\elv.c" />
     <ClCompile Include="..\src\devices\emontx.c" />
diff --git a/vs15/rtl_433.vcxproj.filters b/vs15/rtl_433.vcxproj.filters
index dfc2da63..97bae590 100644
--- a/vs15/rtl_433.vcxproj.filters
+++ b/vs15/rtl_433.vcxproj.filters
@@ -277,6 +277,9 @@
     <ClCompile Include="..\src\devices\efergy_optical.c">
       <Filter>Source Files\devices</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\devices\efth800.c">
+      <Filter>Source Files\devices</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\devices\elro_db286a.c">
       <Filter>Source Files\devices</Filter>
     </ClCompile>