6 get_temperature (uint8_t * msg)
10 temp_f |= ((msg[5] & 0xf0) >> 4);
12 return (temp_f / 10.0f);
16 get_humidity (uint8_t * msg)
18 uint8_t humidity = ( (msg[5] & 0x0f) << 4) | ((msg[6] & 0xf0) >> 4);
23 calculate_checksum (uint8_t *buff, int length)
26 uint8_t checksum = 0x64;
30 for (byteCnt=0; byteCnt < length; byteCnt++)
35 for (bitCnt = 7; bitCnt >= 0 ; bitCnt--)
41 mask = (mask >> 1 ) | (mask << 7);
47 // XOR mask into checksum if data bit is 1
59 validate_checksum (uint8_t * msg, int len)
61 uint8_t expected = ((msg[6] & 0x0f) << 4) | ((msg[7] & 0xf0) >> 4);
64 pkt[0] = ((msg[1] & 0x0f) << 4) | ((msg[2] & 0xf0) >> 4);
65 pkt[1] = ((msg[2] & 0x0f) << 4) | ((msg[3] & 0xf0) >> 4);
66 pkt[2] = ((msg[3] & 0x0f) << 4) | ((msg[4] & 0xf0) >> 4);
67 pkt[3] = ((msg[4] & 0x0f) << 4) | ((msg[5] & 0xf0) >> 4);
68 pkt[4] = ((msg[5] & 0x0f) << 4) | ((msg[6] & 0xf0) >> 4);
69 uint8_t calculated = calculate_checksum (pkt, 5);
71 if (expected == calculated)
74 if (debug_output >= 1) {
75 fprintf(stderr, "Checksum error in Ambient Weather message. Expected: %02x Calculated: %02x\n", expected, calculated);
76 fprintf(stderr, "Message: "); int i; for (i=0; i<len; i++) fprintf(stderr, "%02x ", msg[i]); fprintf(stderr, "\n\n");
83 get_device_id (uint8_t * msg)
85 uint16_t deviceID = ( (msg[2] & 0x0f) << 4) | ((msg[3] & 0xf0) >> 4);
90 get_channel (uint8_t * msg)
92 uint16_t channel = (msg[3] & 0x07) + 1;
97 get_battery_status(uint8_t * msg)
99 uint8_t status = (msg[3] & 8) != 0;
100 return status; // if not zero, battery is low
105 ambient_weather_parser (bitbuffer_t *bitbuffer)
107 bitrow_t *bb = bitbuffer->bb;
112 uint8_t isBatteryLow;
114 char time_str[LOCAL_TIME_BUFLEN];
116 local_time_str(0, time_str);
118 if(bitbuffer->bits_per_row[0] != 195) // There seems to be 195 bits in a correct message
121 /* shift all the bits left 1 to align the fields */
123 for (i = 0; i < BITBUF_COLS-1; i++) {
124 uint8_t bits1 = bb[0][i] << 1;
125 uint8_t bits2 = (bb[0][i+1] & 0x80) >> 7;
130 /* DEBUG: print out the received packet */
132 fprintf(stderr, "\n! ");
133 for (i = 0 ; i < BITBUF_COLS ; i++) {
134 fprintf (stderr, "%02x ", bb[0][i]);
136 fprintf (stderr,"\n\n");
139 if ( ((bb[0][0] == 0x00) && (bb[0][1] == 0x14) && (bb[0][2] & 0x50)) ||
140 ((bb[0][0] == 0xff) && (bb[0][1] == 0xd4) && (bb[0][2] & 0x50)) ) {
142 if (validate_checksum (bb[0], BITBUF_COLS)) {
146 temperature = get_temperature (bb[0]);
147 humidity = get_humidity (bb[0]);
148 channel = get_channel (bb[0]);
149 deviceID = get_device_id (bb[0]);
150 isBatteryLow = get_battery_status(bb[0]);
152 data = data_make("time", "", DATA_STRING, time_str,
153 "model", "", DATA_STRING, "Ambient Weather F007TH Thermo-Hygrometer",
154 "device", "House Code", DATA_INT, deviceID,
155 "channel", "Channel", DATA_INT, channel,
156 "battery", "Battery", DATA_STRING, isBatteryLow ? "Low" : "Ok",
157 "temperature_F", "Temperature", DATA_FORMAT, "%.1f", DATA_DOUBLE, temperature,
158 "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
160 data_acquired_handler(data);
169 ambient_weather_callback (bitbuffer_t *bitbuffer)
171 return ambient_weather_parser (bitbuffer);
174 static char *output_fields[] = {
183 r_device ambient_weather = {
184 .name = "Ambient Weather Temperature Sensor",
185 .modulation = OOK_PULSE_MANCHESTER_ZEROBIT,
187 .long_limit = 0, // not used
189 .json_callback = &ambient_weather_callback,
192 .fields = output_fields