Browse Source

Added most of files needed

Thomas Chef 7 tháng trước cách đây
mục cha
commit
c18223a23e

+ 1 - 0
.gitignore

@@ -71,6 +71,7 @@ wifi_manager/doc/
 
 # Visual Studio Code
 .vscode/
+-.vscode/c_cpp_properties.json
 .DS_Store
 
 #Others ?

+ 5 - 2
main/CMakeLists.txt

@@ -1,6 +1,9 @@
 
-set(COMPONENT_SRCDIRS ".")
-set(COMPONENT_ADD_INCLUDEDIRS ".")
+set(COMPONENT_SRCDIRS "." "./Sensors")
+set(COMPONENT_ADD_INCLUDEDIRS "." "./Sensors")
+
+
+
 
 
 register_component()

+ 151 - 0
main/Sensors/ClasOSensor.c

@@ -0,0 +1,151 @@
+#include "ClasOSensor.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "esp_log.h"
+#include "../rxTimer.h"
+#include "config.h"
+
+#ifdef TRANCEIVER_ENABLED
+
+enum
+{
+    UNKNOWN,
+    T0,
+    T1,
+    T2,
+    T3,
+    TEMP1_OK,
+    DONE
+};
+
+static uint8_t rx_state = UNKNOWN;
+
+static uint64_t sensor_data;
+static uint32_t rx_numBits;
+
+
+void ClasO_ResetDecoder()
+{
+    sensor_data = 0;
+    rx_numBits = 0;
+    rx_state = UNKNOWN;
+}
+
+static void addBit(uint8_t value)
+{
+
+    rx_numBits++;
+    sensor_data = (sensor_data << 1) + (value & 0x01);
+
+    rx_state = TEMP1_OK;
+}
+
+#define START_PULSE_MIN (3880-200)
+#define START_PULSE_MAX (4010+200)
+
+#define T0_PULSE_MIN (380-100)
+#define T0_PULSE_MAX (520+100)
+
+#define SHORT_PULSE_MIN (890-100)
+#define SHORT_PULSE_MAX (990+100)
+
+#define LONG_PULSE_MIN (1880-150)
+#define LONG_PULSE_MAX (1980+150)
+
+
+static int32_t rx_decode(uint32_t width)
+{
+    switch (rx_state) {
+        case UNKNOWN: // Start of frame
+            if ( START_PULSE_MIN <= width && width <= START_PULSE_MAX )
+            {
+                rx_state = T0;
+            }
+            else
+            {
+                return -1; // error, reset
+            }
+            break;
+
+        case T0: // First half of pulse : HIGH around 230us
+
+            if (rx_numBits == 32)
+            { // end of frame
+                rx_state = DONE;
+                sensor_data = (sensor_data >> 8); // Mask away some bits at the end
+                return 1;
+            }
+            else if( T0_PULSE_MIN <= width && width <= T0_PULSE_MAX )
+            {
+                rx_state = T1;
+            }
+            else
+            {
+                if (rx_numBits == 0 && START_PULSE_MIN <= width && width <= START_PULSE_MAX )
+                {
+                    rx_state = T0;
+                }
+                else
+                {
+                    return -1; // error, reset
+                }
+            }
+            break;
+
+        case T1:
+            if( SHORT_PULSE_MIN <= width && width <= SHORT_PULSE_MAX )
+            {
+                addBit(0);
+            }
+            else if( LONG_PULSE_MIN <= width && width <= LONG_PULSE_MAX )
+            {
+                addBit(1);
+            }
+            else
+            {
+                return -1; // error, reset
+            }
+            rx_state = T0;
+            break;
+    }
+    return 0;
+}
+
+int64_t nextPulseClasOSensor(uint32_t width)
+{
+    static int64_t previous_data = 0;
+    static uint32_t old_time=0;
+    static uint32_t now;
+    int64_t retVal = -1;
+
+    if (width > 0)
+    {
+        if (rx_state != DONE)
+        {
+            switch (rx_decode(width))
+            {
+            case -1:
+                ClasO_ResetDecoder();
+                break;
+            case 1:
+                rx_state = DONE;
+                break;
+            }
+        }
+    }
+    if (rx_state == DONE) {
+        now = millis();
+
+        if( sensor_data != previous_data || (now > (old_time+1000)) ) {
+            previous_data = sensor_data;
+            retVal = sensor_data;
+            
+        }
+        old_time = now;
+        ClasO_ResetDecoder();
+    }
+    
+    return retVal;
+}
+
+#endif

+ 11 - 0
main/Sensors/ClasOSensor.h

@@ -0,0 +1,11 @@
+#ifndef __CLASO__
+#define __CLASO__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void ClasO_ResetDecoder ();
+
+int64_t nextPulseClasOSensor(uint32_t width);
+
+#endif

+ 284 - 0
main/Sensors/esic.c

