1 /* Efergy IR is a devices that periodically reports current energy consumption
2 * on frequency ~433.55 MHz. The data that is transmitted consists of 8
5 * Byte 1-4: Start bits (0000), then static data (probably device id)
8 * Byte 9: sample frequency (15 seconds)
10 * Byte 11: bytes0-10 crc16 xmodem XOR with FF
11 * Byte 12: ?crc16 xmodem
12 * if pulse count <3 then energy =(( pulsecount/impulse-perkwh) * (3600/seconds))
13 * else energy= ((pulsecount/n_imp) * (3600/seconds))
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
25 static int efergy_optical_callback(bitbuffer_t *bitbuffer) {
26 unsigned num_bits = bitbuffer->bits_per_row[0];
27 uint8_t *bytes = bitbuffer->bb[0];
32 char time_str[LOCAL_TIME_BUFLEN];
36 if (num_bits < 64 || num_bits > 100){
40 // The bit buffer isn't always aligned to the transmitted data, so
41 // search for data start and shift out the bits which aren't part
42 // of the data. The data always starts with 0000 (or 1111 if
43 // gaps/pulses are mixed up).
44 while ((bytes[0] & 0xf0) != 0xf0 && (bytes[0] & 0xf0) != 0x00)
52 for (unsigned i = 0; i < (num_bits + 7) / 8; ++i)
55 bytes[i] |= (bytes[i + 1] & 0x80) >> 7;
59 // Sometimes pulses and gaps are mixed up. If this happens, invert
60 // all bytes to get correct interpretation.
62 for (unsigned i = 0; i < 12; ++i)
69 fprintf(stdout,"Possible Efergy Optical: ");
70 bitbuffer_print(bitbuffer);
73 // Calculate checksum for bytes[0..10]
74 // crc16 xmodem with start value of 0x00 and polynomic of 0x1021 is same as CRC-CCITT (0x0000)
75 // start of data, length of data=10, polynomic=0x1021, init=0x0000
77 csum1 = ((bytes[10]<<8)|(bytes[11]));
79 crc = crc16_ccitt(bytes, 10, 0x1021, 0x0);
84 fprintf (stdout, "Checksum OK :) :)\n");
85 fprintf (stdout, "Calculated crc is 0x%02X\n", crc);
86 fprintf (stdout, "Received csum1 is 0x%02X\n", csum1);
88 // this setting depends on your electricity meter's optical output
91 pulsecount = bytes[8];
94 //some logic for low pulse count not sure how I reached this formula
97 energy = ((pulsecount/n_imp) * (3600/seconds));
101 energy = ((pulsecount/n_imp) * (3600/30));
103 //New code for calculating varous energy values for differing pulse-kwh values
104 const int imp_kwh[] = {3200, 2000, 1000, 500, 0};
105 for (unsigned i=0; imp_kwh[i] !=0; ++i) {
108 energy = ((pulsecount/imp_kwh[i]) * (3600/seconds));
112 energy = ((pulsecount/imp_kwh[i]) * (3600/30));
114 local_time_str(0, time_str);
116 "time", "Time", DATA_STRING, time_str,
117 "model", "Model", DATA_STRING, "Efergy Optical",
118 "pulses", "Pulse-rate", DATA_FORMAT,"%i", DATA_INT, imp_kwh[i],
119 "energy", "Energy", DATA_FORMAT,"%.03f KWh", DATA_DOUBLE, energy,
121 data_acquired_handler(data);
130 fprintf (stdout, "Checksum not OK !!!\n");
131 fprintf(stdout, "Calculated crc is 0x%02X\n", crc);
132 fprintf(stdout, "Received csum1 is 0x%02X\n", csum1);
138 static char *output_fields[] = {
146 r_device efergy_optical = {
147 .name = "Efergy Optical",
148 .modulation = FSK_PULSE_PWM_RAW,
152 .json_callback = &efergy_optical_callback,
155 .fields = output_fields