3  * *** Fine Offset WH1050 Weather Station ***
 
   7  * This module is a cut-down version of the WH1080 decoder.
 
   8  * The WH1050 sensor unit is like the WH1080 unit except it has no
 
   9  * wind direction sensor or time receiver.
 
  10  * Other than omitting the ynused code, the differences are the message length
 
  11  * and the location of the battery-low bit.
 
  13  * The original module was by
 
  15  * 2016 Nicola Quiriti ('ovrheat')
 
  23  * This weather station is based on an indoor touchscreen receiver, and on a 5+1 outdoor wireless sensors group
 
  24  * (rain, wind speed, temperature, humidity.
 
  25  * See the product page here: http://www.foshk.com/Weather_Professional/WH1070.html (The 1050 model has no radio clock)
 
  27  * Please note that the pressure sensor (barometer) is enclosed in the indoor console unit, NOT in the outdoor
 
  28  * wireless sensors group.
 
  29  * That's why it's NOT possible to get pressure data by wireless communication. If you need pressure data you should try
 
  30  * an Arduino/Raspberry solution wired with a BMP180 or BMP085 sensor.
 
  32  * Data are trasmitted in a 48 seconds cycle (data packet, then wait 48 seconds, then data packet...).
 
  34  * The 'Total rainfall' field is a cumulative counter, increased by 0.3 millimeters of rain at once.
 
  50 static unsigned short get_device_id(const uint8_t* br) {
 
  51         return (br[1] << 4 & 0xf0 ) | (br[2] >> 4);
 
  54 static char* get_battery(const uint8_t* br) {
 
  55         if (!(br[2] & 0x04)) {
 
  62 // ------------ WEATHER SENSORS DECODING ----------------------------------------------------
 
  64 static float get_temperature(const uint8_t* br) {
 
  65     const int temp_raw = (br[2] << 8) + br[3];
 
  66     return ((temp_raw & 0x03ff) - 0x190) / 10.0;
 
  69 static int get_humidity(const uint8_t* br) {
 
  73 static float get_wind_speed_raw(const uint8_t* br) {
 
  77 static float get_wind_avg_ms(const uint8_t* br) {
 
  78     return (br[5] * 34.0f) / 100; // Meters/sec.
 
  81 static float get_wind_avg_mph(const uint8_t* br) {
 
  82     return ((br[5] * 34.0f) / 100) * 2.23693629f; // Mph
 
  85 static float get_wind_avg_kmh(const uint8_t* br) {
 
  86     return ((br[5] * 34.0f) / 100) * 3.6f; // Km/h
 
  89 static float get_wind_avg_knot(const uint8_t* br) {
 
  90     return ((br[5] * 34.0f) / 100) * 1.94384f; // Knots
 
  93 static float get_wind_gust_raw(const uint8_t* br) {
 
  97 static float get_wind_gust_ms(const uint8_t* br) {
 
  98     return (br[6] * 34.0f) / 100; // Meters/sec.
 
 101 static float get_wind_gust_mph(const uint8_t* br) {
 
 102     return ((br[6] * 34.0f) / 100) * 2.23693629f; // Mph
 
 106 static float get_wind_gust_kmh(const uint8_t* br) {
 
 107     return ((br[6] * 34.0f) / 100) * 3.6f; // Km/h
 
 110 static float get_wind_gust_knot(const uint8_t* br) {
 
 111     return ((br[6] * 34.0f) / 100) * 1.94384f; // Knots
 
 114 static float get_rainfall(const uint8_t* br) {
 
 115         return ((((unsigned short)br[7] & 0x0f) << 8) | br[8]) * 0.3f;
 
 119 //-------------------------------------------------------------------------------------
 
 120 //-------------------------------------------------------------------------------------
 
 124 static int fineoffset_wh1050_callback(bitbuffer_t *bitbuffer) {
 
 126     char time_str[LOCAL_TIME_BUFLEN];
 
 127     local_time_str(0, time_str);
 
 129     if (bitbuffer->num_rows != 1) {
 
 132     if (bitbuffer->bits_per_row[0] != 80) {
 
 136     const uint8_t *br = bitbuffer->bb[0];
 
 143     if (br[9] != crc8(br, 9, CRC_POLY, CRC_INIT)) {
 
 148 //---------------------------------------------------------------------------------------
 
 149 //-------- GETTING WEATHER SENSORS DATA -------------------------------------------------
 
 151     const float temperature = get_temperature(br);
 
 152     const int humidity = get_humidity(br);
 
 154         // Select which metric system for *wind avg speed* and *wind gust* :
 
 156         // Wind average speed :
 
 158         //const float speed = get_wind_avg_ms((br)   // <--- Data will be shown in Meters/sec.
 
 159         //const float speed = get_wind_avg_mph((br)  // <--- Data will be shown in Mph
 
 160         const float speed = get_wind_avg_kmh(br);  // <--- Data will be shown in Km/h
 
 161         //const float speed = get_wind_avg_knot((br) // <--- Data will be shown in Knots
 
 166     //const float gust = get_wind_gust_ms(br);   // <--- Data will be shown in Meters/sec.
 
 167         //const float gust = get_wind_gust_mph(br);  // <--- Data will be shown in Mph
 
 168         const float gust = get_wind_gust_kmh(br);  // <--- Data will be shown in km/h
 
 169         //const float gust = get_wind_gust_knot(br); // <--- Data will be shown in Knots
 
 171     const float rain = get_rainfall(br);
 
 172     const int device_id = get_device_id(br);
 
 173         const char* battery = get_battery(br);
 
 175 //---------------------------------------------------------------------------------------
 
 176 //--------- PRESENTING DATA --------------------------------------------------------------
 
 178     data = data_make("time",            "",             DATA_STRING, time_str,
 
 179                      "model",           "",             DATA_STRING, "Fine Offset WH1050 weather station",
 
 180                      "id",            "StationID",      DATA_FORMAT, "%04X",    DATA_INT,    device_id,
 
 181                      "temperature_C", "Temperature",    DATA_FORMAT, "%.01f C", DATA_DOUBLE, temperature,
 
 182                      "humidity",      "Humidity",       DATA_FORMAT, "%u %%",   DATA_INT,    humidity,
 
 183                      "speed",         "Wind avg speed", DATA_FORMAT, "%.02f",   DATA_DOUBLE, speed,
 
 184                      "gust",          "Wind gust",      DATA_FORMAT, "%.02f",   DATA_DOUBLE, gust,
 
 185                      "rain",          "Total rainfall", DATA_FORMAT, "%.01f",   DATA_DOUBLE, rain,
 
 186                      "battery",       "Battery",        DATA_STRING, battery, // Unsure about Battery byte...
 
 188     data_acquired_handler(data);
 
 192 static char *output_fields[] = {
 
 205 r_device fineoffset_wh1050 = {
 
 206     .name           = "Fine Offset WH1050 Weather Station",
 
 207     .modulation     = OOK_PULSE_PWM_RAW,
 
 210     .reset_limit    = 10520,
 
 211     .json_callback  = &fineoffset_wh1050_callback,
 
 214     .fields         = output_fields,