@@ -0,0 +1,284 @@
+#include "esic.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "esp_log.h"
+#include "../rxTimer.h"
+#include "config.h"
+
+#ifdef TRANCEIVER_ENABLED
+
+/**
+**********************************************************************************
+* TEMP 3
+* ESIC WT450H
+
+    +---+   +---+   +-------+       +  high
+    |   |   |   |   |       |       |
+    |   |   |   |   |       |       |
+    +   +---+   +---+       +-------+  low
+    
+    ^       ^       ^       ^       ^  clock cycle
+    |   1   |   1   |   0   |   0   |  translates as
+    
+    Each transmission is 36 bits long (i.e. 72 ms)
+
+	.short_width = 976,  // half-bit width 976 us
+    .long_width  = 1952, // bit width 1952 us
+    
+    Data is transmitted in pure binary values, NOT BCD-coded.
+    
+    Example transmission (House 1, Channel 1, RH 59 %, Temperature 23.5 �C)
+    1100 00010011001110110100100110011000
+    
+    b00 - b03  (4 bits): Constant, 1100, probably preamble
+    b04 - b07  (4 bits): House code (here: 0001 = HC 1)
+    b08 - b09  (2 bits): Channel code - 1 (here 00 = CC 1)
+    b10 - b12  (3 bits): Constant, 110
+    b13 - b19  (7 bits): Relative humidity (here 0111011 = 59 %)
+    b20 - b34 (15 bits): Temperature (see below)
+    b35 - b35  (1 bit) : Parity (xor of all bits should give 0)
+    
+    The temperature is transmitted as (temp + 50.0) * 128,
+    which equals (temp * 128) + 6400. Adding 50.0 �C makes
+    all values positive, an unsigned 15 bit integer where the
+    first 8 bits correspond to the whole part of the temperature
+    (here 01001001, decimal 73, substract 50 = 23).
+    Remaining 7 bits correspond to the fractional part.
+    
+    To avoid floating point calculations I store the raw temperature value
+    as a signed integer in the variable esicTemp, then transform it to
+    actual temperature * 10 using "esicTemp = (esicTemp - 6400) * 10 / 128",
+    where 6400 is the added 50 times 128.
+    When reporting the temperature I simply print "esicTemp / 10" (integer division,
+    no fraction), followed by a decimal point and "esicTemp % 10" (remainder, which
+    equals first fractional decimal digit).
+      
+    Summary of bit fields:
+    1100 0001 00 110 0111011 010010011001100 0
+     c1   hc  cc  c2    rh          t        p
+     
+    c1, c2 = constant field 1 and 2
+    hc, cc = house code and channel code
+    rh, t  = relative humidity, temperature
+    p      = parity bit 1111111111111110
+
+
+	This interpretation is from: https://github.com/merbanan/rtl_433/blob/master/src/devices/wt450.c
+
+	   1100 0001 | 0011 0011 | 1000 0011 | 1011 0011 | 0001
+	   xxxx ssss | ccxx bhhh | hhhh tttt | tttt tttt | sseo
+
+	- x: constant
+	- s: House code
+	- c: Channel
+	- b: battery low indicator (0=>OK, 1=>LOW)
+	- h: Humidity
+	- t: Temperature, 12 bit, offset 50, scale 16
+	- s: sequence number of message repeat
+	- e: parity of all even bits
+	- o: parity of all odd bits
+
+**********************************************************************************
+*/
+
+
+
+volatile unsigned long long temp3_x_data;
+
+
+void ESIC_ResetDecoder() {
+	temp3_x_data = 0;
+}
+
+#define NO_OF_PULSES 60
+#define max(a,b) (((a)>(b))?(a):(b))
+#define isShortPulse(width)  (((long_pulse/2)-maxDiff) <= width && width <= ((long_pulse/2)+maxDiff))
+#define isLongPulse(width)  ((long_pulse-maxDiff) <= width && width <= (long_pulse+maxDiff))
+
+unsigned int temp3_pulses[NO_OF_PULSES];
+
+
+static int long_pulse = 1955;
+static int maxDiff = 300;
+
+static void storePulses(unsigned int inWidth) {
+
+	int i;
+
+	// Shift pulses down
+	for(i=1;i<NO_OF_PULSES;i++) {
+		temp3_pulses[i-1] = temp3_pulses[i];
+	}
+
+	temp3_pulses[NO_OF_PULSES-1] = inWidth;
+}
+
+static void sweepForNoise() {
+
+	// If we have a short pulse in position 2
+	// Then add together pos 1,2 and 3 if they are a valid pulse
+	// This way we can handle one single noise pulse in a real pulse
+	if( temp3_pulses[NO_OF_PULSES-2] < ((long_pulse/2)-maxDiff) ) {
+
+		int totPulse = temp3_pulses[NO_OF_PULSES-1]+temp3_pulses[NO_OF_PULSES-2]+temp3_pulses[NO_OF_PULSES-3];
+		
+		if( isShortPulse(totPulse) || isLongPulse(totPulse) ) {
+			
+			// Store new pulse in last position
+			temp3_pulses[NO_OF_PULSES-1] = totPulse;
+
+			// Move everything up again
+			for(int i=NO_OF_PULSES-2;i>1;i--) {
+				temp3_pulses[i] = temp3_pulses[i-2];
+			}
+			temp3_pulses[0] = 0;
+			temp3_pulses[1] = 0;
+		}
+	}
+}
+
+
+/*static void adjustTiming() {
+
+	int p1 = temp3_pulses[NO_OF_PULSES-8];
+	int p2 = temp3_pulses[NO_OF_PULSES-7];
+	int p3 = temp3_pulses[NO_OF_PULSES-6];
+	int p4 = temp3_pulses[NO_OF_PULSES-5];
+	int p5 = temp3_pulses[NO_OF_PULSES-4];
+	int p6 = temp3_pulses[NO_OF_PULSES-3];
+	int p7 = temp3_pulses[NO_OF_PULSES-2];
+	int p8 = temp3_pulses[NO_OF_PULSES-1];
+
+	// Check max differance between the short pulses
+	int sh_mean = (p1+p2+p3+p4) / 4;
+	int sh_max_diff = max(max(abs(p1-sh_mean),abs(p2-sh_mean)),max(abs(p3-sh_mean),abs(p4-sh_mean)));
+
+	// Check max differance between the long pulses
+	int long_mean = (p5+p6+p7+p8) / 4;
+	int long_max_diff = max(max(abs(p5-long_mean),abs(p6-long_mean)),max(abs(p7-long_mean),abs(p8-long_mean)));
+
+	if( sh_max_diff < maxDiff && long_max_diff < maxDiff ) {
+
+		int mean = (long_mean + sh_mean)/2;
+		if( long_mean > (mean+maxDiff) && sh_mean < (mean-maxDiff) ) {
+			if( abs(long_mean - (sh_mean*2)) < maxDiff ) {
+				long_pulse = (long_mean + sh_mean*2)/2;
+				maxDiff = long_mean / 15;
+			}
+		}
+	}
+}*/
+
+// The latest/newest pulse is at the end of the array [59]
+// This ([59]) is the latest bit in the bit-stream from the transmitter
+// This is way we input the bits at a high position and shift them towards lower values
+// So..start reading backwards and working towards the first/highest bits
+static int checkPulsePattern() {
+
+	int i = NO_OF_PULSES-1;	// Start reading from the last received (end of array)
+	int b = 0;
+
+	unsigned long long code = 0;
+
+	while( i >= 0 ) {
+
+		int combWidth = temp3_pulses[i] + temp3_pulses[i-1];
+
+		if( isLongPulse(temp3_pulses[i]) ) {
+			b++;
+			i-=1;
+			code = code >> 1;
+		}
+		else if( isShortPulse(temp3_pulses[i]) && isShortPulse(temp3_pulses[i-1]) ) {
+			b++;
+			i-=2;
+			code = ((code >> 1) | 0x200000000);
+		}
+		else if( isLongPulse( combWidth ) ) {
+			b++;
+			i-=2;
+			code = ((code >> 1) | 0x200000000);
+		}
+		else {
+			return -1;
+		}
+		if( b == 34 ) {
+/*
+		0000 0001 00 110 0101000 010010110101000 1
+AND:    0011 1111 00 111 0000000 000000000000000 0  = 001111110011100000000000000000000000 = 0x3F3800000
+RES:    0000 0001 00 110 0000000 000000000000000 0  = 000000010011000000000000000000000000 = 0x013000000
+
+		Summary of bit fields:
+		1100 0001 00 110 0111011 010010011001100 0
+		 c1   hc  cc  c2    rh          t        p
+		 */
+			if( (code & 0x3F3800000) == 0x013000000 ) {
+
+				temp3_x_data = (code&0xFFFFFFFF);
+				// Check parity
+				int even=0;
+				unsigned long long data = temp3_x_data;
+				for(int i=0;i<32;i++) {
+					if( data & 1 ) even++;
+					data >>= 1;
+				}
+				if( even % 2 != 0 ) {
+					temp3_x_data = 0;
+					printf("Wrong parity\n");
+					return -1;
+				}
+				// A correct code has been received
+				//printf("Code received: %llu on row:%d\n",(code&0xFFFFFFFF),row_no);
+				temp3_x_data &= 0xFFFFFFF0;	// Remove sequence and parity bits in lowest nibble
+				return 1;
+				
+			}
+			else {
+				return -1;
+			}
+		}
+	}
+	return 0;
+}
+
+static int temp3decode (unsigned int inWidth) {
+
+	int width = inWidth; //preProcessPulses(inWidth);
+
+	if( width == -1 ) return -1;
+	if( width == 0 ) return 0;
+
+	storePulses(inWidth);
+	sweepForNoise();
+	//adjustTiming();
+	return checkPulsePattern();
+}
+
+int64_t nextPulseESICSensor(uint32_t width) {
+  
+  	static int64_t previous_data = 0;
+	static uint32_t old_time=0;
+	static uint32_t now;
+	int64_t retVal = -1;
+  
+	if( width > 0 ) {
+		if( temp3_x_data == 0 ) {
+			temp3decode(width);
+		}
+	}
+  
+	if( temp3_x_data > 0 ) {
+		now = millis();
+
+		if( temp3_x_data != previous_data || (now > (old_time+1000)) ) {
+            previous_data = temp3_x_data;
+            retVal = temp3_x_data;
+		}
+		old_time = now;
+		ESIC_ResetDecoder();
+	}
+	
+	return retVal;
+}
+
+#endif

