Редизайн на основе текущей ветки мейнстрима + новые устройства.
[rtl-433.git] / src / devices / alecto.c
index 00673abc6f3874e234a9cc053d4f142e8ecdf3ab..42cbbd5fd7822bf527ec417ca18c04737638da04 100644 (file)
@@ -1,4 +1,6 @@
 #include "rtl_433.h"
 #include "rtl_433.h"
+#include "data.h"
+#include "util.h"
 
 /* Documentation also at http://www.tfd.hu/tfdhu/files/wsprotocol/auriol_protocol_v20.pdf
  * Message Format: (9 nibbles, 36 bits):
 
 /* Documentation also at http://www.tfd.hu/tfdhu/files/wsprotocol/auriol_protocol_v20.pdf
  * Message Format: (9 nibbles, 36 bits):
  *   F = Checksum
  *********************************************************************************************
  */
  *   F = Checksum
  *********************************************************************************************
  */
-uint8_t reverse8(uint8_t x) {
-    x = (x & 0xF0) >> 4 | (x & 0x0F) << 4;
-    x = (x & 0xCC) >> 2 | (x & 0x33) << 2;
-    x = (x & 0xAA) >> 1 | (x & 0x55) << 1;
-    return x;
-}
 
 uint8_t bcd_decode8(uint8_t x) {
     return ((x & 0xF0) >> 4) * 10 + (x & 0x0F);
 }
 
 
 uint8_t bcd_decode8(uint8_t x) {
     return ((x & 0xF0) >> 4) * 10 + (x & 0x0F);
 }
 
