Bugfixes
[rtl-433.git] / src / devices / prologue.c
1 /* Prologue sensor protocol
2  * also FreeTec NC-7104 sensor for FreeTec Weatherstation NC-7102.
3  *
4  * the sensor sends 36 bits 7 times, before the first packet there is a sync pulse
5  * the packets are ppm modulated (distance coding) with a pulse of ~500 us
6  * followed by a short gap of ~2000 us for a 0 bit or a long ~4000 us gap for a
7  * 1 bit, the sync gap is ~9000 us.
8  *
9  * the data is grouped in 9 nibbles
10  * [model] [id0] [id1] [flags] [temp0] [temp1] [temp2] [humi0] [humi1]
11  *
12  * model is 1001 (9) or 0110 (5)
13  * id is a random id that is generated when the sensor starts, could include battery status
14  * the same batteries often generate the same id
15  * flags(3) is 0 the battery status, 1 ok, 0 low, first reading always say low
16  * flags(2) is 1 when the sensor sends a reading when pressing the button on the sensor
17  * flags(1,0)+1 forms the channel number that can be set by the sensor (1-3)
18  * temp is 12 bit signed scaled by 10
19  * humi0 is always 1100 (0x0C) if no humidity sensor is available
20  * humi1 is always 1100 (0x0C) if no humidity sensor is available
21  *
22  * The sensor can be bought at Clas Ohlson
23  */
24
25 #include "rtl_433.h"
26 #include "util.h"
27 #include "data.h"
28
29 static int prologue_callback(bitbuffer_t *bitbuffer) {
30     bitrow_t *bb = bitbuffer->bb;
31     data_t *data;
32
33     char time_str[LOCAL_TIME_BUFLEN];
34
35     uint8_t model;
36     uint8_t id;
37     uint8_t battery;
38     uint8_t button;
39     uint8_t channel;
40     int16_t temp;
41     uint8_t humidity;
42     int r = bitbuffer_find_repeated_row(bitbuffer, 3, 36);
43
44     if (r >= 0 &&
45         bitbuffer->bits_per_row[r] <= 37 && // we expect 36 bits but there might be a trailing 0 bit
46         ((bb[r][0]&0xF0) == 0x90 ||
47          (bb[r][0]&0xF0) == 0x50)) {
48
49         /* Get time now */
50         local_time_str(0, time_str);
51
52         /* Prologue sensor */
53         model = bb[r][0] >> 4;
54         id = ((bb[r][0]&0x0F)<<4) | ((bb[r][1]&0xF0)>>4);
55         battery = bb[r][1]&0x08;
56         button = (bb[r][1]&0x04) >> 2;
57         channel = (bb[r][1]&0x03) + 1;
58         temp = (int16_t)((uint16_t)(bb[r][2] << 8) | (bb[r][3]&0xF0));
59         temp = temp >> 4;
60         humidity = ((bb[r][3]&0x0F) << 4) | (bb[r][4] >> 4);
61
62         data = data_make("time",          "",            DATA_STRING, time_str,
63                          "model",         "",            DATA_STRING, "Prologue sensor",
64                          "id",            "",            DATA_INT, model, // this should be named "type"
65                          "rid",           "",            DATA_INT, id, // this should be named "id"
66                          "channel",       "Channel",     DATA_INT, channel,
67                          "battery",       "Battery",     DATA_STRING, battery ? "OK" : "LOW",
68                          "button",        "Button",      DATA_INT, button,
69                          "temperature_C", "Temperature", DATA_FORMAT, "%.02f C", DATA_DOUBLE, temp/10.0,
70                          "humidity",      "Humidity",    DATA_FORMAT, "%u %%", DATA_INT, humidity,
71                           NULL);
72         data_acquired_handler(data);
73
74         return 1;
75     }
76     return 0;
77 }
78
79 static char *output_fields[] = {
80     "time",
81     "model",
82     "id",
83     "rid",
84     "channel",
85     "battery",
86     "button",
87     "temperature_C",
88     "humidity",
89     NULL
90 };
91
92 r_device prologue = {
93     .name           = "Prologue Temperature Sensor",
94     .modulation     = OOK_PULSE_PPM_RAW,
95     .short_limit    = 3500,
96     .long_limit     = 7000,
97     .reset_limit    = 10000,
98     .json_callback  = &prologue_callback,
99     .disabled       = 0,
100     .demod_arg      = 0,
101     .fields         = output_fields
102 };