+ 11 - 0
main/Sensors/esic.h

@@ -0,0 +1,11 @@
+#ifndef __ESIC__
+#define __ESIC__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void ESIC_ResetDecoder();
+
+int64_t nextPulseESICSensor(uint32_t width);
+
+#endif

+ 179 - 0
main/Sensors/nexa.c

@@ -0,0 +1,179 @@
+#include "nexa.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "../rxTimer.h"
+#include "config.h"
+
+#ifdef TRANCEIVER_ENABLED
+
+typedef struct {
+    uint32_t max;
+    uint32_t min;
+    uint32_t cnt;
+    uint32_t total;
+} debug_data_t;
+
+//static debug_data_t debug_data = { 0,99999,0,0 };
+//static debug_data_t debug_data_tot = { 0,99999,0,0 };
+
+#define DEBUG_WIDTH_FUNC() { \
+                    if( width > debug_data.max ) debug_data.max = width; \
+                    if( width < debug_data.min ) debug_data.min = width; \
+                    debug_data.total += width; \
+                    debug_data.cnt++; \
+                }
+
+
+#define FACTOR 9
+#define CONV(a) ((((a)*FACTOR) / 100) + (a))
+
+struct nexaData_t {
+  unsigned char bitNo;
+  unsigned short width;
+} ;
+
+enum { UNKNOWN, T0, T1, T2, T3, OK_Sensor, DONE };
+
+static uint8_t rx_state = UNKNOWN;
+
+static uint64_t sensor_data;
+static uint32_t rx_numBits;
+static uint8_t x_2ndbit;
+
+uint32_t startPulseWidth = 0;
+
+void NEXA_resetDecoder () {
+	sensor_data = 0;
+	rx_numBits = 0;
+	x_2ndbit = false;
+	rx_state = UNKNOWN;
+
+    //debug_data.max = 0;
+    //debug_data.min = 99999;
+}
+
+static void addBit (uint8_t value) {
+
+	// X
+	rx_numBits++;
+	sensor_data = (sensor_data << 1) + (value & 0x01);
+	if( x_2ndbit == false ) {
+		x_2ndbit = true;
+	}
+	else {
+		x_2ndbit = false;
+		unsigned int bits = (sensor_data & 0x03);
+		if( bits == 2 ) {
+			// Bit is 1
+			sensor_data = (sensor_data >> 1) | 0x00000001;
+		}
+		else {
+			// Bit is 0
+			sensor_data = (sensor_data >> 1) & 0xFFFFFFFE;
+		}
+	}
+
+	rx_state = OK_Sensor;
+}
+
+static int rx_decode(uint32_t width) {
+  
+    if( rx_numBits == 3 ) {	// end of frame
+          //state = DONE;
+          //return 1;
+	}
+        
+	switch (rx_state) {
+        case UNKNOWN: // Start of frame
+            if ( 2240 <= width && width <= 3540 ) { // Hallway-button: 2760
+                //DEBUG_WIDTH_FUNC();
+                startPulseWidth = width;
+
+                rx_state = T0;
+            }
+            else {
+                return -1;	// error, reset
+            }
+            break;
+
+        case T0: // First half of pulse
+
+            if ( 155 <= width && width <= 305 ) {   // Hallway-button: 230-250
+
+                rx_state = T1;
+
+            }
+            else {
+                if( rx_numBits == 0 && 2240 <= width && width <= 3540 ) {
+                    rx_state = T0;
+                }
+                else {
+                    return -1;	// error, reset
+                }
+            }
+            break;
+
+        case T1:
+            if ( 200 <= width && width <= 440 ) {   // Hallway-button: 250-270
+
+                addBit(0);
+            }
+            else if ( 950 <= width && width <= 1700 ) {  // Hallway-button: 1250-1270
+                
+
+                addBit(1);
+            } else if( rx_numBits == 64 ) {	// end of frame
+                rx_state = DONE;
+                return 1;
+            } else  {
+                return -1;	// error, reset
+            }
+            rx_state = T0;
+            break;
+	}
+	return 0;
+}
+
+#define TOO_SHORT 100
+
+int64_t nextPulseNEXA(uint32_t width)
+{
+    static int64_t previous_data = 0;
+    static uint32_t old_time=0;
+    static uint32_t now;
+    int64_t retVal = -1;
+
+    if (width > 0)
+    {
+        if (rx_state != DONE)
+        {
+            switch (rx_decode(width))
+            {
+            case -1:
+                NEXA_resetDecoder();
+                break;
+            case 1:
+                rx_state = DONE;
+                //printf("%d\n",debug_width);
+                break;
+            }
+        }
+    }
+    if (rx_state == DONE) {
+        now = millis();
+        //if( debug_data.max > debug_data_tot.max ) debug_data_tot.max = debug_data.max;
+        //if( debug_data.min < debug_data_tot.min ) debug_data_tot.min = debug_data.min;
+        //printf("NEXA Debug min,max:%u %u\n",debug_data_tot.min,debug_data_tot.max);
+
+        if( sensor_data != previous_data || (now > (old_time+1000)) ) {
+            previous_data = sensor_data;
+            retVal = sensor_data;
+        }
+        old_time = now;
+        NEXA_resetDecoder();
+    }
+    
+    return retVal;
+}
+
+#endif