-static int alectov1_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_per_row[BITBUF_ROWS]) {
+static int alectov1_callback(bitbuffer_t *bitbuffer) {
+    bitrow_t *bb = bitbuffer->bb;
     int temperature_before_dec;
     int temperature_after_dec;
     int16_t temp;
     uint8_t humidity, csum = 0, csum2 = 0;
     int i;
     int temperature_before_dec;
     int temperature_after_dec;
     int16_t temp;
     uint8_t humidity, csum = 0, csum2 = 0;
     int i;
+
+    data_t *data;
+    char time_str[LOCAL_TIME_BUFLEN];
+    unsigned bits = bitbuffer->bits_per_row[1];
+
+    if (bits != 36)
+        return 0;
+
+    local_time_str(0, time_str);
+
     if (bb[1][0] == bb[5][0] && bb[2][0] == bb[6][0] && (bb[1][4] & 0xf) == 0 && (bb[5][4] & 0xf) == 0
             && (bb[5][0] != 0 && bb[5][1] != 0)) {
 
     if (bb[1][0] == bb[5][0] && bb[2][0] == bb[6][0] && (bb[1][4] & 0xf) == 0 && (bb[5][4] & 0xf) == 0
             && (bb[5][0] != 0 && bb[5][1] != 0)) {
 
@@ -81,21 +88,31 @@ static int alectov1_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_
         csum2 = reverse8((csum2 & 0xf) << 4);
         /* Quit if checksup does not work out */
         if (csum != (bb[1][4] >> 4) || csum2 != (bb[5][4] >> 4)) {
         csum2 = reverse8((csum2 & 0xf) << 4);
         /* Quit if checksup does not work out */
         if (csum != (bb[1][4] >> 4) || csum2 != (bb[5][4] >> 4)) {
-            fprintf(stderr, "\nAlectoV1 CRC error");
+            //fprintf(stdout, "\nAlectoV1 CRC error");
+            if(debug_output) {
+                fprintf(stderr,
+                "%s AlectoV1 Checksum/Parity error\n",
+                time_str);
+            }
             return 0;
         } //Invalid checksum
 
 
         uint8_t wind = 0;
             return 0;
         } //Invalid checksum
 
 
         uint8_t wind = 0;
+        uint8_t channel = (bb[1][0] & 0xc) >> 2;
+        uint8_t sensor_id = reverse8(bb[1][0]);
+        uint8_t battery_low = bb[1][1]&0x80;
 
         if ((bb[1][1] & 0xe0) == 0x60) {
             wind = ((bb[1][1] & 0xf) == 0xc) ? 0 : 1;
 
 
         if ((bb[1][1] & 0xe0) == 0x60) {
             wind = ((bb[1][1] & 0xf) == 0xc) ? 0 : 1;
 
-            fprintf(stdout, "SENSOR:TYPE=ALECTO_%s,", wind ? "WIND" : "RAIN_GAUGE");
-            fprintf(stdout, "ID=%d,", reverse8(bb[1][0]));
-            fprintf(stdout, "BUTTON=%d,", bb[1][1]&0x10 ? 1 : 0);
-            fprintf(stdout, "BATTERY=%s,", bb[1][1]&0x80 ? "LOW" : "OK");
+            //left out data (not needed):
+            //bb[1][1]&0x10 ? "timed event":"Button generated ");
+            //fprintf(stdout, "Protocol      = AlectoV1 bpr1: %d bpr2: %d\n", bits_per_row[1], bits_per_row[5]);
+            //fprintf(stdout, "Button        = %d\n", bb[1][1]&0x10 ? 1 : 0);
             if (wind) {
             if (wind) {
+               // Wind sensor
                 int skip = -1;
                 /* Untested code written according to the specification, may not decode correctly  */
                 if ((bb[1][1]&0xe) == 0x8 && bb[1][2] == 0) {
                 int skip = -1;
                 /* Untested code written according to the specification, may not decode correctly  */
                 if ((bb[1][1]&0xe) == 0x8 && bb[1][2] == 0) {
@@ -107,14 +124,30 @@ static int alectov1_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_
                     double speed = reverse8(bb[1 + skip][3]);
                     double gust = reverse8(bb[5 + skip][3]);
                     int direction = (reverse8(bb[5 + skip][2]) << 1) | (bb[5 + skip][1] & 0x1);
                     double speed = reverse8(bb[1 + skip][3]);
                     double gust = reverse8(bb[5 + skip][3]);
                     int direction = (reverse8(bb[5 + skip][2]) << 1) | (bb[5 + skip][1] & 0x1);
-                    fprintf(stdout, "WINDSPEED=%.0f,", speed);
-                    fprintf(stdout, "WINDGUST=%.0f,", gust);
-                    fprintf(stdout, "WINDDIRECTION=%.2i\n", direction);
+
+                       data = data_make("time",          "",           DATA_STRING, time_str,
+                                                                       "model",          "",           DATA_STRING, "AlectoV1 Wind Sensor",
+                                                                       "id",             "House Code", DATA_INT,    sensor_id,
+                                                                       "channel",        "Channel",    DATA_INT,    channel,
+                                                                       "battery",        "Battery",    DATA_STRING, battery_low ? "LOW" : "OK",
+                                                                       "wind_speed",     "Wind speed", DATA_FORMAT, "%.2f m/s", DATA_DOUBLE, speed * 0.2F,
+                                                                       "wind_gust",      "Wind gust",  DATA_FORMAT, "%.2f m/s", DATA_DOUBLE, gust * 0.2F,
+                                                                       "wind_direction", "Direction",  DATA_INT,    direction,
+                                                                       NULL);
+                               data_acquired_handler(data);
                 }
             } else {
                 }
             } else {
-                /* Untested code written according to the specification, may not decode correctly  */
-                double rain_mm = (reverse8(bb[1][2]) + (reverse8(bb[1][3] << 8))) * 0.25;
-                fprintf(stdout, "RAINFALL=%f\n", rain_mm);
+                // Rain sensor
+                double rain_mm = ((reverse8(bb[1][3]) << 8)+reverse8(bb[1][2])) * 0.25F;
+
+               data = data_make("time",         "",           DATA_STRING, time_str,
+                                                               "model",         "",           DATA_STRING, "AlectoV1 Rain Sensor",
+                                                               "id",            "House Code", DATA_INT,    sensor_id,
+                                                               "channel",       "Channel",    DATA_INT,    channel,
+                                                               "battery",       "Battery",    DATA_STRING, battery_low ? "LOW" : "OK",
+                                                           "rain_total",    "Total Rain", DATA_FORMAT, "%.02f mm", DATA_DOUBLE, rain_mm,
+                                                           NULL);
+                           data_acquired_handler(data);
             }
         } else if (bb[2][0] == bb[3][0] && bb[3][0] == bb[4][0] && bb[4][0] == bb[5][0] &&
                 bb[5][0] == bb[6][0] && (bb[3][4] & 0xf) == 0 && (bb[5][4] & 0xf) == 0) {
             }
         } else if (bb[2][0] == bb[3][0] && bb[3][0] == bb[4][0] && bb[4][0] == bb[5][0] &&
                 bb[5][0] == bb[6][0] && (bb[3][4] & 0xf) == 0 && (bb[5][4] & 0xf) == 0) {
@@ -123,39 +156,56 @@ static int alectov1_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_
             if ((temp & 0x800) != 0) {
                 temp |= 0xf000;
             }
             if ((temp & 0x800) != 0) {
                 temp |= 0xf000;
             }
-            temperature_before_dec = abs(temp / 10);
-            temperature_after_dec = abs(temp % 10);
             humidity = bcd_decode8(reverse8(bb[1][3]));
             humidity = bcd_decode8(reverse8(bb[1][3]));
-            fprintf(stdout, "SENSOR:TYPE=ALECTO_TEMP,");
-            fprintf(stdout, "ID=%d,", reverse8(bb[1][0]));
-            fprintf(stdout, "CHANNEL== %d,", (bb[1][0] & 0xc) >> 2);
-            fprintf(stdout, "BUTTON=%d,", bb[1][1]&0x10 ? 1 : 0);
-            fprintf(stdout, "BATTERY=%s,", bb[1][1]&0x80 ? "Low" : "OK");
-            fprintf(stdout, "TEMPERATURE=%s%d.%d,", temp < 0 ? "-" : "", temperature_before_dec, temperature_after_dec);
-            fprintf(stdout, "HUMIDITY=%d\n", humidity);
-        }
-        fprintf(stderr, "Checksum      = %01x (calculated %01x)\n", bb[1][4] >> 4, csum);
+            if (humidity>100) return 0;//extra detection false positive!! prologue is also 36bits and sometimes detected as alecto            
 
 
-        fprintf(stderr, "Received Data = %02x %02x %02x %02x %02x\n", bb[1][0], bb[1][1], bb[1][2], bb[1][3], bb[1][4]);
-        if (wind) fprintf(stderr, "Rcvd Data 2   = %02x %02x %02x %02x %02x\n", bb[5][0], bb[5][1], bb[5][2], bb[5][3], bb[5][4]);
-        /*
-         * fprintf(stderr, "L2M: %02x %02x %02x %02x %02x\n",reverse8(bb[1][0]),reverse8(bb[1][1]),reverse8(bb[1][2]),reverse8(bb[1][3]),reverse8(bb[1][4]));
+            data = data_make("time",         "",            DATA_STRING, time_str,
+                                                       "model",         "",            DATA_STRING, "AlectoV1 Temperature Sensor",
+                                                       "id",            "House Code",  DATA_INT,    sensor_id,
+                                                       "channel",       "Channel",     DATA_INT,    channel,
+                                                       "battery",       "Battery",     DATA_STRING, battery_low ? "LOW" : "OK",
+                                                       "temperature_C", "Temperature", DATA_FORMAT, "%.02f C", DATA_DOUBLE, (float) temp / 10.0F,
+                                                       "humidity",      "Humidity",    DATA_FORMAT, "%u %%",   DATA_INT, humidity,
+                                                       NULL);
+                       data_acquired_handler(data);
+        }        
+        if (debug_output){
+           fprintf(stdout, "Checksum      = %01x (calculated %01x)\n", bb[1][4] >> 4, csum);
+           fprintf(stdout, "Received Data = %02x %02x %02x %02x %02x\n", bb[1][0], bb[1][1], bb[1][2], bb[1][3], bb[1][4]);
+           if (wind) fprintf(stdout, "Rcvd Data 2   = %02x %02x %02x %02x %02x\n", bb[5][0], bb[5][1], bb[5][2], bb[5][3], bb[5][4]);
+         /*
+         * fprintf(stdout, "L2M: %02x %02x %02x %02x %02x\n",reverse8(bb[1][0]),reverse8(bb[1][1]),reverse8(bb[1][2]),reverse8(bb[1][3]),reverse8(bb[1][4]));
          */
          */
-        if (debug_output)
-            debug_callback(bb, bits_per_row);
-
+        }
         return 1;
     }
     return 0;
 }
 
         return 1;
     }
     return 0;
 }
 
+static char *output_fields[] = {
+       "time",
+       "model",
+       "id",
+       "channel",
+       "battery",
+       "temperature_C",
+       "humidity",
+       "rain_total",
+       "wind_speed",
+       "wind_gust",
+       "wind_direction",
+       NULL
+};
+
 //Timing based on 250000
 r_device alectov1 = {
 //Timing based on 250000
 r_device alectov1 = {
-    /* .id             = */ 13,
-    /* .name           = */ "AlectoV1 Weather Sensor",
-    /* .modulation     = */ OOK_PWM_D,
-    /* .short_limit    = */ 3500 / 4, //875
-    /* .long_limit     = */ 7000 / 4, //1750
-    /* .reset_limit    = */ 15000 / 4, //3750
-    /* .json_callback  = */ &alectov1_callback,
+    .name           = "AlectoV1 Weather Sensor (Alecto WS3500 WS4500 Ventus W155/W044 Oregon)",
+    .modulation     = OOK_PULSE_PPM_RAW,
+    .short_limit    = 3500,
+    .long_limit     = 7000,
+    .reset_limit    = 10000,
+    .json_callback  = &alectov1_callback,
+    .disabled       = 0,
+    .demod_arg      = 0,
+    .fields         = output_fields
 };
 };