Редизайн на основе текущей ветки мейнстрима + новые устройства.
[rtl-433.git] / src / devices / fineoffset_wh1050.c
diff --git a/src/devices/fineoffset_wh1050.c b/src/devices/fineoffset_wh1050.c
new file mode 100644 (file)
index 0000000..a4a3d4e
--- /dev/null
@@ -0,0 +1,215 @@
+
+/*
+ * *** Fine Offset WH1050 Weather Station ***
+ * (aka )
+ * (aka .....)
+ *
+ * This module is a cut-down version of the WH1080 decoder.
+ * The WH1050 sensor unit is like the WH1080 unit except it has no
+ * wind direction sensor or time receiver.
+ * Other than omitting the ynused code, the differences are the message length
+ * and the location of the battery-low bit.
+ *
+ * The original module was by
+ *
+ * 2016 Nicola Quiriti ('ovrheat')
+ *
+ * Modifications by
+ *
+ * 2016 Don More
+ *
+ *********************
+ *
+ * This weather station is based on an indoor touchscreen receiver, and on a 5+1 outdoor wireless sensors group
+ * (rain, wind speed, temperature, humidity.
+ * See the product page here: http://www.foshk.com/Weather_Professional/WH1070.html (The 1050 model has no radio clock)
+ *
+ * Please note that the pressure sensor (barometer) is enclosed in the indoor console unit, NOT in the outdoor
+ * wireless sensors group.
+ * That's why it's NOT possible to get pressure data by wireless communication. If you need pressure data you should try
+ * an Arduino/Raspberry solution wired with a BMP180 or BMP085 sensor.
+ *
+ * Data are trasmitted in a 48 seconds cycle (data packet, then wait 48 seconds, then data packet...).
+ *
+ * The 'Total rainfall' field is a cumulative counter, increased by 0.3 millimeters of rain at once.
+ *
+ *
+ *
+ *
+ */
+
+
+#include "data.h"
+#include "rtl_433.h"
+#include "util.h"
+#include "math.h"
+
+#define CRC_POLY 0x31
+#define CRC_INIT 0xff
+
+static unsigned short get_device_id(const uint8_t* br) {
+       return (br[1] << 4 & 0xf0 ) | (br[2] >> 4);
+}
+
+static char* get_battery(const uint8_t* br) {
+       if (!(br[2] & 0x04)) {
+               return "OK";
+       } else {
+               return "LOW";
+       }
+}
+
+// ------------ WEATHER SENSORS DECODING ----------------------------------------------------
+
+static float get_temperature(const uint8_t* br) {
+    const int temp_raw = (br[2] << 8) + br[3];
+    return ((temp_raw & 0x03ff) - 0x190) / 10.0;
+}
+
+static int get_humidity(const uint8_t* br) {
+    return br[4];
+}
+
+static float get_wind_speed_raw(const uint8_t* br) {
+    return br[5]; // Raw
+}
+
+static float get_wind_avg_ms(const uint8_t* br) {
+    return (br[5] * 34.0f) / 100; // Meters/sec.
+}
+
+static float get_wind_avg_mph(const uint8_t* br) {
+    return ((br[5] * 34.0f) / 100) * 2.23693629f; // Mph
+}
+
+static float get_wind_avg_kmh(const uint8_t* br) {
+    return ((br[5] * 34.0f) / 100) * 3.6f; // Km/h
+}
+
+static float get_wind_avg_knot(const uint8_t* br) {
+    return ((br[5] * 34.0f) / 100) * 1.94384f; // Knots
+}
+
+static float get_wind_gust_raw(const uint8_t* br) {
+    return br[6]; // Raw
+}
+
+static float get_wind_gust_ms(const uint8_t* br) {
+    return (br[6] * 34.0f) / 100; // Meters/sec.
+}
+
+static float get_wind_gust_mph(const uint8_t* br) {
+    return ((br[6] * 34.0f) / 100) * 2.23693629f; // Mph
+
+}
+
+static float get_wind_gust_kmh(const uint8_t* br) {
+    return ((br[6] * 34.0f) / 100) * 3.6f; // Km/h
+}
+
+static float get_wind_gust_knot(const uint8_t* br) {
+    return ((br[6] * 34.0f) / 100) * 1.94384f; // Knots
+}
+
+static float get_rainfall(const uint8_t* br) {
+       return ((((unsigned short)br[7] & 0x0f) << 8) | br[8]) * 0.3f;
+}
+
+
+//-------------------------------------------------------------------------------------
+//-------------------------------------------------------------------------------------
+
+
+
+static int fineoffset_wh1050_callback(bitbuffer_t *bitbuffer) {
+    data_t *data;
+    char time_str[LOCAL_TIME_BUFLEN];
+    local_time_str(0, time_str);
+
+    if (bitbuffer->num_rows != 1) {
+        return 0;
+    }
+    if (bitbuffer->bits_per_row[0] != 80) {
+        return 0;
+    }
+
+    const uint8_t *br = bitbuffer->bb[0];
+
+    if (br[0] != 0xff) {
+        // preamble missing
+        return 0;
+    }
+
+    if (br[9] != crc8(br, 9, CRC_POLY, CRC_INIT)) {
+        // crc mismatch
+        return 0;
+    }
+
+//---------------------------------------------------------------------------------------
+//-------- GETTING WEATHER SENSORS DATA -------------------------------------------------
+
+    const float temperature = get_temperature(br);
+    const int humidity = get_humidity(br);
+
+       // Select which metric system for *wind avg speed* and *wind gust* :
+
+       // Wind average speed :
+
+       //const float speed = get_wind_avg_ms((br)   // <--- Data will be shown in Meters/sec.
+       //const float speed = get_wind_avg_mph((br)  // <--- Data will be shown in Mph
+       const float speed = get_wind_avg_kmh(br);  // <--- Data will be shown in Km/h
+       //const float speed = get_wind_avg_knot((br) // <--- Data will be shown in Knots
+
+
+       // Wind gust speed :
+
+    //const float gust = get_wind_gust_ms(br);   // <--- Data will be shown in Meters/sec.
+       //const float gust = get_wind_gust_mph(br);  // <--- Data will be shown in Mph
+       const float gust = get_wind_gust_kmh(br);  // <--- Data will be shown in km/h
+       //const float gust = get_wind_gust_knot(br); // <--- Data will be shown in Knots
+
+    const float rain = get_rainfall(br);
+    const int device_id = get_device_id(br);
+       const char* battery = get_battery(br);
+
+//---------------------------------------------------------------------------------------
+//--------- PRESENTING DATA --------------------------------------------------------------
+
+    data = data_make("time",           "",             DATA_STRING, time_str,
+                     "model",          "",             DATA_STRING, "Fine Offset WH1050 weather station",
+                     "id",            "StationID",     DATA_FORMAT, "%04X",    DATA_INT,    device_id,
+                     "temperature_C", "Temperature",   DATA_FORMAT, "%.01f C", DATA_DOUBLE, temperature,
+                     "humidity",      "Humidity",      DATA_FORMAT, "%u %%",   DATA_INT,    humidity,
+                     "speed",         "Wind avg speed",        DATA_FORMAT, "%.02f",   DATA_DOUBLE, speed,
+                     "gust",          "Wind gust",     DATA_FORMAT, "%.02f",   DATA_DOUBLE, gust,
+                     "rain",          "Total rainfall",        DATA_FORMAT, "%.01f",   DATA_DOUBLE, rain,
+                    "battery",       "Battery",        DATA_STRING, battery, // Unsure about Battery byte...
+                     NULL);
+    data_acquired_handler(data);
+    return 1;
+}
+
+static char *output_fields[] = {
+       "time",
+       "model",
+       "id",
+       "temperature_C",
+       "humidity",
+       "speed",
+       "gust",
+       "rain",
+       "battery",
+       NULL
+};
+
+r_device fineoffset_wh1050 = {
+    .name           = "Fine Offset WH1050 Weather Station",
+    .modulation     = OOK_PULSE_PWM_RAW,
+    .short_limit    = 976,
+    .long_limit     = 2400,
+    .reset_limit    = 10520,
+    .json_callback  = &fineoffset_wh1050_callback,
+    .disabled       = 0,
+    .demod_arg      = 0,
+    .fields         = output_fields,
+};