+ 13 - 0
main/Sensors/nexa.h

@@ -0,0 +1,13 @@
+#ifndef __NEXA__
+#define __NEXA__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void NEXA_resetDecoder ();
+
+int64_t nextPulseNEXA(uint32_t width);
+
+extern uint32_t startPulseWidth;
+
+#endif

+ 113 - 0
main/Sensors/oregon.c

@@ -0,0 +1,113 @@
+#include "oregon.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "../rxTimer.h"
+#include <string.h>
+#include "esp_log.h"
+#include "config.h"
+
+#ifdef TRANCEIVER_ENABLED
+
+static void done ();
+
+static unsigned char total_bits, bits, flip, state, pos, data[25];
+char result_str[25];
+
+enum { UNKNOWN, T0, T1, T2, T3, SENSOR_OK, DONE };
+
+void Oregon_ResetDecoder () {
+    total_bits = bits = pos = flip = 0;
+    state = UNKNOWN;
+    memset(result_str,'\0',sizeof(result_str));
+}
+
+
+// V3-Version of the gitBit-function
+static void gotBit (char value) {
+    data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
+    total_bits++;
+    pos = total_bits >> 3;
+    if (pos >= sizeof data) {
+        Oregon_ResetDecoder();
+        return;
+    }
+    state = SENSOR_OK;
+}
+
+// store a bit using Manchester encoding
+static void manchester (char value) {
+    flip ^= value; // manchester code, long pulse flips the bit
+    gotBit(flip);
+}
+
+static void done () {
+    while (bits)
+        gotBit(0); // padding
+    state = DONE;
+}
+
+static int rx_decode( int width ) {
+    if( (480-200) < width && width < (980+200) ) {
+        char w = width >= 730;
+        switch (state) {
+            case UNKNOWN:
+                if (w == 0)
+                    ++flip;
+                else if (32 <= flip) {
+                    flip = 1;
+                    manchester(1);  // Width 950
+                } else
+                    return -1;
+                break;
+            case SENSOR_OK:
+                if (w == 0)
+                    state = T0;
+                else 
+                    manchester(1);  // Width 980
+
+                break;
+            case T0:
+                if (w == 0)
+                    manchester(0);  // Width 480
+                else
+                    return -1;
+                break;
+        }
+    } else {
+        return -1;
+    }
+    return  total_bits == 80 ? 1: 0;
+}
+
+ //10 bytes data: 2A 19 04 CE 00 00 60 12 00 30
+
+char * nextPulseOregonSensor(uint32_t width) {
+    if( state != DONE ) {
+    
+        switch (rx_decode(width)) {
+            case -1:
+                Oregon_ResetDecoder();
+                break;
+            case 1:
+                done();
+                break;
+        }
+    }
+    if( state == DONE ) {
+        if( pos == 10 ) {
+            for( int i=0; i<pos; i++ ) {
+                sprintf(result_str+(i*2),"%02X",data[i] );
+            }
+
+            return result_str;
+        }
+        else {
+            Oregon_ResetDecoder();
+            return  (char *)NULL;
+        }
+    }
+    else 
+        return (char *)NULL;
+}
+
+#endif

