4 /* Currently this can decode the temperature and id from Rubicson sensors
6 * the sensor sends 36 bits 12 times pwm modulated
7 * the data is grouped into 9 nibles
8 * [id0] [id1], [bat|unk1|chan1|chan2] [temp0], [temp1] [temp2], [F] [crc1], [crc2]
10 * The id changes when the battery is changed in the sensor.
11 * bat bit is 1 if battery is ok, 0 if battery is low
12 * chan1 and chan2 forms a 2bit value for the used channel
13 * unk1 is always 0 probably unused
14 * temp is 12 bit signed scaled by 10
16 * crc1 and crc2 forms a 8-bit crc
18 * The sensor can be bought at Kjell&Co
22 /* Working routine for checking the crc, lots of magic but it works */
24 //static uint8_t rp[] = {0xb8, 0x80, 0xea, 0xfe, 0x80};
25 static uint8_t rp[] = {0xea, 0x8f, 0x6a, 0xfa, 0x50};
27 int rubicson_crc_check(bitrow_t *bb) {
32 // diff against ref packet
34 diff[0] = rp[0]^bb[1][0];
35 diff[1] = rp[1]^bb[1][1];
36 diff[2] = rp[2]^bb[1][2];
37 diff[3] = rp[3]^bb[1][3];
38 diff[4] = rp[4]^bb[1][4];
40 // fprintf(stdout, "%02x %02x %02x %02x %02x\n",rp[0],rp[1],rp[2],rp[3],rp[4]);
41 // fprintf(stdout, "%02x %02x %02x %02x %02x\n",bb[1][0],bb[1][1],bb[1][2],bb[1][3],bb[1][4]);
42 // fprintf(stdout, "%02x %02x %02x %02x %02x\n",diff[0],diff[1],diff[2],diff[3],diff[4]);
44 for (crc = 0, w = 0xf1, i = 0; i<7 ; i++){
45 uint8_t c = diff[i/2];
46 unsigned digit = (i&1) ? c&0xF : (c&0xF0)>>4;
51 w = (w >> 1) ^ ((w & 1) ? 0x98: 0);
54 if (crc == (((diff[3]<<4)&0xF0) | (diff[4]>>4)))
55 // printf ("\ncrc ok: %x\n", crc);
58 // printf ("\ncrc fail: %x\n", crc);
64 static int rubicson_callback(bitbuffer_t *bitbuffer) {
65 bitrow_t *bb = bitbuffer->bb;
66 int temperature_before_dec;
67 int temperature_after_dec, i;
69 int8_t rh, csum, csum_calc, sum=0;
70 unsigned bits = bitbuffer->bits_per_row[0];
73 char time_str[LOCAL_TIME_BUFLEN];
82 if (rubicson_crc_check(bb)) {
83 local_time_str(0, time_str);
85 /* Nible 3,4,5 contains 12 bits of temperature
86 * The temerature is signed and scaled by 10 */
87 temp = (int16_t)((uint16_t)(bb[0][1] << 12) | (bb[0][2] << 4));
90 channel = ((bb[0][1]&0x30)>>4)+1;
91 battery = (bb[0][1]&0x80);
93 temp_c = (float) temp / 10.0;
95 data = data_make("time", "", DATA_STRING, time_str,
96 "model", "", DATA_STRING, "Rubicson Temperature Sensor",
97 "id", "House Code", DATA_INT, sensor_id,
98 "channel", "Channel", DATA_INT, channel,
99 "battery", "Battery", DATA_STRING, battery ? "OK" : "LOW",
100 "temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
101 "crc", "CRC", DATA_STRING, "OK",
103 data_acquired_handler(data);
110 static char *output_fields[] = {
122 // timings based on samp_rate=1024000
123 r_device rubicson = {
124 .name = "Rubicson Temperature Sensor",
125 .modulation = OOK_PULSE_PPM_RAW,
126 .short_limit = 488+970, // Gaps: Short 976µs, Long 1940µs, Sync 4000µs
127 .long_limit = 970+2000, // Pulse: 500µs (Initial pulse in each package is 388µs)
128 .reset_limit = 4800, // Two initial pulses and a gap of 9120µs is filtered out
129 .json_callback = &rubicson_callback,
132 .fields = output_fields,