X-Git-Url: https://git.rvb.name/rtl-433.git/blobdiff_plain/ca13278b24eb61443559bcb61e64627fba3d8823..6d15c6f967221af825cf84e3ed12b96c763b127b:/src/devices/emontx.c diff --git a/src/devices/emontx.c b/src/devices/emontx.c new file mode 100644 index 0000000..cf04c3b --- /dev/null +++ b/src/devices/emontx.c @@ -0,0 +1,150 @@ +/* OpenEnergyMonitor.org emonTx sensor protocol + * + * Copyright © 2016 Tommy Vestermark + * Copyright © 2016 David Woodhouse + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include "rtl_433.h" +#include "util.h" + +// We don't really *use* this because there's no endianness support +// for just using le16_to_cpu(pkt.ct1) etc. A task for another day... +struct emontx { + uint8_t syn, group, node, len; + uint16_t ct1, ct2, ct3, ct4, Vrms, temp[6]; + uint32_t pulse; + uint16_t crc; + uint8_t postamble; +} __attribute__((packed)); + +// This is the JeeLibs RF12 packet format as described at +// http://jeelabs.org/2011/06/09/rf12-packet-format-and-design/ +// +// The RFM69 chip misses out the zero bit at the end of the +// 0xAA 0xAA 0xAA preamble; the receivers only use it to set +// up the bit timing, and they look for the 0x2D at the start +// of the packet. So we'll do the same — except since we're +// specifically looking for emonTx packets, we can require a +// little bit more. We look for a group of 0xD2, and we +// expect the CDA bits in the header to all be zero: +static unsigned char preamble[3] = { 0xaa, 0xaa, 0xaa }; +static unsigned char pkt_hdr_inverted[3] = { 0xd2, 0x2d, 0xc0 }; +static unsigned char pkt_hdr[3] = { 0x2d, 0xd2, 0x00 }; + +static int emontx_callback(bitbuffer_t *bitbuffer) { + bitrow_t *bb = bitbuffer->bb; + unsigned bitpos = 0; + unsigned bits = bitbuffer->bits_per_row[0]; + int events = 0; + + // Search for only 22 bits to cope with inverted frames and + // the missing final preamble bit with RFM69 transmissions. + while ((bitpos = bitbuffer_search(bitbuffer, 0, bitpos, + preamble, 22)) < bitbuffer->bits_per_row[0]) { + int inverted = 0; + unsigned pkt_pos; + uint16_t crc; + data_t *data; + char time_str[LOCAL_TIME_BUFLEN]; + union { + struct emontx p; + uint8_t b[sizeof(struct emontx)]; + } pkt; + uint16_t words[14]; + double vrms; + unsigned i; + + bitpos += 22; + + // Eat any additional 101010 sequences (which might be attributed + // to noise at the start of the packet which coincidentally matches). + while (bitbuffer_search(bitbuffer, 0, bitpos, preamble, 2) == bitpos) + bitpos += 2; + + // Account for RFM69 bug which drops a zero bit at the end of the + // preamble before the 0x2d SYN byte. And for inversion. + bitpos--; + + // Check for non-inverted packet header... + pkt_pos = bitbuffer_search(bitbuffer, 0, bitpos, + pkt_hdr, 11); + + // And for inverted, if it's not found close enough... + if (pkt_pos > bitpos + 5) { + pkt_pos = bitbuffer_search(bitbuffer, 0, bitpos, + pkt_hdr_inverted, 11); + if (pkt_pos > bitpos + 5) + continue; + inverted = 1; + } + + // Need enough data for a full packet (including postamble) + if (pkt_pos + sizeof(pkt)*8 > bitbuffer->bits_per_row[0]) + break; + + // Extract the group even though we matched on it; the CRC + // covers it too. And might as well have the 0x2d too for + // alignment. + bitbuffer_extract_bytes(bitbuffer, 0, pkt_pos, + (uint8_t *)&pkt, sizeof(pkt) * 8); + if (inverted) { + for (i=0; i