+ 11 - 0
main/Sensors/oregon.h

@@ -0,0 +1,11 @@
+#ifndef __OREGON__
+#define __OREGON__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void Oregon_ResetDecoder();
+
+char * nextPulseOregonSensor(uint32_t width);
+
+#endif

+ 163 - 0
main/Sensors/proovesmartSensor.c

@@ -0,0 +1,163 @@
+#include "proovesmartSensor.h"
+#include <stdint.h>
+#include <stdio.h>
+#include "../rxTimer.h"
+#include <string.h>
+#include "esp_log.h"
+#include "config.h"
+
+#ifdef TRANCEIVER_ENABLED
+
+typedef struct {
+    uint32_t max;
+    uint32_t min;
+    uint32_t cnt;
+    uint32_t total;
+} debug_data_t;
+
+static debug_data_t debug_data = { 0,99999,0,0 };
+static debug_data_t debug_data_tot = { 0,99999,0,0 };
+
+#define DEBUG_WIDTH_FUNC() { \
+                    if( width > debug_data.max ) debug_data.max = width; \
+                    if( width < debug_data.min ) debug_data.min = width; \
+                    debug_data.total += width; \
+                    debug_data.cnt++; \
+                }
+
+
+enum { UNKNOWN, T0, T1, T2, T3, OK_Sensor, DONE };
+
+static unsigned char rx_state = T0;
+
+static uint64_t sensor_data;
+static uint32_t rx_numBits;
+
+static unsigned char isTrigged = 0;
+static uint32_t trigDataBuff[4] = {0,0,0,0};
+
+void ProovesmartSensor_ResetDecoder () {
+	sensor_data = 0;
+	rx_numBits = 0;
+	rx_state = T0;
+    isTrigged = 0;
+    memset(trigDataBuff,0,sizeof(trigDataBuff));
+}
+
+static void addBit (uint8_t value) {
+
+	rx_numBits++;
+	sensor_data = (sensor_data << 1) + (value & 0x01);
+
+	rx_state = OK_Sensor;
+}
+
+static int rx_decode (uint32_t width) {
+        
+	switch (rx_state) {
+
+        uint32_t bitData;
+
+        case T0: // First ON-half of pulse : HIGH around 910
+
+            if ( (960-100) <= width && width <= (1080+100) ) {
+                rx_state = T1;
+            }
+            else {
+                return -1;	// error, reset
+            }
+            break;
+
+        case T1:
+            
+            if ( 200 <= width && width <= 2000 ) {
+                
+                if( width > 1000 ) {
+                    bitData = 0;
+                }
+                else {
+                    //DEBUG_WIDTH_FUNC();
+                    bitData = 1;
+                }
+
+            } else  {
+                return -1;	// error, reset
+            }
+
+            if( isTrigged == 0 ) {
+
+                trigDataBuff[3] = trigDataBuff[2];
+                trigDataBuff[2] = trigDataBuff[1];
+                trigDataBuff[1] = trigDataBuff[0];
+                trigDataBuff[0] = bitData;
+
+                if( trigDataBuff[3] == 0 &&
+                    trigDataBuff[2] == 1 &&
+                    trigDataBuff[1] == 0 &&
+                    trigDataBuff[0] == 0) {
+
+                        isTrigged = 1;
+                        // ESP_LOGI("PROOVE", "Trig %u",width);
+                }
+
+            }
+            else {
+                addBit(bitData);
+
+                if( rx_numBits == 36-8 ) {	// end of frame (We skip the last 8 bits)
+                    rx_state = DONE;
+                    return 1;
+                }
+            }
+              
+            rx_state = T0;
+
+            break;
+    }
+    return 0;
+}
+
+int64_t nextPulseProovesmartSensor(uint32_t width)
+{
+    static int64_t previous_data = 0;
+    static uint32_t old_time=0;
+    static uint32_t now;
+    int64_t retVal = -1;
+
+    if (width > 0)
+    {
+        if (rx_state != DONE)
+        {
+            switch (rx_decode(width))
+            {
+            case -1:
+                ProovesmartSensor_ResetDecoder();
+                break;
+            case 1:
+                rx_state = DONE;
+                break;
+            }
+        }
+    }
+    if (rx_state == DONE) {
+        now = millis();
+        sensor_data <<= 8;
+
+        /*
+        if( debug_data.max > debug_data_tot.max ) debug_data_tot.max = debug_data.max;
+        if( debug_data.min < debug_data_tot.min ) debug_data_tot.min = debug_data.min;
+        printf("OREGON DEbug min,max:%u %u\n",debug_data_tot.min,debug_data_tot.max);
+        */
+
+        if( sensor_data != previous_data || (now > (old_time+1000)) ) {
+            previous_data = sensor_data;
+            retVal = sensor_data;
+        }
+        old_time = now;
+        ProovesmartSensor_ResetDecoder();
+    }
+    
+    return retVal;
+}
+
+#endif

+ 11 - 0
main/Sensors/proovesmartSensor.h

@@ -0,0 +1,11 @@
+#ifndef __PROOVE__
+#define __PROOVE__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void ProovesmartSensor_ResetDecoder ();
+
+int64_t nextPulseProovesmartSensor(uint32_t width);
+
+#endif

+ 8 - 1
main/config.h

@@ -7,7 +7,7 @@
 
 // These defines configures which code to generate (to save download time during development)
 
-#define RX_TIMER_ENABLED
+//#define RX_TIMER_ENABLED
 //#define TRANCEIVER_ENABLED
 
 //#define WIFI_ENABLED
@@ -19,4 +19,11 @@
 #define ONE_WIRE_BUS_IO           GPIO_NUM_26   // Temp sensors
 
 
+//#define ENABLE_TSL2561
+#define I2C_MASTER_SCL  4   // GPIO number for I2C Master clock line.
+#define I2C_MASTER_SDA  5   // GPIO number for I2C Master data line.
+#define I2C_MASTER_FREQUENCY 400000  // I2C master clock frequency
+
+
+
 #endif

+ 12 - 0
main/main.c

@@ -6,6 +6,9 @@
 #include "mqtt.h"
 #include "readTemps.h"
 #include "rxTimer.h"
+#include "transceiver.h"
+#include "receiver.h"
+#include "tsl2561.h"
 
 
 // Chip info:
@@ -36,6 +39,11 @@ void app_main(void)
     rxTimerInit();          // First we start the Timer (which samples Rx and handles uS-delays)
 #endif
 
+#ifdef TRANCEIVER_ENABLED
+    initTransceiver();      // Init the transceiver
+    initReceiver();         // Init the receiver
+#endif
+
 #ifdef ENABLE_DS18B20
     initTempReadings();
 #endif
@@ -48,6 +56,10 @@ void app_main(void)
     mqtt_init();
 #endif
 
+#ifdef ENABLE_TSL2561
+    tsl2561Init();
+#endif
+
     TickType_t vLastWakeTime = xTaskGetTickCount();
 
     // Do an initial delay to make the different tasks to work out of sync to each other (not send all data at same time)

+ 173 - 0
main/receiver.c

@@ -0,0 +1,173 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_sleep.h"
+#include "esp_log.h"
+#include "driver/uart.h"
+#include "driver/rtc_io.h"
+#include "esp_intr_alloc.h"
+#include "esp_attr.h"
+#include "driver/timer.h"
+#include <stddef.h>
+#include "esp_intr_alloc.h"
+
+#include "receiver.h"
+#include "transceiver.h"
+#include "rxTimer.h"
+#include "Sensors/ClasOSensor.h"
+#include "Sensors/proovesmartSensor.h"
+#include "Sensors/nexa.h"
+#include "Sensors/oregon.h"
+#include "Sensors/esic.h"
+#include "config.h"
+
+uint32_t dataArr[1000];
+uint32_t dataArrIdx = 0;
+
+#ifdef TRANCEIVER_ENABLED
+
+static int convertToSignedTemp(unsigned int value)
+{
+
+	//int signValue;
+
+	return ( (value >> 11) == 0 )? value : ((-1 ^ 0xFFF) | value);
+}
+
+#define UDP_QUEUE_OBJ_LENGTH 40
+
+void receiverTask(void *pvParameter)
+{
+    ESP_LOGI("RX", "Receiver task starting.");
+    uint32_t width;
+    
+    char dataStr[UDP_QUEUE_OBJ_LENGTH];
+
+    while (1) {
+
+        while( xQueueReceive( rxQueue, &width, portMAX_DELAY ) == pdTRUE ) {
+
+            dataArr[dataArrIdx++] = width;
+            if( dataArrIdx == 1000 ) dataArrIdx=0;
+
+            // Receive the Clas Ohlsson Sensors
+            int64_t data = nextPulseClasOSensor(width);
+            if( data != -1 ) {
+
+                int value      = convertToSignedTemp( data & 0xFFF );
+                unsigned char id         = (data>>12) & 0x007;
+
+                ESP_LOGI("RX", "ClasO:  <TR%08llX> %u               %4.1f",data,id, (float)value/10);
+
+                sprintf(dataStr,"<TR%08llX>",data);
+#ifdef MQTT_ENABLED
+                //sendUDPMessage(dataStr, true);
+#endif
+            }
+
+            // Receive the Telldus / Proovesmart Sensors
+            data = nextPulseProovesmartSensor(width);
+            if( data != -1 ) {
+
+                const int value = (data & 0x00FFF0000) >> 16;
+                const int id = (data & 0xFF0000000) >> 28;
+
+                ESP_LOGI("RX", "Proove: <Tr%016llX> ID:%d  %4.1f",data,id,(float)value/10);
+
+                sprintf(dataStr,"<Tr%016llX>",data);
+#ifdef MQTT_ENABLED
+                //sendUDPMessage(dataStr, true);
+#endif
+            }
+
+            // Receive the NEXA Sensors
+            data = nextPulseNEXA(width);
+            if( data != -1 ) {
+
+                ESP_LOGI("RX", "NEXA: <NR%08llX>",data);
+
+                sprintf(dataStr,"<NR%08llX>%u",data,startPulseWidth);
+
+#ifdef MQTT_ENABLED
+                //sendUDPMessage(dataStr, false);
+#endif
+            }
+
+            // Receive the Oregon (Rain) Sensor
+            char *ch_data_p = nextPulseOregonSensor(width);
+            if( ch_data_p != NULL ) {
+
+                // Nibbles 17..12 = Total Rain = LSD is 0.001 inch (0,0254 mm)
+                
+                //   0 1 2 3  4 5  6 7 8  9                     Rate    Total
+                // RR2A1904CE 0000 601600 70 = 001.660          0000    001660
+                // RR2A1904CE 2001 702000 60 = 002.070 = 0,41   0120    002070
+                // RR2A1904CE 0001 902400 A0 = 002.490 = 0,42           002490
+                // RR2A1904CE 0000 906600 F0 = 006.690 = 6.69 = 109,62903 cm2
+                // Sequence:       563412  
+                // 1 cubic mm of water = 0,001 gram
+                // 7 grams of water = 7000 mm2
+                // Area of the rain sensor is 7697.69 sq.mm. It flips every ~7grams of water
+                // Every flip is therefore 0.90936402542048 mm or rain
+                // The value that is reported is in 1/1000 cubic inches of water.
+                // Multiply with 16387 / 1000 to get cm2
+
+                double total = 100 * (ch_data_p[4+12]-'0') + 
+                                10 * (ch_data_p[5+12]-'0') +
+                                     (ch_data_p[2+12]-'0') +
+                               0.1 * (ch_data_p[3+12]-'0') +
+                              0.01 * (ch_data_p[0+12]-'0') +
+                             0.001 * (ch_data_p[1+12]-'0');
+
+                total = (total * 16387) / 1000; // Convert to cubic centimeters
+
+                char ch_data[21];
+                strncpy(ch_data,ch_data_p, sizeof(ch_data));
+                ESP_LOGI("RX", "OREGON: <RR%s> %6.4f cm2", ch_data, total );
+
+#ifdef MQTT_ENABLED
+                //sprintf(dataStr,"<RR%s>",ch_data);
+                //sendUDPMessage(dataStr, true);
+#endif
+
+                Oregon_ResetDecoder();
+            }
+
+            // ESIC (Fridge / Freezer Sensors)
+            data = nextPulseESICSensor(width);
+            if( data != -1 ) {
+
+                int32_t value	   = (data & 0xFFFE) >> 1;
+		                value	   = (value - 6400) * 10 / 128;
+
+                int32_t id         = (data>>12) & 0x007;
+
+                ESP_LOGI("RX", "ESIC:   <TE%08llX> %u               %4.1f",data,id, (float)value/10);
+
+                sprintf(dataStr,"<TE%08llX>",data);
+#ifdef MQTT_ENABLED
+                //sendUDPMessage(dataStr, true);
+#endif
+            }
+        }
+    }
+    vTaskDelete(NULL);
+}
+
+void initReceiver() {
+
+    Oregon_ResetDecoder();
+    ClasO_ResetDecoder();
+    ProovesmartSensor_ResetDecoder();
+    ESIC_ResetDecoder();
+            
+    ESP_LOGI("RX", "Receiver has been initialized.");
+
+    xTaskCreatePinnedToCore(&receiverTask, "receiverTask", 8192, NULL, tskIDLE_PRIORITY + 5, NULL, 0);
+}
+
+#endif

+ 13 - 0
main/receiver.h

@@ -0,0 +1,13 @@
+#ifndef __RECEIVER__
+#define __RECEIVER__
+
+
+
+void initReceiver();
+
+extern uint32_t dataArr[1000];
+extern uint32_t dataArrIdx;
+
+
+
+#endif

+ 4 - 0
main/rxTimer.c

@@ -16,6 +16,8 @@
 #include "esp_intr_alloc.h"
 #include "transceiver.h"
 
+#ifdef RX_TIMER_ENABLED
+
 static intr_handle_t s_timer_handle;
 
 static bool timerTaskIsDone = false;
@@ -118,3 +120,5 @@ void delayMicroseconds(uint32_t delay)
 
 	while( tenUsCounter < endtime ) ;
 }
+
+#endif

+ 1 - 0
main/transceiver.c

@@ -17,6 +17,7 @@
 
 #include "transceiver.h"
 #include "rxTimer.h"
+#include "config.h"
 
 
 bool disableRx = true; // Controls if trcv is in RX or TX-mode

+ 102 - 0
main/tsl2561.c

@@ -0,0 +1,102 @@
+/* i2c - Simple example
+
+   Simple I2C example that shows how to initialize I2C
+   as well as reading and writing from and to registers for a sensor connected over I2C.
+
+   The sensor used in this example is a MPU9250 inertial measurement unit.
+
+   For other examples please check:
+   https://github.com/espressif/esp-idf/tree/master/examples
+
+   See README.md file to get detailed usage of this example.
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include <stdio.h>
+#include "esp_log.h"
+#include "driver/i2c.h"
+#include "config.h"
+
+#ifdef ENABLE_TSL2561
+
+static const char *TAG = "i2c-simple-example";
+
+#define I2C_MASTER_SCL_IO           I2C_MASTER_SCL             /*!< GPIO number used for I2C master clock */
+#define I2C_MASTER_SDA_IO           I2C_MASTER_SDA             /*!< GPIO number used for I2C master data  */
+#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
+#define I2C_MASTER_FREQ_HZ          400000                     /*!< I2C master clock frequency */
+#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
+#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
+#define I2C_MASTER_TIMEOUT_MS       1000
+
+#define MPU9250_SENSOR_ADDR                 0x68        /*!< Slave address of the MPU9250 sensor */
+#define MPU9250_WHO_AM_I_REG_ADDR           0x75        /*!< Register addresses of the "who am I" register */
+
+#define MPU9250_PWR_MGMT_1_REG_ADDR         0x6B        /*!< Register addresses of the power managment register */
+#define MPU9250_RESET_BIT                   7
+
+/**
+ * @brief Read a sequence of bytes from a MPU9250 sensor registers
+ */
+static esp_err_t mpu9250_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
+{
+    return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
+}
+
+/**
+ * @brief Write a byte to a MPU9250 sensor register
+ */
+static esp_err_t mpu9250_register_write_byte(uint8_t reg_addr, uint8_t data)
+{
+    int ret;
+    uint8_t write_buf[2] = {reg_addr, data};
+
+    ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
+
+    return ret;
+}
+
+/**
+ * @brief i2c master initialization
+ */
+static esp_err_t i2c_master_init(void)
+{
+    int i2c_master_port = I2C_MASTER_NUM;
+
+    i2c_config_t conf = {
+        .mode = I2C_MODE_MASTER,
+        .sda_io_num = I2C_MASTER_SDA_IO,
+        .scl_io_num = I2C_MASTER_SCL_IO,
+        .sda_pullup_en = GPIO_PULLUP_ENABLE,
+        .scl_pullup_en = GPIO_PULLUP_ENABLE,
+        .master.clk_speed = I2C_MASTER_FREQ_HZ,
+    };
+
+    i2c_param_config(i2c_master_port, &conf);
+
+    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
+}
+
+
+void tsl2561Init(void)
+{
+    uint8_t data[2];
+    ESP_ERROR_CHECK(i2c_master_init());
+    ESP_LOGI(TAG, "I2C initialized successfully");
+
+    /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */
+    ESP_ERROR_CHECK(mpu9250_register_read(MPU9250_WHO_AM_I_REG_ADDR, data, 1));
+    ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]);
+
+    /* Demonstrate writing by reseting the MPU9250 */
+    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT));
+
+    ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
+    ESP_LOGI(TAG, "I2C unitialized successfully");
+}
+
+#endif

+ 12 - 0
main/tsl2561.h

@@ -0,0 +1,12 @@
+#ifndef __TSL_2561__
+#define __TSL_2561__
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include <stdint.h>
+
+void tsl2561Init();
+
+
+
+#endif