├── .gitignore ├── License.txt ├── README.md ├── RFLink ├── 1_Radio.cpp ├── 1_Radio.h ├── 2_Signal.cpp ├── 2_Signal.h ├── 3_Serial.cpp ├── 3_Serial.h ├── 4_Display.cpp ├── 4_Display.h ├── 5_Plugin.cpp ├── 5_Plugin.h ├── 6_Credentials.h ├── 6_WiFi_MQTT.cpp ├── 6_WiFi_MQTT.h ├── 7_Utils.cpp ├── 7_Utils.h ├── 8_OLED.cpp ├── 8_OLED.h ├── Plugins │ ├── Plugin_001.c │ ├── Plugin_002.c │ ├── Plugin_003.c │ ├── Plugin_004.c │ ├── Plugin_005.c │ ├── Plugin_006.c │ ├── Plugin_007.c │ ├── Plugin_008.c │ ├── Plugin_009.c │ ├── Plugin_010.c │ ├── Plugin_011.c │ ├── Plugin_012.c │ ├── Plugin_013.c │ ├── Plugin_014.c │ ├── Plugin_015.c │ ├── Plugin_029.c │ ├── Plugin_030.c │ ├── Plugin_031.c │ ├── Plugin_032.c │ ├── Plugin_033.c │ ├── Plugin_034.c │ ├── Plugin_035.c │ ├── Plugin_036.c │ ├── Plugin_037.c │ ├── Plugin_040.c │ ├── Plugin_041.c │ ├── Plugin_042.c │ ├── Plugin_043.c │ ├── Plugin_044.c │ ├── Plugin_045.c │ ├── Plugin_046.c │ ├── Plugin_047.c │ ├── Plugin_048.old │ ├── Plugin_060.c │ ├── Plugin_061.c │ ├── Plugin_062.c │ ├── Plugin_063.c │ ├── Plugin_064.c │ ├── Plugin_065.c │ ├── Plugin_070.c │ ├── Plugin_071.c │ ├── Plugin_072.c │ ├── Plugin_073.c │ ├── Plugin_074.c │ ├── Plugin_075.c │ ├── Plugin_080.c │ ├── Plugin_081.c │ ├── Plugin_082.c │ ├── Plugin_083.c │ ├── Plugin_090.old │ ├── Plugin_101.old │ ├── Plugin_250.old │ ├── Plugin_251.old │ ├── Plugin_254.c │ └── _Plugin_Config_01.h ├── RFLink.h └── RFLink.ino ├── Readme_RFLink.txt ├── include └── dummy.txt ├── pictures ├── RFLink-ESP_OLED.jpg ├── RFLink-ESP_OLED_2.jpg ├── RFLink-ESP_Pinout.jpg ├── RFLink-ESP_RXB6.jpg └── RFLink-ESP_Receivers.jpg └── platformio.ini /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode 3 | pictures/Full size/ 4 | RFLink/6_Credentials.h 5 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/License.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RFLink ESP 2 | This is an RF to MQTT gateway build for an ESP8266 board (see #MCU for more). 3 | 4 | It receive OOK 433MHz signals, then it identifies, decodes and push them over MQTT. 5 | 6 | Projet is based on RFlink project "R29" (see rflink.nl, latest known open source shard version). 7 | 8 | ## 1. MCU 9 | We use extensively Wemos ESP8266 D1 mini clone. 10 | 11 | This is default settings in Platformio.ini and RFLink.h files. 12 | 13 | You may use: 14 | - Other ESP8266/ESP8255 based boards, when no pins limitations. NodeMCUv2 is known working. 15 | - ESP32 based boards should work too. Although we need feedbacks there. 16 | - Arduino board (Uno, Pro Mini, Mega) are working too, of course without WiFi/MQTT part. 17 | 18 | ## 2. Receiver / Transmitter / Transceiver 19 | We mainly use RXB6 receiver. 20 | It is simple, steady, running on 3.3v, easy to find and cheap. 21 | 22 | Many other receivers will do! 23 | Simply *** Please avoid generic noname receiver *** 24 | 25 | ![Receivers](https://github.com/couin3/RFLink/blob/master/pictures/RFLink-ESP_Receivers.jpg "Receivers") 26 | 27 | ## 3. OLED display 28 | You can use an OLED display! We used SSD1306 128x64 I2C screen for our testings. 29 | 30 | *** This is highly experimental ***, and thus not activated by default. 31 | 32 | ![OLED](https://github.com/couin3/RFLink/blob/master/pictures/RFLink-ESP_OLED_2.jpg "OLED") 33 | 34 | ## 4. IDE 35 | - We strongly recommend using PlatformIO IDE (https://platformio.org/install) 36 | - You may alternatively use Arduino IDE 1.8.10 (https://www.arduino.cc/en/Guide/HomePage) 37 | 38 | ## 5. Framework 39 | We use Arduino Core for ESP8266 https://github.com/esp8266/Arduino 40 | 41 | ## 6. Libraries 42 | So far, in addition of core libraries, we use: 43 | - PubSubClient for MQTT messaging https://github.com/knolleary/pubsubclient 44 | - u8g2/u8x8 library for OLED display https://github.com/olikraus/u8g2 45 | - AutoConnect for simplified configuration (incomming v2.0) https://hieromon.github.io/AutoConnect 46 | 47 | ## 7. COMPILE OPTIONS AND FLAGS 48 | Many features are not enabled by default or can be disabled for various reasons : firmware size, compability etc etc. Here is a listing with some instructions: 49 | ### MQTT Server (disabled by default) 50 | - Define compilation flag MQTT_ENABLED or define it in 6_WIFI_MQTT.h 51 | - If you have not enabled WifiManager, make sure you update Wifi settings in 6_Credentials.h 52 | 53 | ## 8. Additional info 54 | ### Pinout 55 | - When WebServer is active (which is default), pin setup has to be done there. 56 | - For safety & simplicity, default WebServer setup is : all pin inactive. 57 | - You may add decoupling capacitors and antenna to improve results. 58 | - This is a simple RX pin wiring : 59 | 60 | | Name | D1 mini | RXB6 | 61 | |---------------|---------|-------| 62 | | PIN_RF_TX_VCC | D5 | 5 VCC | 63 | | PIN_RF_TX_NA | D6 | 6 DER | 64 | | PIN_RF_TX_DATA| D7 | 7 DAT | 65 | | PIN_RF_TX_GND | D8 | 8 GND | 66 | 67 | ![Pinout](https://github.com/couin3/RFLink/blob/master/pictures/RFLink-ESP_Pinout.jpg "Pinout") 68 | 69 | ### Alternative Pinout 70 | - ESP8266 can't draw more than 12mA on a GPIO pin. 71 | - Some receivers have current spikes bigger than that (eg RXB12). 72 | - This lead to a non working receiver / non starting ESP. 73 | - Here is a more safe wiring 74 | 75 | | Name (Alt) | D1 mini | RXB6 | 76 | |---------------|---------|-------| 77 | | PIN_RF_TX_VCC | 3v3 | 5 VCC | 78 | | PIN_RF_TX_NA | N/A | 6 DER | 79 | | PIN_RF_TX_DATA| D7 | 7 DAT | 80 | | PIN_RF_TX_GND | GND | 8 GND | 81 | 82 | ### Thanks 83 | Special thanks to: Axellum, Etimou, Schmurtz, Zoomx 84 | -------------------------------------------------------------------------------- /RFLink/1_Radio.cpp: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #include 9 | #include "RFLink.h" 10 | #include "1_Radio.h" 11 | #include "4_Display.h" 12 | 13 | uint8_t PIN_RF_RX_PMOS = PIN_RF_RX_PMOS_0; 14 | uint8_t PIN_RF_RX_NMOS = PIN_RF_RX_NMOS_0; 15 | uint8_t PIN_RF_RX_VCC = PIN_RF_RX_VCC_0; 16 | uint8_t PIN_RF_RX_GND = PIN_RF_RX_GND_0; 17 | uint8_t PIN_RF_RX_NA = PIN_RF_RX_NA_0; 18 | uint8_t PIN_RF_RX_DATA = PIN_RF_RX_DATA_0; 19 | boolean PULLUP_RF_RX_DATA = PULLUP_RF_RX_DATA_0; 20 | uint8_t PIN_RF_TX_PMOS = PIN_RF_TX_PMOS_0; 21 | uint8_t PIN_RF_TX_NMOS = PIN_RF_TX_NMOS_0; 22 | uint8_t PIN_RF_TX_VCC = PIN_RF_TX_VCC_0; 23 | uint8_t PIN_RF_TX_GND = PIN_RF_TX_GND_0; 24 | uint8_t PIN_RF_TX_NA = PIN_RF_TX_NA_0; 25 | uint8_t PIN_RF_TX_DATA = PIN_RF_TX_DATA_0; 26 | 27 | Radio_State current_State = Radio_NA; 28 | 29 | #ifdef RFM69_ENABLED 30 | 31 | #include 32 | #include 33 | #include 34 | RFM69OOK radio; 35 | 36 | void set_Radio_mode(Radio_State new_State) 37 | { 38 | if (current_State != new_State) 39 | { 40 | switch (new_State) 41 | { 42 | case Radio_OFF: 43 | PIN_RF_RX_DATA = NOT_A_PIN; 44 | PIN_RF_TX_DATA = NOT_A_PIN; 45 | radio.reset(); 46 | radio.initialize(); 47 | radio.setFrequency(433920000); 48 | Serial.print("Freq = "); 49 | Serial.println(radio.getFrequency()); 50 | //Serial.print("Temp = "); Serial.println(radio.readTemperature()); 51 | radio.setHighPower(true); // for RFM69HW 52 | // radio.sleep(); 53 | break; 54 | 55 | case Radio_RX: 56 | radio.transmitEnd(); 57 | PIN_RF_TX_DATA = NOT_A_PIN; 58 | radio.receiveBegin(); 59 | PIN_RF_RX_DATA = RF69OOK_IRQ_PIN; 60 | radio.attachUserInterrupt(NULL); 61 | detachInterrupt(0); 62 | detachInterrupt(1); 63 | break; 64 | 65 | case Radio_TX: 66 | radio.receiveEnd(); 67 | PIN_RF_RX_DATA = NOT_A_PIN; 68 | radio.transmitBegin(); 69 | PIN_RF_TX_DATA = RF69OOK_IRQ_PIN; 70 | radio.setPowerLevel(10); 71 | break; 72 | 73 | case Radio_NA: 74 | break; 75 | } 76 | current_State = new_State; 77 | } 78 | } 79 | #else 80 | // Prototype 81 | void enableRX(); 82 | void disableRX(); 83 | void enableTX(); 84 | void disableTX(); 85 | 86 | void set_Radio_mode(Radio_State new_State) 87 | { 88 | if (current_State != new_State) 89 | { 90 | switch (new_State) 91 | { 92 | case Radio_OFF: 93 | disableTX(); 94 | disableRX(); 95 | break; 96 | 97 | case Radio_RX: 98 | disableTX(); 99 | enableRX(); 100 | break; 101 | 102 | case Radio_TX: 103 | disableRX(); 104 | enableTX(); 105 | break; 106 | 107 | case Radio_NA: 108 | break; 109 | } 110 | current_State = new_State; 111 | } 112 | } 113 | 114 | #if (defined(ESP8266) || defined(ESP32)) 115 | void show_Radio_Pin() 116 | { 117 | if (PIN_RF_RX_PMOS != (uint8_t)NOT_A_PIN) 118 | { 119 | Serial.print(F("Radio pin RF_RX_PMOS :\t")); 120 | Serial.println(GPIO2String(PIN_RF_RX_PMOS)); 121 | Serial.println(PIN_RF_RX_PMOS); 122 | } 123 | if (PIN_RF_RX_NMOS != (uint8_t)NOT_A_PIN) 124 | { 125 | Serial.print(F("Radio pin RF_RX_NMOS :\t")); 126 | Serial.println(GPIO2String(PIN_RF_RX_NMOS)); 127 | } 128 | if (PIN_RF_RX_VCC != (uint8_t)NOT_A_PIN) 129 | { 130 | Serial.print(F("Radio pin RF_RX_VCC :\t")); 131 | Serial.println(GPIO2String(PIN_RF_RX_VCC)); 132 | } 133 | if (PIN_RF_RX_GND != (uint8_t)NOT_A_PIN) 134 | { 135 | Serial.print(F("Radio pin RF_RX_GND :\t")); 136 | Serial.println(GPIO2String(PIN_RF_RX_GND)); 137 | } 138 | if (PIN_RF_RX_NA != (uint8_t)NOT_A_PIN) 139 | { 140 | Serial.print(F("Radio pin RF_RX_NA :\t")); 141 | Serial.println(GPIO2String(PIN_RF_RX_NA)); 142 | } 143 | if (PIN_RF_RX_DATA != (uint8_t)NOT_A_PIN) 144 | { 145 | Serial.print(F("Radio pin RF_RX_DATA :\t")); 146 | Serial.print(GPIO2String(PIN_RF_RX_DATA)); 147 | if (PULLUP_RF_RX_DATA) 148 | Serial.println(F(" (Pullup enabled)")); 149 | else 150 | Serial.println(); 151 | } 152 | // 153 | if (PIN_RF_TX_PMOS != (uint8_t)NOT_A_PIN) 154 | { 155 | Serial.print(F("Radio pin RF_TX_PMOS :\t")); 156 | Serial.println(GPIO2String(PIN_RF_TX_PMOS)); 157 | } 158 | if (PIN_RF_TX_NMOS != (uint8_t)NOT_A_PIN) 159 | { 160 | Serial.print(F("Radio pin RF_TX_NMOS :\t")); 161 | Serial.println(GPIO2String(PIN_RF_TX_NMOS)); 162 | } 163 | if (PIN_RF_TX_VCC != (uint8_t)NOT_A_PIN) 164 | { 165 | Serial.print(F("Radio pin RF_TX_VCC :\t")); 166 | Serial.println(GPIO2String(PIN_RF_TX_VCC)); 167 | } 168 | if (PIN_RF_TX_GND != (uint8_t)NOT_A_PIN) 169 | { 170 | Serial.print(F("Radio pin RF_TX_GND :\t")); 171 | Serial.println(GPIO2String(PIN_RF_TX_GND)); 172 | } 173 | if (PIN_RF_TX_DATA != (uint8_t)NOT_A_PIN) 174 | { 175 | Serial.print(F("Radio pin RF_TX_DATA :\t")); 176 | Serial.println(GPIO2String(PIN_RF_TX_DATA)); 177 | } 178 | if (PIN_RF_TX_NA != (uint8_t)NOT_A_PIN) 179 | { 180 | Serial.print(F("Radio pin RF_TX_NA :\t")); 181 | Serial.println(GPIO2String(PIN_RF_TX_NA)); 182 | } 183 | } 184 | #endif // ESP8266 || ESP32 185 | 186 | void enableRX() 187 | { 188 | // RX pins 189 | pinMode(PIN_RF_RX_NA, INPUT); // Initialise in/output ports 190 | pinMode(PIN_RF_RX_DATA, INPUT); // Initialise in/output ports 191 | pinMode(PIN_RF_RX_NMOS, OUTPUT); // MOSFET, always output 192 | pinMode(PIN_RF_RX_PMOS, OUTPUT); // MOSFET, always output 193 | digitalWrite(PIN_RF_RX_NMOS, HIGH); // turn GND to RF receiver ON 194 | digitalWrite(PIN_RF_RX_PMOS, LOW); // turn VCC to RF receiver ON 195 | pinMode(PIN_RF_RX_GND, OUTPUT); // Initialise in/output ports 196 | pinMode(PIN_RF_RX_VCC, OUTPUT); // Initialise in/output ports 197 | digitalWrite(PIN_RF_RX_GND, LOW); // turn GND to RF receiver ON 198 | digitalWrite(PIN_RF_RX_VCC, HIGH); // turn VCC to RF receiver ON 199 | if (PULLUP_RF_RX_DATA) 200 | pinMode(PIN_RF_RX_DATA, INPUT_PULLUP); // Initialise in/output ports 201 | delayMicroseconds(TRANSMITTER_STABLE_DELAY_US); 202 | } 203 | 204 | void disableRX() 205 | { 206 | // RX pins 207 | pinMode(PIN_RF_RX_DATA, INPUT); 208 | pinMode(PIN_RF_RX_NA, INPUT); 209 | pinMode(PIN_RF_RX_PMOS, OUTPUT); // MOSFET, always output 210 | pinMode(PIN_RF_RX_NMOS, OUTPUT); // MOSFET, always output 211 | digitalWrite(PIN_RF_RX_PMOS, HIGH); // turn VCC to RF receiver OFF 212 | digitalWrite(PIN_RF_RX_NMOS, LOW); // turn GND to RF receiver OFF 213 | pinMode(PIN_RF_RX_VCC, INPUT); 214 | pinMode(PIN_RF_RX_GND, INPUT); 215 | } 216 | 217 | void enableTX() 218 | { 219 | // TX Pins 220 | pinMode(PIN_RF_TX_NA, INPUT); // Initialise in/output ports 221 | pinMode(PIN_RF_TX_DATA, OUTPUT); // Initialise in/output ports 222 | digitalWrite(PIN_RF_TX_DATA, LOW); // No signal yet 223 | pinMode(PIN_RF_TX_NMOS, OUTPUT); // MOSFET, always output 224 | pinMode(PIN_RF_TX_PMOS, OUTPUT); // MOSFET, always output 225 | digitalWrite(PIN_RF_TX_NMOS, HIGH); // turn GND to TX receiver ON 226 | digitalWrite(PIN_RF_TX_PMOS, LOW); // turn VCC to TX receiver ON 227 | pinMode(PIN_RF_TX_GND, OUTPUT); // Initialise in/output ports 228 | pinMode(PIN_RF_TX_VCC, OUTPUT); // Initialise in/output ports 229 | digitalWrite(PIN_RF_TX_GND, LOW); // turn GND to TX receiver ON 230 | digitalWrite(PIN_RF_TX_VCC, HIGH); // turn VCC to TX receiver ON 231 | delayMicroseconds(TRANSMITTER_STABLE_DELAY_US); 232 | } 233 | 234 | void disableTX() 235 | { 236 | // TX Pins 237 | delayMicroseconds(TRANSMITTER_STABLE_DELAY_US); 238 | digitalWrite(PIN_RF_TX_DATA, LOW); // No more signal 239 | pinMode(PIN_RF_TX_DATA, INPUT); // 240 | pinMode(PIN_RF_TX_NA, INPUT); // 241 | pinMode(PIN_RF_TX_NMOS, OUTPUT); // MOSFET, always output 242 | pinMode(PIN_RF_TX_PMOS, OUTPUT); // MOSFET, always output 243 | digitalWrite(PIN_RF_TX_PMOS, HIGH); // turn VCC to TX receiver OFF 244 | digitalWrite(PIN_RF_TX_NMOS, LOW); // turn GND to TX receiver OFF 245 | pinMode(PIN_RF_TX_VCC, INPUT); 246 | pinMode(PIN_RF_TX_GND, INPUT); 247 | } 248 | #endif // RFM69_ENABLED -------------------------------------------------------------------------------- /RFLink/1_Radio.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef Radio_h 9 | #define Radio_h 10 | 11 | #include 12 | 13 | #define TRANSMITTER_STABLE_DELAY_US 500 // 500 // Delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms). 14 | #define PULLUP_RF_RX_DATA_0 false // false // Sometimes a pullup in needed on RX data pin 15 | // #define RFM69_ENABLED // use RF69OOK_IRQ_PIN as RX/TX_DATA 16 | 17 | #ifdef RFM69_ENABLED 18 | #undef BUILTIN_LED 19 | #define BUILTIN_LED 9 20 | #endif 21 | 22 | // PIN Definition 23 | // 24 | extern uint8_t PIN_RF_RX_PMOS; 25 | extern uint8_t PIN_RF_RX_NMOS; 26 | extern uint8_t PIN_RF_RX_VCC; 27 | extern uint8_t PIN_RF_RX_GND; 28 | extern uint8_t PIN_RF_RX_NA; 29 | extern uint8_t PIN_RF_RX_DATA; 30 | extern uint8_t PIN_RF_TX_PMOS; 31 | extern uint8_t PIN_RF_TX_NMOS; 32 | extern uint8_t PIN_RF_TX_VCC; 33 | extern uint8_t PIN_RF_TX_GND; 34 | extern uint8_t PIN_RF_TX_NA; 35 | extern uint8_t PIN_RF_TX_DATA; 36 | extern boolean PULLUP_RF_RX_DATA; 37 | 38 | #ifdef ESP8266 39 | // ESP8266 D1 Mini 40 | #define PIN_RF_RX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 41 | #define PIN_RF_RX_NMOS_0 D5 // Low Side N-MOSFET, active on HIGH level 42 | #define PIN_RF_RX_VCC_0 NOT_A_PIN // Power to the receiver on this pin 43 | #define PIN_RF_RX_GND_0 NOT_A_PIN // Ground to the receiver on this pin 44 | #define PIN_RF_RX_NA_0 NOT_A_PIN // Alt. RX_DATA. Forced as input 45 | #define PIN_RF_RX_DATA_0 D6 // On this input, the 433Mhz-RF signal is received. LOW when no signal. 46 | #define PIN_RF_TX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 47 | #define PIN_RF_TX_NMOS_0 D7 // Low Side N-MOSFET, active on HIGH level 48 | #define PIN_RF_TX_VCC_0 NOT_A_PIN // +5 volt / Vcc power to the transmitter on this pin 49 | #define PIN_RF_TX_GND_0 NOT_A_PIN // Ground power to the transmitter on this pin 50 | #define PIN_RF_TX_NA_0 NOT_A_PIN // Spare RX pin. Forced as input 51 | #define PIN_RF_TX_DATA_0 D4 // Data to the 433Mhz transmitter on this pin 52 | #endif 53 | 54 | #ifdef ESP32 55 | #define PIN_RF_RX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 56 | #define PIN_RF_RX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 57 | #define PIN_RF_RX_VCC_0 27 // Power to the receiver on this pin 58 | #define PIN_RF_RX_GND_0 13 // Ground to the receiver on this pin 59 | #define PIN_RF_RX_NA_0 14 // Alt. RX_DATA. Forced as input 60 | #define PIN_RF_RX_DATA_0 12 // On this input, the 433Mhz-RF signal is received. LOW when no signal. 61 | #define PIN_RF_TX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 62 | #define PIN_RF_TX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 63 | #define PIN_RF_TX_VCC_0 4 // +5 volt / Vcc power to the transmitter on this pin 64 | #define PIN_RF_TX_GND_0 16 // Ground power to the transmitter on this pin 65 | #define PIN_RF_TX_NA_0 17 // Spare RX pin. Forced as input 66 | #define PIN_RF_TX_DATA_0 2 // Data to the 433Mhz transmitter on this pin 67 | #endif 68 | 69 | #ifdef __AVR_ATmega328P__ 70 | #define PIN_RF_RX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 71 | #define PIN_RF_RX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 72 | #define PIN_RF_RX_VCC_0 4 // Power to the receiver on this pin 73 | #define PIN_RF_RX_GND_0 NOT_A_PIN // Ground to the receiver on this pin 74 | #define PIN_RF_RX_NA_0 3 // Alt. RX_DATA. Forced as input 75 | #define PIN_RF_RX_DATA_0 2 // On this input, the 433Mhz-RF signal is received. LOW when no signal. 76 | #define PIN_RF_TX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 77 | #define PIN_RF_TX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 78 | #define PIN_RF_TX_VCC_0 NOT_A_PIN // +5 volt / Vcc power to the transmitter on this pin 79 | #define PIN_RF_TX_GND_0 NOT_A_PIN // Ground power to the transmitter on this pin 80 | #define PIN_RF_TX_NA_0 NOT_A_PIN // Spare RX pin. Forced as input 81 | #define PIN_RF_TX_DATA_0 NOT_A_PIN // Data to the 433Mhz transmitter on this pin 82 | #endif 83 | 84 | #ifdef __AVR_ATmega2560__ 85 | #define PIN_RF_RX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 86 | #define PIN_RF_RX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 87 | #define PIN_RF_RX_VCC_0 16 // Power to the receiver on this pin 88 | #define PIN_RF_RX_GND_0 NOT_A_PIN // Ground to the receiver on this pin 89 | #define PIN_RF_RX_NA_0 NOT_A_PIN // Alt. RX_DATA. Forced as input 90 | #define PIN_RF_RX_DATA_0 19 // On this input, the 433Mhz-RF signal is received. LOW when no signal. 91 | #define PIN_RF_TX_PMOS_0 NOT_A_PIN // High Side P-MOSFET, active on LOW level 92 | #define PIN_RF_TX_NMOS_0 NOT_A_PIN // Low Side N-MOSFET, active on HIGH level 93 | #define PIN_RF_TX_VCC_0 15 // +5 volt / Vcc power to the transmitter on this pin 94 | #define PIN_RF_TX_GND_0 NOT_A_PIN // Ground power to the transmitter on this pin 95 | #define PIN_RF_TX_NA_0 NOT_A_PIN // Spare RX pin. Forced as input 96 | #define PIN_RF_TX_DATA_0 14 // Data to the 433Mhz transmitter on this pin 97 | #endif 98 | 99 | enum Radio_State 100 | { 101 | Radio_OFF, 102 | Radio_RX, 103 | Radio_TX, 104 | Radio_NA 105 | }; 106 | 107 | void set_Radio_mode(Radio_State new_state); 108 | #if (defined(ESP8266) || defined(ESP32)) 109 | void show_Radio_Pin(); 110 | #endif // ESP8266 || ESP32 111 | #endif // Radio_h -------------------------------------------------------------------------------- /RFLink/2_Signal.h: -------------------------------------------------------------------------------- 1 | /// ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef Signal_h 9 | #define Signal_h 10 | 11 | #include 12 | 13 | #define RAW_BUFFER_SIZE 292 // 292 // Maximum number of pulses that is received in one go. 14 | #define MIN_RAW_PULSES 36 // 36 // Minimal number of bits that need to have been received before we spend CPU time on decoding the signal. 15 | #define RAWSIGNAL_SAMPLE_RATE 32 // 32 // =8 bits. Sample width / resolution in uSec for raw RF pulses. 16 | #define SIGNAL_SEEK_TIMEOUT_MS 25 // 25 // After this time in mSec, RF signal will be considered absent. 17 | #define SIGNAL_MIN_PREAMBLE_US 400 // 400 // After this time in uSec, a RF signal will be considered to have started. 18 | #define MIN_PULSE_LENGTH_US 100 // 100 // Pulses shorter than this value in uSec. will be seen as garbage and not taken as actual pulses. 19 | #define SIGNAL_END_TIMEOUT_US 5000 // 5000 // After this time in uSec, the RF signal will be considered to have stopped. 20 | #define SIGNAL_REPEAT_TIME_MS 250 // 500 // Time in mSec. in which the same RF signal should not be accepted again. Filters out retransmits. 21 | #define SCAN_HIGH_TIME_MS 50 // 50 // time interval in ms. fast processing for background tasks 22 | 23 | struct RawSignalStruct // Raw signal variabelen places in a struct 24 | { 25 | int Number; // Number of pulses, times two as every pulse has a mark and a space. 26 | byte Repeats; // Number of re-transmits on transmit actions. 27 | byte Delay; // Delay in ms. after transmit of a single RF pulse packet 28 | byte Multiply; // Pulses[] * Multiply is the real pulse time in microseconds 29 | unsigned long Time; // Timestamp indicating when the signal was received (millis()) 30 | byte Pulses[RAW_BUFFER_SIZE + 1]; // Table with the measured pulses in microseconds divided by RawSignal.Multiply. (halves RAM usage) 31 | // First pulse is located in element 1. Element 0 is used for special purposes, like signalling the use of a specific plugin 32 | }; 33 | 34 | extern RawSignalStruct RawSignal; 35 | extern unsigned long SignalCRC; // holds the bitstream value for some plugins to identify RF repeats 36 | extern unsigned long SignalCRC_1; // holds the previous SignalCRC (for mixed burst protocols) 37 | extern byte SignalHash; // holds the processed plugin number 38 | extern byte SignalHashPrevious; // holds the last processed plugin number 39 | extern unsigned long RepeatingTimer; 40 | 41 | boolean FetchSignal(); 42 | boolean ScanEvent(void); 43 | // void RFLinkHW(void); 44 | // void RawSendRF(void); 45 | 46 | void AC_Send(unsigned long data, byte cmd); 47 | 48 | #endif -------------------------------------------------------------------------------- /RFLink/3_Serial.cpp: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #include 9 | #include "RFLink.h" 10 | #include "1_Radio.h" 11 | #include "3_Serial.h" 12 | #include "4_Display.h" 13 | #include "5_Plugin.h" 14 | 15 | char InputBuffer_Serial[INPUT_COMMAND_SIZE]; 16 | 17 | boolean ReadSerial(); 18 | boolean CheckCmd(); 19 | boolean CopySerial(char *); 20 | /*********************************************************************************************/ 21 | 22 | boolean CheckSerial() 23 | { 24 | if (ReadSerial()) 25 | { 26 | #ifdef SERIAL_ENABLED 27 | Serial.flush(); 28 | Serial.print(F("Message arrived [Serial] ")); 29 | Serial.println(InputBuffer_Serial); 30 | #endif 31 | if (CheckCmd()) 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | boolean CheckMQTT(byte *byte_in) 38 | { 39 | if (CopySerial((char *)byte_in)) 40 | { 41 | #ifdef SERIAL_ENABLED 42 | Serial.flush(); 43 | Serial.print(F("Message arrived [MQTT] ")); 44 | Serial.println(InputBuffer_Serial); 45 | #endif 46 | if (CheckCmd()) 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | boolean CopySerial(char *src) 53 | { 54 | return (strncpy(InputBuffer_Serial, src, INPUT_COMMAND_SIZE - 2)); 55 | } 56 | 57 | boolean ReadSerial() 58 | { 59 | // SERIAL: *************** Check if there is data ready on the serial port ********************** 60 | static byte SerialInByte; // incoming character value 61 | static byte SerialInByteCounter; // number of bytes counter 62 | static unsigned long FocusTimer; // Timer to keep focus on the task during communication 63 | 64 | if (Serial.available()) 65 | { 66 | SerialInByteCounter = 0; 67 | 68 | FocusTimer = millis() + FOCUS_TIME_MS; 69 | while (true) 70 | { 71 | if (Serial.available()) 72 | { 73 | SerialInByte = Serial.read(); 74 | 75 | if (isprint(SerialInByte)) 76 | InputBuffer_Serial[SerialInByteCounter++] = SerialInByte; 77 | 78 | FocusTimer = millis() + FOCUS_TIME_MS; 79 | } 80 | 81 | if ((SerialInByte == '\n') || (millis() >= FocusTimer) || (SerialInByteCounter >= (INPUT_COMMAND_SIZE - 1))) 82 | // new line character or timeout or buffer full 83 | { 84 | // if (InputBuffer_Serial[SerialInByteCounter - 1] == ';') 85 | // InputBuffer_Serial[SerialInByteCounter - 1] = 0; // remove last ";" char 86 | // else 87 | InputBuffer_Serial[SerialInByteCounter] = 0; // serial data is complete 88 | return true; 89 | } 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | boolean CheckCmd() 96 | { 97 | static byte ValidCommand = 0; 98 | if (strlen(InputBuffer_Serial) > 7) 99 | { // need to see minimal 8 characters on the serial port 100 | // 10;....;..;ON; 101 | if (strncmp(InputBuffer_Serial, "10;", 3) == 0) 102 | { // Command from Master to RFLink 103 | // ------------------------------------------------------- 104 | // Handle Device Management Commands 105 | // ------------------------------------------------------- 106 | if (strncasecmp(InputBuffer_Serial + 3, "PING;",5) == 0) 107 | { 108 | display_Header(); 109 | display_Name(PSTR("PONG")); 110 | display_Footer(); 111 | } 112 | else if (strncasecmp(InputBuffer_Serial + 3, "REBOOT;",7) == 0) 113 | { 114 | display_Header(); 115 | display_Name(PSTR("REBOOT")); 116 | display_Footer(); 117 | CallReboot(); 118 | } 119 | else if (strncasecmp(InputBuffer_Serial + 3, "RFDEBUG=O", 9) == 0) 120 | { 121 | if (InputBuffer_Serial[12] == 'N' || InputBuffer_Serial[12] == 'n') 122 | { 123 | RFDebug = true; // full debug on 124 | QRFDebug = false; // q full debug off 125 | RFUDebug = false; // undecoded debug off 126 | QRFUDebug = false; // q undecoded debug off 127 | display_Header(); 128 | display_Name(PSTR("RFDEBUG=ON")); 129 | display_Footer(); 130 | } 131 | else 132 | { 133 | RFDebug = false; // full debug off 134 | display_Header(); 135 | display_Name(PSTR("RFDEBUG=OFF")); 136 | display_Footer(); 137 | } 138 | } 139 | else if (strncasecmp(InputBuffer_Serial + 3, "RFUDEBUG=O", 10) == 0) 140 | { 141 | if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') 142 | { 143 | RFDebug = false; // full debug off 144 | QRFDebug = false; // q debug off 145 | RFUDebug = true; // undecoded debug on 146 | QRFUDebug = false; // q undecoded debug off 147 | display_Header(); 148 | display_Name(PSTR("RFUDEBUG=ON")); 149 | display_Footer(); 150 | } 151 | else 152 | { 153 | RFUDebug = false; // undecoded debug off 154 | display_Header(); 155 | display_Name(PSTR("RFUDEBUG=OFF")); 156 | display_Footer(); 157 | } 158 | } 159 | else if (strncasecmp(InputBuffer_Serial + 3, "QRFDEBUG=O", 10) == 0) 160 | { 161 | if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') 162 | { 163 | RFDebug = false; // full debug off 164 | QRFDebug = true; // q debug on 165 | RFUDebug = false; // undecoded debug off 166 | QRFUDebug = false; // q undecoded debug off 167 | display_Header(); 168 | display_Name(PSTR("QRFDEBUG=ON")); 169 | display_Footer(); 170 | } 171 | else 172 | { 173 | QRFDebug = false; // q debug off 174 | display_Header(); 175 | display_Name(PSTR("QRFDEBUG=OFF")); 176 | display_Footer(); 177 | } 178 | } 179 | else if (strncasecmp(InputBuffer_Serial + 3, "QRFUDEBUG=O", 11) == 0) 180 | { 181 | if (InputBuffer_Serial[14] == 'N' || InputBuffer_Serial[14] == 'n') 182 | { 183 | RFDebug = false; // full debug off 184 | QRFDebug = false; // q debug off 185 | RFUDebug = false; // undecoded debug off 186 | QRFUDebug = true; // q undecoded debug on 187 | display_Header(); 188 | display_Name(PSTR("QRFUDEBUG=ON")); 189 | display_Footer(); 190 | } 191 | else 192 | { 193 | QRFUDebug = false; // q undecode debug off 194 | display_Header(); 195 | display_Name(PSTR("QRFUDEBUG=OFF")); 196 | display_Footer(); 197 | } 198 | } 199 | else if (strncasecmp(InputBuffer_Serial + 3, "VERSION", 7) == 0) 200 | { 201 | display_Header(); 202 | display_Splash(); 203 | display_Footer(); 204 | } 205 | else 206 | { 207 | // ------------------------------------------------------- 208 | // Handle Generic Commands / Translate protocol data into Nodo text commands 209 | // ------------------------------------------------------- 210 | set_Radio_mode(Radio_TX); 211 | 212 | if (PluginTXCall(0, InputBuffer_Serial)) 213 | ValidCommand = 1; 214 | else // Answer that an invalid command was received? 215 | ValidCommand = 2; 216 | 217 | set_Radio_mode(Radio_RX); 218 | } 219 | } 220 | } // if > 7 221 | if (ValidCommand != 0) 222 | { 223 | display_Header(); 224 | if (ValidCommand == 1) 225 | display_Name(PSTR("OK")); 226 | else 227 | display_Name(PSTR("CMD UNKNOWN")); 228 | display_Footer(); 229 | } 230 | InputBuffer_Serial[0] = 0; // serial data has been processed. 231 | ValidCommand = 0; 232 | return true; 233 | } 234 | 235 | /*********************************************************************************************/ -------------------------------------------------------------------------------- /RFLink/3_Serial.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef Serial_h 9 | #define Serial_h 10 | 11 | #include 12 | 13 | #define BAUD 921600 // 57600 // Baudrate for serial communication. 14 | #define INPUT_COMMAND_SIZE 60 // 60 // Maximum number of characters that a command via serial can be. 15 | #define FOCUS_TIME_MS 50 // 50 // Duration in mSec. that, after receiving serial data from USB only the serial port is checked. 16 | 17 | extern char InputBuffer_Serial[INPUT_COMMAND_SIZE]; 18 | 19 | boolean CheckSerial(); 20 | boolean CheckMQTT(byte *); 21 | #endif -------------------------------------------------------------------------------- /RFLink/4_Display.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef Misc_h 9 | #define Misc_h 10 | 11 | #include 12 | 13 | #define PRINT_BUFFER_SIZE 90 // 90 // Maximum number of characters that a command should print in one go via the print buffer. 14 | 15 | // extern byte PKSequenceNumber; // 1 byte packet counter 16 | extern char pbuffer[PRINT_BUFFER_SIZE]; // Buffer for printing data 17 | 18 | void display_Header(void); 19 | void display_Name(const char *); 20 | void display_Footer(void); 21 | void display_Splash(void); 22 | void display_IDn(unsigned long, byte); 23 | void display_IDc(const char *); 24 | void display_SWITCH(byte); 25 | void display_SWITCHc(const char *); 26 | void display_CHAN(byte); 27 | enum CMD_Group 28 | { 29 | CMD_Single, 30 | CMD_All 31 | }; 32 | enum CMD_OnOff 33 | { 34 | CMD_Off, 35 | CMD_On, 36 | CMD_Bright, 37 | CMD_Dim, 38 | CMD_Unknown 39 | }; 40 | void display_CMD(boolean, byte); 41 | void display_SET_LEVEL(byte); 42 | void display_TEMP(unsigned int); 43 | enum HUM_Type 44 | { 45 | HUM_HEX, 46 | HUM_BCD 47 | }; 48 | void display_HUM(byte, boolean); 49 | void display_BARO(unsigned int); 50 | void display_HSTATUS(byte); 51 | void display_BFORECAST(byte); 52 | void display_UV(unsigned int); 53 | void display_LUX(unsigned int); 54 | void display_BAT(boolean); 55 | void display_RAIN(unsigned int); 56 | void display_RAINRATE(unsigned int); 57 | void display_WINSP(unsigned int); 58 | void display_AWINSP(unsigned int); 59 | void display_WINGS(unsigned int); 60 | void display_WINDIR(unsigned int); 61 | void display_WINCHL(unsigned int); 62 | void display_WINTMP(unsigned int); 63 | void display_CHIME(unsigned int); 64 | enum SMOKE_OnOff 65 | { 66 | SMOKE_Off, 67 | SMOKE_On 68 | }; 69 | void display_SMOKEALERT(boolean); 70 | enum PIR_OnOff 71 | { 72 | PIR_Off, 73 | PIR_On 74 | }; 75 | void display_PIR(boolean); 76 | void display_CO2(unsigned int); 77 | void display_SOUND(unsigned int); 78 | void display_KWATT(unsigned int); 79 | void display_WATT(unsigned int); 80 | void display_CURRENT(unsigned int); 81 | void display_DIST(unsigned int); 82 | void display_METER(unsigned int); 83 | void display_VOLT(unsigned int); 84 | void display_RGBW(unsigned int); 85 | 86 | void retrieve_Init(); 87 | boolean retrieve_Name(const char *); 88 | boolean retrieve_ID(unsigned long &); 89 | boolean retrieve_Switch(byte &); 90 | boolean retrieve_Command(byte &, byte &); 91 | boolean retrieve_End(); 92 | 93 | #define VALUE_PAIR 44 94 | #define VALUE_ALLOFF 55 95 | #define VALUE_OFF 74 96 | #define VALUE_ON 75 97 | #define VALUE_DIM 76 98 | #define VALUE_BRIGHT 77 99 | #define VALUE_UP 78 100 | #define VALUE_DOWN 79 101 | #define VALUE_STOP 80 102 | #define VALUE_CONFIRM 81 103 | #define VALUE_LIMIT 82 104 | #define VALUE_ALLON 141 105 | 106 | int str2cmd(char *); 107 | void replacechar(char *, char, char); 108 | 109 | #if (defined(ESP8266) || defined(ESP32)) 110 | uint8_t String2GPIO(String); 111 | String GPIO2String(uint8_t uGPIO); 112 | #endif // ESP8266 || ESP32 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /RFLink/5_Plugin.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef Plugin_h 9 | #define Plugin_h 10 | 11 | #include 12 | 13 | #define PLUGIN_MAX 84 // Maximum number of Receive plugins 14 | #define PLUGIN_TX_MAX 84 // Maximum number of Transmit plugins 15 | 16 | enum PState 17 | { 18 | P_Forbidden, 19 | P_Disabled, 20 | P_Enabled, 21 | P_Mandatory 22 | }; 23 | 24 | extern boolean (*Plugin_ptr[PLUGIN_MAX])(byte, char *); // Receive plugins 25 | extern byte Plugin_id[PLUGIN_MAX]; 26 | extern byte Plugin_State[PLUGIN_MAX]; 27 | #ifndef ARDUINO_AVR_UNO // Optimize memory limite to 2048 bytes on arduino uno 28 | extern String Plugin_Description[PLUGIN_MAX]; 29 | #endif 30 | 31 | extern boolean (*PluginTX_ptr[PLUGIN_TX_MAX])(byte, char *); // Transmit plugins 32 | extern byte PluginTX_id[PLUGIN_TX_MAX]; 33 | extern byte PluginTX_State[PLUGIN_TX_MAX]; 34 | 35 | extern boolean RFDebug; // debug RF signals with plugin 001 (no decode) 36 | extern boolean QRFDebug; // debug RF signals with plugin 001 but no multiplication (faster?, compact) 37 | extern boolean RFUDebug; // debug RF signals with plugin 254 (decode 1st) 38 | extern boolean QRFUDebug; // debug RF signals with plugin 254 but no multiplication (faster?, compact) 39 | 40 | // Of all the devices that are compiled, the addresses are stored in a table so that you can jump to them 41 | void PluginInit(void); 42 | void PluginTXInit(void); 43 | byte PluginInitCall(byte Function, char *str); 44 | byte PluginTXInitCall(byte Function, char *str); 45 | byte PluginRXCall(byte Function, char *str); 46 | byte PluginTXCall(byte Function, char *str); 47 | 48 | #endif -------------------------------------------------------------------------------- /RFLink/6_Credentials.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef CREDENTIALS_h 9 | #define CREDENTIALS_h 10 | 11 | #include "RFLink.h" 12 | 13 | // local AP 14 | String WIFI_SSID = "xxx"; 15 | String WIFI_PSWD = "xxx"; 16 | 17 | // DHCP or Static IP 18 | // #define USE_DHCP 19 | #ifndef USE_DHCP 20 | String WIFI_IP = "192.168.1.xxx"; 21 | String WIFI_DNS = "192.168.1.xxx"; 22 | String WIFI_GATEWAY = "192.168.1.xxx"; 23 | String WIFI_SUBNET = "255.255.255.0"; 24 | #endif 25 | 26 | // MQTT Server 27 | String MQTT_SERVER = "192.168.1.xxx"; 28 | String MQTT_PORT = "1883"; 29 | String MQTT_ID = "ESP8266-RFLink_xxx"; 30 | String MQTT_USER = "xxx"; 31 | String MQTT_PSWD = "xxx"; 32 | 33 | // MQTT Topic 34 | String MQTT_TOPIC_OUT = "/ESP00/msg"; 35 | String MQTT_TOPIC_IN = "/ESP00/cmd"; 36 | String MQTT_TOPIC_LWT = "/ESP00/lwt"; 37 | 38 | #ifdef CHECK_CACERT 39 | static const char ca_cert[] PROGMEM = R"EOF( 40 | -----BEGIN CERTIFICATE----- 41 | MIID (...) 42 | -----END CERTIFICATE----- 43 | )EOF"; 44 | #endif //CHECK_CACERT 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /RFLink/6_WiFi_MQTT.cpp: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #include 9 | // #include 10 | #include "RFLink.h" 11 | #include "3_Serial.h" 12 | #include "4_Display.h" 13 | #include "6_WiFi_MQTT.h" 14 | #include "6_Credentials.h" 15 | 16 | #ifdef ESP32 17 | #include 18 | #elif ESP8266 19 | #include 20 | #endif 21 | 22 | #ifdef MQTT_ENABLED 23 | 24 | // MQTT_KEEPALIVE : keepAlive interval in Seconds 25 | #define MQTT_KEEPALIVE 60 26 | 27 | // MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds 28 | #define MQTT_SOCKET_TIMEOUT 60 29 | 30 | #include 31 | boolean bResub; // uplink reSubscribe after setup only 32 | 33 | // Update these with values suitable for your network. 34 | 35 | #ifdef MQTT_SSL 36 | #include 37 | WiFiClientSecure WIFIClient; 38 | #else //SSL 39 | #include 40 | WiFiClient WIFIClient; 41 | #endif //SSL 42 | 43 | PubSubClient MQTTClient; // MQTTClient(WIFIClient); 44 | 45 | void callback(char *, byte *, unsigned int); 46 | 47 | static String WIFI_PWR = String(WIFI_PWR_0); 48 | 49 | void setup_WIFI() 50 | { 51 | WiFi.persistent(false); 52 | WiFi.setAutoReconnect(true); 53 | #ifdef ESP32 54 | WiFi.setTxPower(WIFI_POWER_11dBm); 55 | #elif ESP8266 56 | WiFi.setSleepMode(WIFI_MODEM_SLEEP); 57 | WiFi.setOutputPower(WIFI_PWR.toInt()); 58 | #endif // ESP 59 | 60 | // For Static IP 61 | #ifndef USE_DHCP 62 | WiFi.config(ipaddr_addr(WIFI_IP.c_str()), ipaddr_addr(WIFI_GATEWAY.c_str()), ipaddr_addr(WIFI_SUBNET.c_str())); 63 | #endif // USE_DHCP 64 | } 65 | 66 | void start_WIFI() 67 | { 68 | WiFi.mode(WIFI_STA); 69 | 70 | // We start by connecting to a WiFi network 71 | Serial.print(F("WiFi SSID :\t\t")); 72 | Serial.println(WIFI_SSID.c_str()); 73 | Serial.print(F("WiFi Connection :\t")); 74 | WiFi.begin(WIFI_SSID.c_str(), WIFI_PSWD.c_str()); 75 | 76 | while (WiFi.status() != WL_CONNECTED) 77 | { 78 | delay(500); 79 | Serial.print("."); 80 | } 81 | 82 | Serial.println(F("Established")); 83 | Serial.print(F("WiFi IP :\t\t")); 84 | Serial.println(WiFi.localIP()); 85 | Serial.print(F("WiFi RSSI :\t\t")); 86 | Serial.println(WiFi.RSSI()); 87 | 88 | /* 89 | ArduinoOTA.onStart([]() { 90 | String type; 91 | if (ArduinoOTA.getCommand() == U_FLASH) 92 | type = "sketch"; 93 | else // U_SPIFFS 94 | type = "filesystem"; 95 | 96 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() 97 | Serial.println("Start updating " + type); 98 | }); 99 | ArduinoOTA.onEnd([]() { 100 | Serial.println("\nEnd"); 101 | }); 102 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 103 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 104 | }); 105 | ArduinoOTA.onError([](ota_error_t error) { 106 | Serial.printf("Error[%u]: ", error); 107 | if (error == OTA_AUTH_ERROR) 108 | Serial.println("Auth Failed"); 109 | else if (error == OTA_BEGIN_ERROR) 110 | Serial.println("Begin Failed"); 111 | else if (error == OTA_CONNECT_ERROR) 112 | Serial.println("Connect Failed"); 113 | else if (error == OTA_RECEIVE_ERROR) 114 | Serial.println("Receive Failed"); 115 | else if (error == OTA_END_ERROR) 116 | Serial.println("End Failed"); 117 | }); 118 | ArduinoOTA.begin(); 119 | */ 120 | } 121 | 122 | void stop_WIFI() 123 | { 124 | WiFi.disconnect(); 125 | WiFi.mode(WIFI_OFF); 126 | delay(500); 127 | } 128 | 129 | void setup_MQTT() 130 | { 131 | Serial.print(F("SSL :\t\t\t")); 132 | #ifdef MQTT_SSL 133 | if (MQTT_PORT == "") 134 | MQTT_PORT = "8883"; // just in case .... 135 | #ifdef CHECK_CACERT 136 | Serial.println(F("Using ca_cert")); 137 | WIFIClient.setCACert(ca_cert); 138 | #else 139 | Serial.println(F("Insecure (No Key/Cert/Fp)")); 140 | #endif // MQTT_CACERT 141 | #else 142 | if (MQTT_PORT == "") 143 | MQTT_PORT = "1883"; // just in case .... 144 | Serial.println(F("Not Set")); 145 | #endif //SSL 146 | 147 | MQTTClient.setClient(WIFIClient); 148 | MQTTClient.setServer(MQTT_SERVER.c_str(), MQTT_PORT.toInt()); 149 | MQTTClient.setCallback(callback); 150 | bResub = true; 151 | } 152 | 153 | void callback(char *topic, byte *payload, unsigned int length) 154 | { 155 | payload[length] = 0; 156 | CheckMQTT(payload); 157 | } 158 | 159 | void reconnect() 160 | { 161 | bResub = true; 162 | 163 | while (!MQTTClient.connected()) 164 | { 165 | if (WiFi.status() != WL_CONNECTED) 166 | { 167 | stop_WIFI(); 168 | start_WIFI(); 169 | } 170 | 171 | Serial.print(F("MQTT Server :\t\t")); 172 | Serial.println(MQTT_SERVER.c_str()); 173 | Serial.print(F("MQTT Connection :\t")); 174 | 175 | #ifdef MQTT_LWT 176 | #ifdef ESP32 177 | if (MQTTClient.connect(MQTT_ID.c_str(), MQTT_USER.c_str(), MQTT_PSWD.c_str(), (MQTT_TOPIC_LWT).c_str(), 2, true, PSTR("Offline"))) 178 | #elif ESP8266 179 | if (MQTTClient.connect(MQTT_ID.c_str(), MQTT_USER.c_str(), MQTT_PSWD.c_str(), (MQTT_TOPIC_LWT).c_str(), 2, true, "Offline")) 180 | #endif // ESP 181 | #else // MQTT_LWT 182 | if (MQTTClient.connect(MQTT_ID.c_str(), MQTT_USER.c_str(), MQTT_PSWD.c_str())) 183 | #endif // MQTT_LWT 184 | { 185 | Serial.println(F("Established")); 186 | Serial.print(F("MQTT ID :\t\t")); 187 | Serial.println(MQTT_ID.c_str()); 188 | Serial.print(F("MQTT Username :\t\t")); 189 | Serial.println(MQTT_USER.c_str()); 190 | #ifdef MQTT_LWT 191 | #ifdef ESP32 192 | MQTTClient.publish((MQTT_TOPIC_LWT).c_str(), PSTR("Online"), true); 193 | #elif ESP8266 194 | MQTTClient.publish((MQTT_TOPIC_LWT).c_str(), "Online", true); 195 | #endif // ESP 196 | #endif // MQTT_LWT 197 | } 198 | else 199 | { 200 | Serial.print(F("Failed - rc=")); 201 | Serial.println(MQTTClient.state()); 202 | Serial.println(F("MQTT Retry :\tTry again in 5 seconds")); 203 | // Wait 5 seconds before retrying 204 | for (byte i = 0; i < 10; i++) 205 | delay(500); // delay(5000) may cause hang 206 | } 207 | } 208 | } 209 | 210 | void publishMsg() 211 | { 212 | static boolean MQTT_RETAINED = MQTT_RETAINED_0; 213 | 214 | if (!MQTTClient.connected()) 215 | reconnect(); 216 | MQTTClient.publish(MQTT_TOPIC_OUT.c_str(), pbuffer, MQTT_RETAINED); 217 | } 218 | 219 | void checkMQTTloop() 220 | { 221 | static unsigned long lastCheck = millis(); 222 | 223 | if (millis() > lastCheck + MQTT_LOOP_MS) 224 | { 225 | if (!MQTTClient.connected()) 226 | reconnect(); 227 | 228 | if (bResub) 229 | { 230 | // Once connected, resubscribe 231 | MQTTClient.subscribe(MQTT_TOPIC_IN.c_str()); 232 | bResub = false; 233 | delay(10); 234 | } 235 | MQTTClient.loop(); 236 | lastCheck = millis(); 237 | } 238 | // ArduinoOTA.handle(); 239 | } 240 | 241 | #else // MQTT_ENABLED 242 | 243 | #if (defined(ESP32) || defined(ESP8266)) 244 | void setup_WIFI_OFF() 245 | { 246 | WiFi.persistent(false); 247 | WiFi.setAutoReconnect(false); 248 | #ifdef ESP8266 249 | WiFi.setSleepMode(WIFI_MODEM_SLEEP); 250 | #endif 251 | WiFi.mode(WIFI_OFF); 252 | #ifdef ESP8266 253 | WiFi.forceSleepBegin(); 254 | #endif 255 | } 256 | #endif 257 | #endif // MQTT_ENABLED 258 | -------------------------------------------------------------------------------- /RFLink/6_WiFi_MQTT.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef WiFi_MQTT_h 9 | #define WiFi_MQTT_h 10 | 11 | #include 12 | #include "RFLink.h" 13 | 14 | #ifdef ESP32 15 | #include 16 | #elif ESP8266 17 | #include 18 | #endif 19 | 20 | #ifdef MQTT_ENABLED 21 | extern char MQTTbuffer[PRINT_BUFFER_SIZE]; // Buffer for MQTT message 22 | 23 | void setup_WIFI(); 24 | void start_WIFI(); 25 | void stop_WIFI(); 26 | void setup_MQTT(); 27 | void reconnect(); 28 | void publishMsg(); 29 | void checkMQTTloop(); 30 | 31 | #else // MQTT_ENABLED 32 | 33 | #if (defined(ESP32) || defined(ESP8266)) 34 | void setup_WIFI_OFF(); 35 | #endif 36 | 37 | #endif // MQTT_ENABLED 38 | 39 | #endif // WiFi_MQTT_h -------------------------------------------------------------------------------- /RFLink/7_Utils.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Various utility functions for use by device drivers. 3 | 4 | Copyright (C) 2015 Tommy Vestermark 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | */ 11 | 12 | #ifndef INCLUDE_UTIL_H_ 13 | #define INCLUDE_UTIL_H_ 14 | 15 | #include 16 | 17 | // Helper macros, collides with MSVC's stdlib.h unless NOMINMAX is used 18 | #ifndef MAX 19 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 20 | #endif 21 | #ifndef MIN 22 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 23 | #endif 24 | 25 | /// Reverse (reflect) the bits in an 8 bit byte. 26 | /// 27 | /// @param x input byte 28 | /// @return bit reversed byte 29 | uint8_t reverse8(uint8_t x); 30 | 31 | /// Reflect (reverse LSB to MSB) each byte of a number of bytes. 32 | /// 33 | /// @param message bytes of message data 34 | /// @param num_bytes number of bytes to reflect 35 | void reflect_bytes(uint8_t message[], unsigned num_bytes); 36 | 37 | /// Reflect (reverse LSB to MSB) each nibble in an 8 bit byte, preserves nibble order. 38 | /// 39 | /// @param x input byte 40 | /// @return reflected nibbles 41 | uint8_t reflect4(uint8_t x); 42 | 43 | /// Reflect (reverse LSB to MSB) each nibble in a number of bytes. 44 | /// 45 | /// @param message bytes of nibble message data 46 | /// @param num_bytes number of bytes to reflect 47 | void reflect_nibbles(uint8_t message[], unsigned num_bytes); 48 | 49 | /// Unstuff nibbles with 1-bit separator (4B1S) to bytes, returns number of successfully unstuffed nibbles. 50 | /// 51 | /// @param message bytes of message data 52 | /// @param offset_bits start offset of message in bits 53 | /// @param num_bits message length in bits 54 | /// @param dst target buffer for extracted nibbles, at least num_bits/5 size 55 | unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst); 56 | 57 | /// CRC-4. 58 | /// 59 | /// @param message array of bytes to check 60 | /// @param nBytes number of bytes in message 61 | /// @param polynomial CRC polynomial 62 | /// @param init starting crc value 63 | /// @return CRC value 64 | uint8_t crc4(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init); 65 | 66 | /// CRC-7. 67 | /// 68 | /// @param message array of bytes to check 69 | /// @param nBytes number of bytes in message 70 | /// @param polynomial CRC polynomial 71 | /// @param init starting crc value 72 | /// @return CRC value 73 | uint8_t crc7(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init); 74 | 75 | /// Generic Cyclic Redundancy Check CRC-8. 76 | /// 77 | /// Example polynomial: 0x31 = x8 + x5 + x4 + 1 (x8 is implicit) 78 | /// Example polynomial: 0x80 = x8 + x7 (a normal bit-by-bit parity XOR) 79 | /// 80 | /// @param message array of bytes to check 81 | /// @param nBytes number of bytes in message 82 | /// @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one) 83 | /// @param init starting crc value 84 | /// @return CRC value 85 | uint8_t crc8(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init); 86 | 87 | /// "Little-endian" Cyclic Redundancy Check CRC-8 LE 88 | /// Input and output are reflected, i.e. least significant bit is shifted in first. 89 | /// 90 | /// @param message array of bytes to check 91 | /// @param nBytes number of bytes in message 92 | /// @param polynomial CRC polynomial 93 | /// @param init starting crc value 94 | /// @return CRC value 95 | uint8_t crc8le(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init); 96 | 97 | /// CRC-16 LSB. 98 | /// Input and output are reflected, i.e. least significant bit is shifted in first. 99 | /// Note that poly and init already need to be reflected. 100 | /// 101 | /// @param message array of bytes to check 102 | /// @param nBytes number of bytes in message 103 | /// @param polynomial CRC polynomial 104 | /// @param init starting crc value 105 | /// @return CRC value 106 | uint16_t crc16lsb(uint8_t const message[], unsigned nBytes, uint16_t polynomial, uint16_t init); 107 | 108 | /// CRC-16. 109 | /// 110 | /// @param message array of bytes to check 111 | /// @param nBytes number of bytes in message 112 | /// @param polynomial CRC polynomial 113 | /// @param init starting crc value 114 | /// @return CRC value 115 | uint16_t crc16(uint8_t const message[], unsigned nBytes, uint16_t polynomial, uint16_t init); 116 | 117 | /// Digest-8 by "LFSR-based Toeplitz hash". 118 | /// 119 | /// @param message bytes of message data 120 | /// @param bytes number of bytes to digest 121 | /// @param gen key stream generator, needs to includes the MSB if the LFSR is rolling 122 | /// @param key initial key 123 | /// @return digest value 124 | uint8_t lfsr_digest8(uint8_t const message[], unsigned bytes, uint8_t gen, uint8_t key); 125 | 126 | /// Digest-8 by "LFSR-based Toeplitz hash", byte reflect, bit reflect. 127 | /// 128 | /// @param message bytes of message data 129 | /// @param bytes number of bytes to digest 130 | /// @param gen key stream generator, needs to includes the MSB if the LFSR is rolling 131 | /// @param key initial key 132 | /// @return digest value 133 | uint8_t lfsr_digest8_reflect(uint8_t const message[], int bytes, uint8_t gen, uint8_t key); 134 | 135 | /// Digest-16 by "LFSR-based Toeplitz hash". 136 | /// 137 | /// @param data up to 32 bits data, LSB aligned 138 | /// @param bits number of bits to digest 139 | /// @param gen key stream generator, needs to includes the MSB if the LFSR is rolling 140 | /// @param key initial key 141 | /// @return digest value 142 | uint16_t lfsr_digest16(uint32_t data, int bits, uint16_t gen, uint16_t key); 143 | 144 | /// Compute bit parity of a single byte (8 bits). 145 | /// 146 | /// @param byte single byte to check 147 | /// @return 1 odd parity, 0 even parity 148 | int parity8(uint8_t byte); 149 | 150 | /// Compute bit parity of a number of bytes. 151 | /// 152 | /// @param message bytes of message data 153 | /// @param num_bytes number of bytes to sum 154 | /// @return 1 odd parity, 0 even parity 155 | int parity_bytes(uint8_t const message[], unsigned num_bytes); 156 | 157 | /// Compute XOR (byte-wide parity) of a number of bytes. 158 | /// 159 | /// @param message bytes of message data 160 | /// @param num_bytes number of bytes to sum 161 | /// @return summation value, per bit-position 1 odd parity, 0 even parity 162 | uint8_t xor_bytes(uint8_t const message[], unsigned num_bytes); 163 | 164 | /// Compute Addition of a number of bytes. 165 | /// 166 | /// @param message bytes of message data 167 | /// @param num_bytes number of bytes to sum 168 | /// @return summation value 169 | int add_bytes(uint8_t const message[], unsigned num_bytes); 170 | 171 | /// Compute Addition of a number of nibbles (byte wise). 172 | /// 173 | /// @param message bytes (of two nibbles) of message data 174 | /// @param num_bytes number of bytes to sum 175 | /// @return summation value 176 | int add_nibbles(uint8_t const message[], unsigned num_bytes); 177 | 178 | #endif /* INCLUDE_UTIL_H_ */ 179 | -------------------------------------------------------------------------------- /RFLink/8_OLED.cpp: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #include 9 | #include "RFLink.h" 10 | #include "8_OLED.h" 11 | 12 | #ifdef OLED_ENABLED 13 | 14 | #include "4_Display.h" 15 | #include "8_OLED.h" 16 | #include // Comment to avoid dependency graph inclusion 17 | 18 | #define U8X8_PIN_NONE 255 19 | // 0.91" I2C 128x32 Display 20 | // U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE, /* clock=*/PIN_OLED_SCL, /* data=*/PIN_OLED_SDA); 21 | // U8X8_SSD1306_128X64_ALT0_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE, /* clock=*/PIN_OLED_SCL, /* data=*/PIN_OLED_SDA); 22 | U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE, /* clock=*/PIN_OLED_SCL, /* data=*/PIN_OLED_SDA); 23 | // U8X8_SSD1306_128X64_VCOMH0_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE, /* clock=*/PIN_OLED_SCL, /* data=*/PIN_OLED_SDA); 24 | 25 | #define U8LOG_WIDTH 16 26 | #define U8LOG_HEIGHT 8 27 | uint8_t u8log_buffer[U8LOG_WIDTH * U8LOG_HEIGHT]; 28 | U8X8LOG u8x8log; 29 | 30 | void setup_OLED() 31 | { 32 | u8x8.begin(); 33 | u8x8.setPowerSave(1); 34 | u8x8.setContrast(OLED_CONTRAST); 35 | u8x8.setFlipMode(OLED_FLIP); 36 | 37 | u8x8log.begin(u8x8, U8LOG_WIDTH, U8LOG_HEIGHT, u8log_buffer); 38 | u8x8log.setRedrawMode(0); // 0: Update screen with newline, 1: Update screen for every char 39 | u8x8log.setLineHeightOffset(0); 40 | } 41 | 42 | void splash_OLED() 43 | { 44 | char ver[7]; 45 | sprintf_P(ver, PSTR("v%d.%d"), BUILDNR, REVNR); 46 | u8x8.setFont(u8x8_font_amstrad_cpc_extended_r); 47 | u8x8.draw2x2String(0, 0, "RFLink"); 48 | u8x8.draw2x2String(10, 2, "ESP"); 49 | u8x8.drawString(0, 3, ver); 50 | u8x8.drawString(0, 4, "24/09/20"); 51 | u8x8.drawString(6, 6, "github.com"); 52 | u8x8.drawString(2, 7, "/couin3/RFLink"); 53 | u8x8.setPowerSave(0); 54 | } 55 | 56 | void print_OLED() 57 | { 58 | /* 59 | static char delim[2] = ";"; 60 | static char *ptr; 61 | static boolean ret; 62 | 63 | 64 | ptr = strtok(pbuffer, delim); 65 | ret = false; 66 | 67 | while ((ptr != NULL) && (ptr[0] != '\r')) 68 | { 69 | u8x8log.print(ptr); 70 | u8x8log.print(delim); 71 | if (ret) 72 | u8x8log.print("\n"); 73 | else 74 | ret = true; 75 | ptr = strtok(NULL, delim); 76 | } 77 | */ 78 | u8x8log.print('\f'); 79 | replacechar(pbuffer, ';', '\n'); 80 | u8x8log.print(pbuffer); 81 | } 82 | 83 | #endif // OLED_ENABLED -------------------------------------------------------------------------------- /RFLink/8_OLED.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef OLED_h 9 | #define OLED_h 10 | 11 | #include 12 | #include "RFLink.h" 13 | 14 | #ifdef OLED_ENABLED 15 | 16 | #define PIN_OLED_GND NOT_A_PIN // Ground power on this pin 17 | #define PIN_OLED_VCC NOT_A_PIN // +3 volt / Vcc power on this pin# 18 | #ifdef ESP8266 19 | #define PIN_OLED_SCL D1 // I2C SCL 20 | #define PIN_OLED_SDA D2 // I2C SDA 21 | #elif ESP32 22 | #define PIN_OLED_SCL 22 // I2C SCL 23 | #define PIN_OLED_SDA 21 // I2C SDA 24 | #endif 25 | 26 | void setup_OLED(); 27 | void splash_OLED(); 28 | void print_OLED(); 29 | 30 | #endif // OLED_ENABLED 31 | #endif // OLED_h -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_014.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-014: Ikea Koppla ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of sending and receiving the Ikea Koppla protocol 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | *********************************************************************************************** 15 | * Technical information: 16 | * Packets are variable length as zero bits are 2 pulses and 1 bits are single pulses. 17 | * Pulse lengths are ~1600 for a 0 bit and two times ~750 for a 1 bit 18 | * Packets contain 28 bits 19 | * 20 | * AAAA BBBB CCCCCCCCCC DD EEEEEE FF 21 | * 1110 0011 0000000001 01 000010 01 on 22 | * 1110 0011 0000000001 01 010110 01 off 23 | * 1110 1111 1111111111 00 001110 10 Pair 24 | * 25 | * A = Preamble, Always '1110' 26 | * B = System code 0-0x0f 27 | * C = Unit code bit selection, order: ch10,1,2,3,4,5,6,7,8,9 28 | * D = Checksum on B 29 | * E = Level and Fade 30 | * F = Checksum on D 31 | * 32 | * Sample: 33 | * 20;07;DEBUG;Pulses=38;Pulses(uSec)=825,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,750,1600,775,750,1625,1600,1625,1600,775,750,1625,1600,775,750; 34 | * 20;08;DEBUG;Pulses=40;Pulses(uSec)=925,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,775,1600,775,750,1625,750,750,1625,775,750,775,750,1625,1600,750,750; 35 | \*********************************************************************************************/ 36 | #define KOPPLA_PLUGIN_ID 014 37 | #define PLUGIN_DESC_014 "Ikea Koppla" 38 | #define KOPPLA_PulseLength_MIN 36 39 | #define KOPPLA_PulseLength_MAX 52 40 | 41 | #define KOPPLA_PULSEMID 1300 / RAWSIGNAL_SAMPLE_RATE 42 | #define KOPPLA_PULSEMAX 1850 / RAWSIGNAL_SAMPLE_RATE 43 | #define KOPPLA_PULSEMIN 650 / RAWSIGNAL_SAMPLE_RATE 44 | 45 | #ifdef PLUGIN_014 46 | #include "../4_Display.h" 47 | 48 | boolean Plugin_014(byte function, char *string) 49 | { 50 | if ((RawSignal.Number < KOPPLA_PulseLength_MIN) || (RawSignal.Number > KOPPLA_PulseLength_MAX)) 51 | return false; 52 | unsigned long bitstream = 0L; 53 | 54 | // byte preamble = 0; // unused? 55 | unsigned int sysunit = 0; 56 | byte levelfade = 0; 57 | byte command = 0; 58 | byte level = 0; 59 | int i = 0; 60 | 61 | byte checksum1 = 0; 62 | byte checksum2 = 0; 63 | byte checksum = 0x03; 64 | byte tempcrc = 0; 65 | //================================================================================== 66 | // Get all 28 bits 67 | //================================================================================== 68 | for (byte x = 1; x < RawSignal.Number; x++) 69 | { 70 | bitstream <<= 1; // Always shift 71 | if (RawSignal.Pulses[x] > KOPPLA_PULSEMID) 72 | { // long pulse, 0 bit 73 | if (RawSignal.Pulses[x] > KOPPLA_PULSEMAX) 74 | return false; // long pulse is too long 75 | // bitstream |= 0x0; // 0 bit 76 | } 77 | else 78 | { // Short pulse 79 | if (RawSignal.Pulses[x] < KOPPLA_PULSEMIN) 80 | return false; // short pulse is too short 81 | if (RawSignal.Pulses[x + 1] > KOPPLA_PULSEMID) 82 | return false; // need 2 short pulses for a 1 bit 83 | if (RawSignal.Pulses[x + 1] < KOPPLA_PULSEMIN) 84 | return false; // second short pulse is too short 85 | x++; // skip second short pulse 86 | bitstream |= 0x1; // 1 bit 87 | } 88 | } 89 | //================================================================================== 90 | // Sort data and perform sanity checks 91 | //================================================================================== 92 | if (bitstream == 0) 93 | return false; // No bits detected? 94 | if ((((bitstream) >> 24) & 0x0F) != 0x0E) 95 | return false; // Preamble should always be '1110' 96 | sysunit = (((bitstream) >> 10) & 0x03FFF); // 4 bits system code and 10 bits unit code 97 | checksum1 = (((bitstream) >> 8) & 0x03); // first checksum 98 | levelfade = (((bitstream) >> 2) & 0x3F); // 6 bits level and face code 99 | checksum2 = ((bitstream)&0x03); // second checksum 100 | // calculate checksum 1 101 | checksum = 3; 102 | for (i = 0; i < 7; i++) 103 | { 104 | tempcrc = ((sysunit) >> (i * 2)) & 3; 105 | checksum = checksum ^ tempcrc; 106 | } 107 | if (checksum1 != checksum) 108 | return false; 109 | // calculate checksum 2 110 | checksum = 3; 111 | for (i = 0; i < 3; i++) 112 | { 113 | tempcrc = ((levelfade) >> (i * 2)) & 3; 114 | checksum = checksum ^ tempcrc; 115 | } 116 | if (checksum2 != checksum) 117 | return false; 118 | // sort command / dim bits 119 | if ((levelfade) == 0x2) 120 | { // on 121 | command = 1; 122 | } 123 | else if ((levelfade) == 0x16) 124 | { // off 125 | command = 0; 126 | } 127 | else if ((levelfade) == 0x0) 128 | { // up 129 | command = 2; 130 | } 131 | else if ((levelfade) == 0x4) 132 | { // down 133 | command = 3; 134 | } 135 | else 136 | { 137 | command = 4; 138 | for (i = 2; i < 6; i++) 139 | { 140 | level = level << 1; 141 | level = level | ((levelfade >> i) & 0x01); 142 | } 143 | } 144 | //================================================================================== 145 | // ---------------------------------- 146 | // Output 147 | // ---------------------------------- 148 | display_Header(); 149 | display_Name(PSTR("Ikea Koppla")); 150 | display_IDn(sysunit, 4); //"%S%04x" 151 | display_SWITCH(levelfade); // "%02x" 152 | 153 | switch (command) 154 | { 155 | case 0x00: 156 | case 0x01: 157 | case 0x04: 158 | case 0x05: 159 | display_CMD(((command >> 3) & B01), (command & B01)); // #ALL #ON 160 | break; 161 | case 0x02: 162 | display_CMD(CMD_Single, CMD_Bright); // #All #ON 163 | break; 164 | case 0x03: 165 | display_CMD(CMD_Single, CMD_Dim); // #All #ON 166 | break; 167 | default: 168 | display_SET_LEVEL(level); 169 | } 170 | display_Footer(); 171 | // ---------------------------------- 172 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 173 | RawSignal.Number = 0; 174 | return true; 175 | } 176 | #endif //PLUGIN_014 177 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_032.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-032: AlectoV4 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the protocol used for outdoor sensors of the Alecto weather stations 7 | * following protocol version 4 8 | * This Plugin works at least with: Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor sensors 9 | * But probably with many others as the OEM sensor is sold under many brand names 10 | * 11 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 12 | * Support (present) : https://github.com/couin3/RFLink 13 | * Author (original) : StuntTeam 2015..2016 14 | * Support (original) : http://sourceforge.net/projects/rflink/ 15 | * License : This code is free for use in any open source project when this header is included. 16 | * Usage of any parts of this code in a commercial application is prohibited! 17 | ********************************************************************************************* 18 | * Technische informatie: 19 | * Message Format: (9 nibbles, 36 bits): 20 | * 21 | * Format for Temperature Humidity 22 | * AAAAAAAA AAAA BCDD EEEE EEEE EEEE FFFFFFFF 23 | * 01011100 0001 1000 1111 0111 1011 00001110 24 | 01110000 0000 1111 1011 0000 0000 00000101 25 | 10110101 0000 1x00 01001001 26 | 27 | 01000101 1000 0110 1111 0000 1100 00100110 28 | 01011111 1101 1000 0000 1111 0001 00001110 29 | 01000101 1000 0010 30 | * 31 | * A = Rolling Code --- In rtl_433 the first 4 bits are type 32 | * B = 1 (fixed value) --- This is the battery level ( 1 = Ok, 0 = low battery) 33 | * C = 0=scheduled transmission, 1=requested transmission (button press) 34 | * D = Channel number (00=ch1 01=ch2 10=ch3) 35 | * E = Temperature (two's complement) 36 | * F = Humidity BCD format 37 | * 38 | * 20;3F;DEBUG;Pulses=74;Pulses(uSec)=525,1725,425,3600,425,1725,425,3600,425,3625,425,1725,425,3600,425,1725,425,1725,425,1700,425,3600,425,3600,425,3600,425,1725,425,1725,425,1725,425,1725,425,1725,400,1725,425,3600,425,1725,425,1725,425,1725,425,3600,400,1725,425,1725,425,3625,400,1725,425,1725,425,1750,400,3600,425,1725,400,1750,400,3625,425,1725,400,1725,425; 39 | * 20;C2;DEBUG;Pulses=76;Pulses(uSec)=325,500,250,1800,375,3650,375,1775,375,3650,375,3650,375,1775,375,3650,375,1800,350,1800,375,3650,375,3650,375,3650,375,3650,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,3650,375,3650,375,3650,375,1775,375,3650,375,3650,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,3650,375,3650,375,3650,375,3650,375; 40 | * 20;3E;DEBUG;Pulses=78;Pulses(uSec)=525,250,500,375,600,1650,450,3550,475,1675,450,3550,475,3550,450,1675,450,3575,450,1675,450,1700,450,1700,450,3575,425,3600,450,3575,475,1700,425,1725,425,1725,425,1725,400,1725,425,1725,425,3625,425,1725,425,1725,425,1725,425,3600,425,1725,400,1725,425,3600,425,1725,425,1725,400,1725,425,3600,400,1725,425,1725,400,3600,425,1725,425,1725,400; 41 | \*********************************************************************************************/ 42 | #define ALECTOV4_PLUGIN_ID 032 43 | #define PLUGIN_DESC_032 "Alecto V4" 44 | #define ALECTOV4_PULSECOUNT 74 45 | 46 | #define ALECTOV4_MIDHI 550 / RAWSIGNAL_SAMPLE_RATE 47 | #define ALECTOV4_PULSEMIN 1500 / RAWSIGNAL_SAMPLE_RATE 48 | #define ALECTOV4_PULSEMINMAX 2500 / RAWSIGNAL_SAMPLE_RATE 49 | #define ALECTOV4_PULSEMAXMIN 3000 / RAWSIGNAL_SAMPLE_RATE 50 | 51 | #ifdef PLUGIN_032 52 | #include "../4_Display.h" 53 | 54 | boolean Plugin_032(byte function, char *string) 55 | { 56 | if (RawSignal.Number < ALECTOV4_PULSECOUNT || RawSignal.Number > (ALECTOV4_PULSECOUNT + 4)) 57 | return false; 58 | 59 | unsigned long bitstream = 0L; 60 | int temperature = 0; 61 | byte humidity = 0; //bitstream2 ! 62 | byte rc = 0; 63 | byte rc2 = 0; 64 | byte battery = 0; 65 | //================================================================================== 66 | // Get all 36 bits 67 | //================================================================================== 68 | byte start = 0; 69 | if (RawSignal.Number == (ALECTOV4_PULSECOUNT + 4)) 70 | start = 4; 71 | if (RawSignal.Number == (ALECTOV4_PULSECOUNT + 2)) 72 | start = 2; 73 | 74 | for (byte x = 2 + start; x <= 56 + start; x += 2) 75 | { // Get first 28 bits 76 | if (RawSignal.Pulses[x + 1] > ALECTOV4_MIDHI) 77 | return false; 78 | 79 | bitstream <<= 1; // Always shift 80 | if (RawSignal.Pulses[x] > ALECTOV4_PULSEMAXMIN) 81 | bitstream |= 0x1; 82 | else 83 | { 84 | if (RawSignal.Pulses[x] < ALECTOV4_PULSEMIN) 85 | return false; 86 | if (RawSignal.Pulses[x] > ALECTOV4_PULSEMINMAX) 87 | return false; 88 | // bitstream |= 0x0; 89 | } 90 | } 91 | 92 | for (byte x = 58 + start; x <= 72 + start; x = x + 2) 93 | { // Get remaining 8 bits 94 | if (RawSignal.Pulses[x + 1] > ALECTOV4_MIDHI) 95 | return false; 96 | 97 | humidity <<= 1; // Always shift 98 | if (RawSignal.Pulses[x] > ALECTOV4_PULSEMAXMIN) 99 | humidity |= 0x1; 100 | else 101 | { 102 | if (RawSignal.Pulses[x] < ALECTOV4_PULSEMIN) 103 | return false; 104 | if (RawSignal.Pulses[x] > ALECTOV4_PULSEMINMAX) 105 | return false; 106 | // humidity |= 0x0; 107 | } 108 | } 109 | //================================================================================== 110 | // Perform a quick sanity check 111 | //================================================================================== 112 | if (bitstream == 0) 113 | return false; 114 | 115 | if (humidity == 0) 116 | return false; // Sanity check 117 | 118 | //================================================================================== 119 | // Now process the various sensor types 120 | //================================================================================== 121 | rc = (bitstream >> 20) & 0xFF; 122 | rc2 = (bitstream >> 12) & 0xF3; // Remove battery and button from ID 123 | /* 124 | if (((rc2)&0x08) != 0x08) 125 | return false; // needs to be 1 126 | */ 127 | temperature = (bitstream & 0xFFF); 128 | //fix 12 bit signed number conversion 129 | if ((temperature & 0x800) == 0x800) 130 | { 131 | temperature = 4096 - temperature; // fix for minus temperatures 132 | if (temperature > 0x258) 133 | return false; // temperature out of range ( > 60.0 degrees) 134 | temperature = temperature | 0x8000; // turn highest bit on for minus values 135 | } 136 | else 137 | { 138 | if (temperature > 0x258) 139 | return false; // temperature out of range ( > 60.0 degrees) 140 | } 141 | if (humidity > 99) 142 | return false; // Humidity out of range 143 | battery = ((bitstream >> 12) & B1000); // get battery indicator 144 | //================================================================================== 145 | // Prevent repeating signals from showing up 146 | //================================================================================== 147 | unsigned long tmpval = (((bitstream << 8) & 0xFFF0) | humidity); // All but 8 1st ID bits ... 148 | 149 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 500) < millis()) || (SignalCRC != tmpval)) 150 | SignalCRC = tmpval; // not seen this RF packet recently 151 | else 152 | return true; // already seen the RF packet recently 153 | //================================================================================== 154 | // Output 155 | //================================================================================== 156 | display_Header(); 157 | display_Name(PSTR("Alecto V4")); 158 | char c_ID[5]; 159 | sprintf(c_ID, "%02x%02x", rc, rc2); 160 | display_IDc(c_ID); 161 | display_TEMP(temperature); 162 | if (humidity < 99) // Only report valid humidty values 163 | display_HUM(humidity, HUM_HEX); 164 | display_BAT(battery); 165 | display_Footer(); 166 | //================================================================================== 167 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 168 | RawSignal.Number = 0; 169 | return true; 170 | } 171 | #endif // PLUGIN_032 172 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_033.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-033: Conrad ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding Conrad Pool Thermomether model 9771 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical information: 18 | * Decodes signals from a Conrad Model 9771 Pool Thermometer, (80 pulses, 40 bits, 433 MHz). 19 | * Message Format: 20 | * AAAAAAAA BBBBBBBB CCCCCCCCCC DD EEEE FFFF GGGG 21 | * 00000000 00010010 1100101101 01 1001 0001 1001 22 | * 23 | * A = Always 0 ? 24 | * B = Device id ? 25 | * C = Temperature digits 26 | * D = Temperature ones 27 | * E = Temperature tens 28 | * F = Always 1? 29 | * G = Unknown 30 | * 31 | * Sample: 32 | * 20;8D;DEBUG;Pulses=80;Pulses(uSec)=1890,5760,1890,5730,1890,5760,1890,5730,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,5910,1830,1890,5640,1890,5760,5910,1830,1890,5640,5910,1830,1860,5640,5910,1830,1890,5610,5910,1830,5910,1830,5910,1830,1890,5400,5910,1830,1890,5610,1890,5760,5910,1830,5910,1830,1890,5520,1890,5760,5910,1860,1890,5610,1890,5760,1890,5760,5910,1830,1890,5610,5910,1830,5910,1830,1860,6990; 33 | \*********************************************************************************************/ 34 | #define CONRAD_PLUGIN_ID 033 35 | #define PLUGIN_DESC_033 "Conrad" 36 | #define CONRAD_PULSECOUNT 80 37 | 38 | #define CONRAD_PULSEMAX 5000 / RAWSIGNAL_SAMPLE_RATE 39 | #define CONRAD_PULSEMIN 2300 / RAWSIGNAL_SAMPLE_RATE 40 | 41 | #ifdef PLUGIN_033 42 | #include "../4_Display.h" 43 | 44 | boolean Plugin_033(byte function, char *string) 45 | { 46 | if (RawSignal.Number != CONRAD_PULSECOUNT) 47 | return false; 48 | 49 | unsigned long bitstream = 0L; 50 | byte checksum = 0; 51 | byte bitcount = 0; // bit counter (counting first 8 bits that need 52 | unsigned int rc = 0; 53 | unsigned int temperature = 0; 54 | //================================================================================== 55 | // Get all 28 bits 56 | //================================================================================== 57 | for (byte x = 1; x <= CONRAD_PULSECOUNT - 1; x += 2) 58 | { 59 | if (RawSignal.Pulses[x] > CONRAD_PULSEMAX) 60 | { 61 | if (RawSignal.Pulses[x + 1] > CONRAD_PULSEMAX) 62 | if ((x + 1) < CONRAD_PULSECOUNT) 63 | return false; // invalid pulse length 64 | 65 | if (bitcount > 7) 66 | { 67 | bitstream <<= 1; 68 | bitstream |= 0x1; 69 | } 70 | else 71 | return false; // first 8 bits should all be zeros 72 | bitcount++; 73 | } 74 | else 75 | { 76 | if (RawSignal.Pulses[x] > CONRAD_PULSEMIN) 77 | return false; // invalid pulse length 78 | 79 | if (RawSignal.Pulses[x + 1] < CONRAD_PULSEMIN) 80 | return false; // invalid pulse length 81 | 82 | if (bitcount > 7) 83 | bitstream <<= 1; 84 | 85 | bitcount++; 86 | } 87 | } 88 | //================================================================================== 89 | // Perform a quick sanity check 90 | //================================================================================== 91 | if (bitstream == 0) 92 | return false; 93 | //================================================================================== 94 | // Prevent repeating signals from showing up 95 | //================================================================================== 96 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 500 < millis()) || (SignalCRC != bitstream)) 97 | SignalCRC = bitstream; // not seen the RF packet recently 98 | else 99 | return true; // already seen the RF packet recently 100 | //================================================================================== 101 | // Perform checksum calculations 102 | //================================================================================== 103 | checksum = (bitstream >> 4) & 0xF; 104 | if (checksum != 0x1) 105 | return false; 106 | //================================================================================== 107 | // Now process the various sensor types 108 | //================================================================================== 109 | rc = ((bitstream >> 24) & 0xFF); 110 | temperature = ((bitstream >> 14) & 0x3FF); 111 | temperature = temperature - 500; 112 | //================================================================================== 113 | // Output 114 | //================================================================================== 115 | display_Header(); 116 | display_Name(PSTR("Conrad")); 117 | display_IDn(rc, 4); 118 | display_TEMP(temperature); 119 | display_Footer(); 120 | //================================================================================== 121 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 122 | RawSignal.Number = 0; 123 | return true; 124 | } 125 | #endif // PLUGIN_033 126 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_035.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-035: Imagintronix ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding Imagintronix sensors 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical information: 18 | * 19 | * ~0.5ms high puls followed by ~1ms pause = high 20 | * ~1.5ms high puls followed by ~1ms pause = low 21 | * 22 | * Message Format: 23 | * 11111111 01010101 00000101 01000101 11111111 10011110 24 | * FF550545FF9E 25 | * AABCDDEEFFGG 26 | * 27 | * A = Preamble, always FF 28 | * B = TX type, always 5 29 | * C = Address (5/6/7) > low 2 bits = 1/2/3 30 | * D = Soil moisture 05% 31 | * E = temperature 32 | * F = security code, always F 33 | * G = Checksum 55+05+45+FF=19E CRC value = 9E 34 | * 35 | * Sample: 36 | * 20;02;DEBUG;Pulses=96;Pulses(uSec)=390,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1260,870,420,870,1260,870,420,870, 1230,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,1230,870,1260,870,420,870,1260,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,420,870,1260,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1230,870,1260,870,420,870,420,870,420,840,420,840,1260,6990; 37 | * 111111110101010100000101010001011111111110011110 38 | \*********************************************************************************************/ 39 | #define IMAGINTRONIX_PLUGIN_ID 035 40 | #define PLUGIN_DESC_035 "Imagintronix" 41 | 42 | #define IMAGINTRONIX_PULSECOUNT 96 43 | 44 | #define IMAGINTRONIX_PULSEMID 1000 / RAWSIGNAL_SAMPLE_RATE 45 | #define IMAGINTRONIX_PULSESHORT 550 / RAWSIGNAL_SAMPLE_RATE 46 | 47 | #ifdef PLUGIN_035 48 | #include "../4_Display.h" 49 | 50 | boolean Plugin_035(byte function, char *string) 51 | { 52 | if (RawSignal.Number != IMAGINTRONIX_PULSECOUNT) 53 | return false; 54 | unsigned int temperature = 0; 55 | unsigned int rc = 0; 56 | 57 | byte checksum = 0; 58 | byte data[8]; 59 | unsigned long bitstream = 0L; 60 | //================================================================================== 61 | byte bytecounter = 0; // used for counting the number of received bytes 62 | byte bitcounter = 0; // counts number of received bits (converted from pulses) 63 | // get bits 64 | for (byte x = 1; x < IMAGINTRONIX_PULSECOUNT; x += 2) 65 | { 66 | if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSEMID) 67 | { // long pulse = 0 bit 68 | if (x < 95) 69 | if ((RawSignal.Pulses[x + 1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x + 1] < IMAGINTRONIX_PULSESHORT)) 70 | return false; 71 | data[bytecounter] <<= 1; // 0 bit 72 | // data[bytecounter] 0x0;// 0 bit 73 | bitcounter++; // received a bit 74 | } 75 | else 76 | { // Short pulse = 1 bit 77 | if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSESHORT) 78 | return false; // Short pulse too long? 79 | if (x < 95) 80 | if ((RawSignal.Pulses[x + 1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x + 1] < IMAGINTRONIX_PULSESHORT)) 81 | return false; 82 | data[bytecounter] <<= 1; // 1 bit 83 | data[bytecounter] |= 0x1; // 1 bit 84 | bitcounter++; // received a bit 85 | } 86 | // prepare for next bit/byte 87 | if (bitcounter == 8) 88 | { // received 8 bits? 89 | bitcounter = 0; // reset for next byte 90 | bytecounter++; // byte received, increase counter 91 | if (bytecounter > 7) 92 | return false; // overflow, should not happen 93 | } 94 | } 95 | //================================================================================== 96 | // Perform a quick sanity check 97 | //================================================================================== 98 | if (data[0] != 0xFF) 99 | return false; 100 | 101 | if ((data[1] >> 4) != 0x5) 102 | return false; 103 | 104 | if (data[4] != 0xFF) 105 | return false; 106 | //================================================================================== 107 | // Perform checksum calculations 108 | //================================================================================== 109 | checksum = data[1] + data[2] + data[3] + data[4]; 110 | checksum &= 0xFF; 111 | if (checksum != data[5]) 112 | return false; 113 | //================================================================================== 114 | // Prevent repeating signals from showing up 115 | //================================================================================== 116 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 500) < millis()) || (SignalCRC != bitstream)) 117 | SignalCRC = bitstream; // not seen the RF packet recently 118 | else 119 | return true; // already seen the RF packet recently 120 | //================================================================================== 121 | rc = (data[1]) & 0x3; 122 | temperature = ((data[3]) << 4); 123 | temperature /= temperature; 124 | //================================================================================== 125 | // Output 126 | //================================================================================== 127 | display_Header(); 128 | display_Name(PSTR("Imagintronix")); 129 | display_IDn(rc, 4); 130 | display_TEMP(temperature); 131 | display_HUM(data[2], HUM_HEX); 132 | display_Footer(); 133 | //================================================================================== 134 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 135 | RawSignal.Number = 0; 136 | return true; 137 | } 138 | #endif // PLUGIN_035 139 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_037.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-037: AcuRite 986 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the protocol used for AcuRite 986 Refrigerator and Freezer sensors 7 | * This Plugin works at least with: 8 | * 9 | * Author (present) : NorthernMan54 10 | * Support (present) : https://github.com/couin3/RFLink 11 | * Author (original) : NorthernMan54 ( Borrowed heavily from rtl_433 ) 12 | * Support (original) : http://sourceforge.net/projects/rflink/ 13 | * License : This code is free for use in any open source project when this header is included. 14 | * Usage of any parts of this code in a commercial application is prohibited! 15 | ********************************************************************************************* 16 | * Technical Information: 17 | * Message Format: (10 nibbles, 40 bits): 18 | * 19 | * TT II II SS CC 20 | - T - Temperature in Fahrenheit, integer, MSB = sign. 21 | Encoding is "Sign and magnitude", LSB first 22 | - I - 16 bit sensor ID 23 | changes at each power up 24 | - S - status/sensor type 25 | 0x01 = Sensor 2 26 | 0x02 = low battery 27 | - C = CRC (CRC-8 poly 0x07, little-endian) 28 | * 29 | * Format for Temperature 30 | * TTTT TTTT IIII IIII IIII IIII SSSS SSSS CCCC CCCC 31 | * 1110 0100 0100 0111 1001 0100 0000 0001 0111 1100 32 | * 0110 0100 0100 0111 1001 0100 0000 0000 0100 1010 33 | * 0100 0000 0001 0100 1111 1001 0000 0001 0101 1110 34 | * 35 | * T - Temperature in Fahrenheit, integer, MSB = sign. Encoding is "Sign and magnitude" 36 | * I - 16 bit sensor ID, changes at each power up 37 | * S - status/sensor type, 0x01 = Sensor 2, 0x02 = low battery 38 | * 39 | * 20;XX;DEBUG;Pulses=176;Pulses(uSec)=1696,1472,1664,1280,256,416,256,448,256,512,256,832,256,512,256,832,256,416,256,512,256,864,256,800,256,512,256,832,224,512,256,832,256,512,256,832,256,512,256,864,256,896,256,832,224,448,256,512,256,832,256,448,224,480,256,448,256,448,256,448,224,448,224,480,224,480,224,480,224,512,224,832,224,512,224,896,224,832,224,480,224,480,224,544,224,224,224,224,1632,1504,1632,1504,1632,1504,1632,1344,224,480,224,480,224,544,224,832,224,544,224,864,224,480,224,544,224,896,224,864,224,544,224,864,224,544,224,864,224,544,224,864,224,544,224,928,224,928,224,864,224,480,224,544,224,864,224,480,224,480,224,480,224,480,224,480,224,480,224,480,192,480,192,480,192,544,192,864,224,544,224,928,224,864,192,480,192,480,192,480; 40 | * \*********************************************************************************************/ 41 | #define ACURITE_PLUGIN_ID 037 42 | #define PLUGIN_DESC_037 "AcuRite 986" 43 | #define ACURITE_PULSECOUNT 84 44 | 45 | #define ACURITE_MIDHI 2000 / RAWSIGNAL_SAMPLE_RATE 46 | #define ACURITE_PULSEMIN 150 / RAWSIGNAL_SAMPLE_RATE 47 | #define ACURITE_PULSEMINMAX 2500 / RAWSIGNAL_SAMPLE_RATE 48 | #define ACURITE_PULSEMAXMIN 650 / RAWSIGNAL_SAMPLE_RATE 49 | 50 | #ifdef PLUGIN_037 51 | #include "../4_Display.h" 52 | 53 | boolean Plugin_037(byte function, char *string) 54 | { 55 | if (RawSignal.Number < ACURITE_PULSECOUNT || RawSignal.Number > (ACURITE_PULSECOUNT + 4)) 56 | return false; 57 | 58 | unsigned long bitstream = 0L; 59 | byte bitstream2 = 0; 60 | byte data[4]; 61 | int temperature = 0; 62 | unsigned long rc = 0; 63 | byte rc2 = 0; 64 | byte battery = 0; 65 | byte status = 0; 66 | byte crcc; 67 | //================================================================================== 68 | // Get all 36 bits 69 | //================================================================================== 70 | // Serial.print("Bitstream: "); 71 | for (byte x = 0; x < 64; x += 2) 72 | { 73 | if (RawSignal.Pulses[x + 1] > ACURITE_MIDHI) 74 | return false; // in between pulses should be short 75 | bitstream <<= 1; 76 | if (RawSignal.Pulses[x + 1] > ACURITE_PULSEMAXMIN) 77 | { 78 | bitstream |= 0x1; 79 | // Serial.print("1"); 80 | } 81 | else 82 | { 83 | // Serial.print("0"); 84 | } 85 | } 86 | // Serial.print(" "); 87 | for (byte x = 64; x < 80; x = x + 2) 88 | { 89 | bitstream2 <<= 1; 90 | 91 | if (RawSignal.Pulses[x + 1] > ACURITE_PULSEMAXMIN) 92 | { 93 | bitstream2 |= 0x1; 94 | // Serial.print("1"); 95 | } 96 | else 97 | { 98 | // Serial.print("0"); 99 | } 100 | } 101 | // char dataPrint[9]; 102 | //sprintf(dataPrint, "%04lx %01x", bitstream, bitstream2); 103 | //Serial.println(""); 104 | //Serial.print("Datastream: "); 105 | //Serial.println(dataPrint); 106 | //================================================================================== 107 | // Perform a quick sanity check 108 | //================================================================================== 109 | if (bitstream == 0) 110 | return false; 111 | //================================================================================== 112 | // Prepare nibbles from bit stream 113 | //================================================================================== 114 | data[3] = reverse8(bitstream & 0xFF); // 0x78 115 | data[2] = reverse8((bitstream >> 8) & 0xFF); // 0x56 116 | data[1] = reverse8((bitstream >> 16) & 0xFF); // 0x34 117 | data[0] = reverse8((bitstream >> 24) & 0xFF); // 0x12 118 | 119 | // Serial.print("bitstream: "); 120 | // Serial.println(bitstream); 121 | // Serial.print("bitstream2: "); 122 | // Serial.println(bitstream2); 123 | //================================================================================== 124 | // CRC Check 125 | //================================================================================== 126 | crcc = crc8le(data, 4, 0x07, 0); 127 | if (crcc != reverse8(bitstream2)) 128 | { 129 | //Serial.println("ERROR: crc failed."); 130 | //Serial.print("crcc le: "); 131 | //Serial.println(crcc); 132 | //Serial.print("crc: "); 133 | //Serial.println(reverse8(bitstream2)); 134 | return false; 135 | } 136 | //================================================================================== 137 | // Now process the various sensor types 138 | //================================================================================== 139 | if (data[0] & 0x80) 140 | { 141 | temperature = (data[0] & 0x7f) * -1; 142 | } 143 | else 144 | { 145 | temperature = data[0]; 146 | } 147 | temperature = ((temperature - 32) * 5 / 9 * 10); // ACURITE sensors are in Farenheit 148 | // Serial.print("temperature: "); 149 | // Serial.println(temperature); 150 | if ( temperature < 0 ) 151 | { 152 | temperature = (temperature * -1 ) | 0x8000; 153 | } 154 | 155 | rc = (data[1] << 8) + data[2]; 156 | status = data[3]; 157 | rc2 = (status & 0x01) + 1; 158 | status = status >> 1; 159 | battery = ((status & 1) == 0); 160 | // Serial.print("id: "); 161 | // Serial.println(rc); 162 | // Serial.print("unit: "); 163 | // Serial.println(rc2); 164 | // Serial.print("battery: "); 165 | // Serial.println(battery); 166 | // Serial.print("data[3]: "); 167 | // Serial.println(data[3]); 168 | //================================================================================== 169 | // Prevent repeating signals from showing up 170 | //================================================================================== 171 | unsigned long tmpval = (((bitstream << 8) & 0xFFF0)); // All but 8 1st ID bits ... 172 | 173 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 500) < millis()) || (SignalCRC != tmpval)) 174 | SignalCRC = tmpval; // not seen this RF packet recently 175 | else 176 | return true; // already seen the RF packet recently 177 | //================================================================================== 178 | // Output 179 | //================================================================================== 180 | display_Header(); 181 | display_Name(PSTR("AcuRite 986")); 182 | char c_ID[5]; 183 | sprintf(c_ID, "%02x%02x", (rc & 0xFF), rc2); 184 | display_IDc(c_ID); 185 | display_TEMP(temperature); 186 | display_BAT(battery); 187 | display_Footer(); 188 | //================================================================================== 189 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 190 | RawSignal.Number = 0; 191 | return true; 192 | } 193 | #endif // PLUGIN_037 194 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_040.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-040: Mebus ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding Mebus weatherstation outdoor sensors 7 | * It concerns Mebus sensors that are not following the Cresta (Hideki) protocol 8 | * Also sold as Stacja Pogody WS-9941-M 9 | * 10 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 11 | * Support (present) : https://github.com/couin3/RFLink 12 | * Author (original) : StuntTeam 2015..2016 13 | * Support (original) : http://sourceforge.net/projects/rflink/ 14 | * License : This code is free for use in any open source project when this header is included. 15 | * Usage of any parts of this code in a commercial application is prohibited! 16 | ********************************************************************************************* 17 | * Changelog: v1.0 initial release 18 | ********************************************************************************************* 19 | * Technical information: 20 | * Decodes signals from a Mebus Weatherstation outdoor unit, (58 pulses, 28 bits, 433 MHz). 21 | * Mebus Message Format: 22 | * AAAA BBBB BBBB CCCC CCCC CCCC DDEF 23 | * 24 | * A = Checksum value AAAA=((BBBB+BBBB+CCCC+CCCC+DDEF)-1)&0x0f 25 | * B = Changes after each reset, no change during normal operation. (Device 'Session' ID) 26 | * C = Temperature (21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 27 | * D = Channel number 1/2/3 28 | * E = Always 1 29 | * F = 0 when "normal" data transmit, 1 when "requested" data transmit (TX button press) 30 | * 31 | * 20;DE;DEBUG;Pulses=58;Pulses(uSec)=525,1800,350,1800,350,4275,350,1800,350,4275,350,4275,350,4275,350,1800,350,4250,350,4275,350,1800,350,4250,350,1800,350,1800,350,1800,350,1800,350,4275,350,4275,350,4250,350,1800,350,1800,350,1800,350,4275,350,4250,350,1800,350,4275,350,4275,350,4250,350; 32 | * 20;80;DEBUG;Pulses=58;Pulses(uSec)=450,4450,375,4450,375,4450,375,4450,375,1875,375,4450,375,4450,375,1875,375,1875,375,4425,375,4425,375,4425,375,1875,375,1875,375,1875,375,4425,375,1875,375,1875,375,1875,375,1875,375,4450,375,4450,375,1875,375,1875,375,1875,375,4450,375,4425,375,1875,375; 33 | * 20;81;Mebus;ID=6701;TEMP=010c; 34 | \*********************************************************************************************/ 35 | // ================================================================================== 36 | // MEBUS bit packets 37 | // 0000 1101 1001 0000 1100 1000 0111 38 | // 0100 1101 1001 0000 1101 1100 0110 39 | // 0100 1101 1001 0000 1100 1101 0110 40 | // 1001 1101 1001 0000 1101 1100 1011 41 | // 1011 1101 1001 0001 0000 1111 0110 27.1 42 | // 0010 0110 1110 0000 0000 1001 0110 0.9 43 | // 0011 0110 1110 1111 1000 0011 0110 -12.5 (1111 1000 0011=3971, 4096-3971=125 44 | // |----------|----------> temperature 0 - 51.1 45 | // |-|---------------------> set when minus temperatures -51.2 - 0 46 | // ================================================================================== 47 | #define MEBUS_PLUGIN_ID 040 48 | #define PLUGIN_DESC_040 "Mebus" 49 | #define MEBUS_PULSECOUNT 58 50 | 51 | #define MEBUS_MIDHI 550 / RAWSIGNAL_SAMPLE_RATE 52 | #define MEBUS_PULSEMIN 1500 / RAWSIGNAL_SAMPLE_RATE 53 | #define MEBUS_PULSEMINMAX 2100 / RAWSIGNAL_SAMPLE_RATE 54 | #define MEBUS_PULSEMAXMIN 3400 / RAWSIGNAL_SAMPLE_RATE 55 | 56 | #ifdef PLUGIN_040 57 | #include "../4_Display.h" 58 | 59 | boolean Plugin_040(byte function, char *string) 60 | { 61 | if (RawSignal.Number != MEBUS_PULSECOUNT) 62 | return false; 63 | 64 | unsigned long bitstream = 0L; 65 | unsigned int temperature = 0; 66 | byte data[7]; 67 | byte checksum = 0; 68 | byte rc = 0; 69 | byte channel = 0; 70 | //================================================================================== 71 | // Get all 28 bits 72 | //================================================================================== 73 | for (byte x = 2; x <= MEBUS_PULSECOUNT - 2; x += 2) 74 | { 75 | if (RawSignal.Pulses[x + 1] > MEBUS_MIDHI) 76 | return false; // make sure inbetween pulses are not too long 77 | 78 | bitstream <<= 1; // Always shift 79 | if (RawSignal.Pulses[x] > MEBUS_PULSEMAXMIN) 80 | bitstream |= 0x1; 81 | else 82 | { 83 | if (RawSignal.Pulses[x] > MEBUS_PULSEMINMAX) 84 | return false; // invalid pulse length 85 | if (RawSignal.Pulses[x] < MEBUS_PULSEMIN) 86 | return false; // invalid pulse length 87 | 88 | // bitstream |= 0x0; 89 | } 90 | } 91 | //================================================================================== 92 | // Perform a quick sanity check 93 | //================================================================================== 94 | if (bitstream == 0) 95 | return false; 96 | //================================================================================== 97 | // Prevent repeating signals from showing up 98 | //================================================================================== 99 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 150 < millis() && SignalCRC != bitstream) || (SignalCRC != bitstream)) 100 | SignalCRC = bitstream; // not seen the RF packet recently 101 | else 102 | return true; // already seen the RF packet recently 103 | //================================================================================== 104 | // Prepare nibbles from bit stream 105 | //================================================================================== 106 | for (byte i = 0; i < 7; i++) 107 | { 108 | data[i] = ((bitstream >> (24 - (4 * i))) & 0xF); 109 | if (i > 0) 110 | checksum += data[i]; 111 | } 112 | //================================================================================== 113 | // Perform checksum calculations 114 | //================================================================================== 115 | checksum = (checksum - 1) & 0xF; 116 | if (checksum != data[0]) 117 | return false; 118 | //================================================================================== 119 | // Now process the various sensor types 120 | //================================================================================== 121 | rc = (data[1] << 4) | data[2]; 122 | channel = (data[6]) >> 2; 123 | temperature = (data[3] << 8) | (data[4] << 4) | data[5]; 124 | if (temperature > 3000) 125 | { 126 | temperature = 4096 - temperature; // fix for minus temperatures 127 | if (temperature > 0x258) 128 | return false; // temperature out of range ( > -60.0 degrees) 129 | temperature = temperature | 0x8000; // turn highest bit on for minus values 130 | } 131 | else 132 | { 133 | if (temperature > 0x258) 134 | return false; // temperature out of range ( > 60.0 degrees) 135 | } 136 | //================================================================================== 137 | // Output 138 | //================================================================================== 139 | display_Header(); 140 | display_Name(PSTR("Mebus")); 141 | char c_ID[5]; 142 | sprintf(c_ID, "%02x%02x", rc, channel); 143 | display_IDc(c_ID); 144 | display_TEMP(temperature); 145 | display_Footer(); 146 | //================================================================================== 147 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 148 | RawSignal.Number = 0; 149 | return true; 150 | } 151 | #endif // PLUGIN_040 152 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_044.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-044: Auriol V3 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol for sensor type Z32171A 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical Information: 18 | * Decodes signals from a Auriol Weatherstation outdoor unit, (40 bits, 433 MHz). 19 | * 20 | * Auriol Message Format: 21 | * 1011 1111 1001 1010 0110 0001 1011 0100 1001 0001 22 | * B F 9 A 6 1 B 4 9 1 23 | * AAAA AAAA BBBB CCDD EEEE EEEE EEEE FFFF FFFF GGHH 24 | * 25 | * A = ID? 26 | * B = Rolling code? 27 | * C = possibly battery indicator ? 28 | * D = trend (2 bits) indicating temp equal/up/down ? 29 | * E = Temperature => 0x61b (0x61b-0x4c4)=0x157 *5)=0x6b3 /9)=0xBE => 0xBE = 190 decimal! 30 | * F = humidity: 49% 31 | * G = ? 32 | * H = channel: 1 (2 bits) 33 | * 34 | * Sample: 35 | * 20;C2;DEBUG;Pulses=82;Pulses(uSec)=475,3850,450,1700,450,3825,450,3900,450,3725,450,3825,450,3825,450,3900,450,3725,450,1700,450,1700,450,3900,450,3725,450,1700,450,1700,450,1800,450,1625,450,3800,450,3825,450,1800,450,1625,450,1700,450,1700,450,1800,450,3725,450,3800,450,1700,450,1800,450,1625,450,3825,450,1700,450,3900,450,1625,450,1700,450,1700,450,3900,450,1625,450,1700,450,1700,450,3825,500; 36 | \*********************************************************************************************/ 37 | #define AURIOLV3_PLUGIN_ID 044 38 | #define PLUGIN_DESC_044 "Auriol V3" 39 | #define AURIOLV3_PULSECOUNT 82 40 | 41 | #define AURIOLV3_MIDHI 650 / RAWSIGNAL_SAMPLE_RATE 42 | 43 | #define AURIOLV3_PULSEMIN 1500 / RAWSIGNAL_SAMPLE_RATE 44 | #define AURIOLV3_PULSEMINMAX 2000 / RAWSIGNAL_SAMPLE_RATE 45 | #define AURIOLV3_PULSEMAXMIN 3500 / RAWSIGNAL_SAMPLE_RATE 46 | 47 | #ifdef PLUGIN_044 48 | #include "../4_Display.h" 49 | 50 | boolean Plugin_044(byte function, char *string) 51 | { 52 | if (RawSignal.Number != AURIOLV3_PULSECOUNT) 53 | return false; 54 | 55 | unsigned long bitstream1 = 0L; // holds first 4x4=16 bits 56 | unsigned long bitstream2 = 0L; // holds last 6x4=24 bits 57 | byte bitcounter = 0; // counts number of received bits (converted from pulses) 58 | byte rc = 0; 59 | byte channel = 0; 60 | unsigned long temperature = 0; 61 | byte humidity = 0; 62 | //================================================================================== 63 | // Get all 40 bits 64 | //================================================================================== 65 | for (byte x = 2; x < AURIOLV3_PULSECOUNT; x += 2) 66 | { 67 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply > AURIOLV3_MIDHI) 68 | return false; 69 | if (RawSignal.Pulses[x] > AURIOLV3_PULSEMAXMIN) 70 | { 71 | if (bitcounter < 16) 72 | { 73 | bitstream1 <<= 1; 74 | bitstream1 |= 0x1; 75 | bitcounter++; // only need to count the first 10 bits 76 | } 77 | else 78 | { 79 | bitstream2 <<= 1; 80 | bitstream2 |= 0x1; 81 | } 82 | } 83 | else 84 | { 85 | if (RawSignal.Pulses[x] > AURIOLV3_PULSEMINMAX) 86 | return false; 87 | if (RawSignal.Pulses[x] < AURIOLV3_PULSEMIN) 88 | return false; 89 | if (bitcounter < 16) 90 | { 91 | bitstream1 <<= 1; 92 | bitcounter++; // only need to count the first 10 bits 93 | } 94 | else 95 | bitstream2 <<= 1; 96 | } 97 | } 98 | //================================================================================== 99 | // Perform sanity checks and prevent repeating signals from showing up 100 | //================================================================================== 101 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer < millis())) 102 | { 103 | if (bitstream1 == 0) 104 | return false; // not seen the RF packet recently 105 | if (bitstream2 == 0) 106 | return false; 107 | } 108 | else 109 | { 110 | return true; // already seen the RF packet recently 111 | } 112 | //================================================================================== 113 | // now process sensor type 114 | //================================================================================== 115 | rc = (bitstream1 >> 8) & 0xFF; // get rolling code 116 | temperature = ((bitstream2) >> 12) & 0xFFF; // get 12 temperature bits 117 | temperature = (temperature - 0x4c4) & 0xFFFF; 118 | temperature = (((temperature)*5) / 9) & 0xFFFF; 119 | if (temperature > 3000) 120 | { 121 | temperature = 4096 - temperature; // fix for minus temperatures 122 | if (temperature > 0x258) 123 | return false; // temperature out of range ( > -60.0 degrees) 124 | temperature = temperature | 0x8000; // turn highest bit on for minus values 125 | } 126 | else 127 | { 128 | if (temperature > 0x258) 129 | return false; // temperature out of range ( > 60.0 degrees) 130 | } 131 | humidity = (bitstream2 >> 4) & 0xff; // humidity 132 | channel = (bitstream2)&0x03; // channel number 133 | //================================================================================== 134 | // Output 135 | //================================================================================== 136 | display_Header(); 137 | display_Name(PSTR("Auriol V3")); 138 | char c_ID[5]; 139 | sprintf(c_ID, "%02X%02X", rc, channel); 140 | display_IDc(c_ID); 141 | display_TEMP(temperature); 142 | display_HUM(humidity, HUM_HEX); 143 | display_Footer(); 144 | //================================================================================== 145 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 146 | RawSignal.Number = 0; 147 | return true; 148 | } 149 | #endif // PLUGIN_044 150 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_045.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-045: Auriol ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol (Z31743) and other devices following the same protocol (Rubicson?) 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical Information: 18 | * Decodes signals from a Auriol Weatherstation outdoor unit, (32/36 bits, 433 MHz). 19 | * Auriol Message Format: 20 | * 1101 0110 1000 0000 1101 1111 1111 0000 21 | * AAAA AAAA BCCC DDDD DDDD DDDD EEEE FFFG 22 | * 23 | * A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number) 24 | * B = Battery status, 1=OK, 0=LOW 25 | * C = Always 000 26 | * D = Temperature (21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 27 | * E = Unknown 28 | * F = Unknown 29 | * G = sum of all bits xored together 30 | * 31 | * Sample: 32 | * 20;34;DEBUG;Pulses=66;Pulses(uSec)=325,3725,325,1825,325,1825,325,1825,325,3700,325,3700,325,3700,325,3700,325,3700,325,1850,300,1825,325,1850,325,1825,325,1850,325,1825,300,1825,325,3725,300,3725,325,1825,325,1825,300,3725,300,1850,325,3725,300,1850,325,3725,300,3700,300,3725,300,1825,325,3700,325,3700,300,3700,325,1825,325; 33 | * 20;0A;DEBUG;Pulses=66;Pulses(uSec)=325,1850,300,1850,300,3700,300,1850,300,1850,300,1850,325,1850,300,1850,325,3700,325,1850,300,1850,300,1825,325,1850,300,1850,325,1825,300,1850,325,3725,300,3700,325,1825,300,1850,325,3700,300,3725,300,3725,300,1850,300,1850,300,3725,325,3700,300,1850,300,1825,325,1850,300,3700,300,1850,325; 34 | \*********************************************************************************************/ 35 | #define AURIOL_PLUGIN_ID 045 36 | #define PLUGIN_DESC_045 "Auriol" 37 | #define AURIOL_PULSECOUNT 66 38 | 39 | #define AURIOL_MIDHI 550 / RAWSIGNAL_SAMPLE_RATE 40 | 41 | #define AURIOL_PULSEMIN 1600 / RAWSIGNAL_SAMPLE_RATE 42 | #define AURIOL_PULSEMINMAX 2200 / RAWSIGNAL_SAMPLE_RATE 43 | #define AURIOL_PULSEMAXMIN 3000 / RAWSIGNAL_SAMPLE_RATE 44 | 45 | #ifdef PLUGIN_045 46 | #include "../4_Display.h" 47 | 48 | boolean Plugin_045(byte function, char *string) 49 | { 50 | if (RawSignal.Number != AURIOL_PULSECOUNT) 51 | return false; 52 | 53 | unsigned long bitstream = 0L; // holds 8x4=32 bits 54 | byte checksumcalc = 0; 55 | byte rc = 0; 56 | byte bat = 0; 57 | unsigned int temperature = 0; 58 | //================================================================================== 59 | // Get all 32 bits 60 | //================================================================================== 61 | for (byte x = 2; x < AURIOL_PULSECOUNT; x += 2) 62 | { 63 | if (RawSignal.Pulses[x + 1] > AURIOL_MIDHI) 64 | return false; // in between pulses should not exceed a length of 550 65 | 66 | bitstream <<= 1; // Always shift 67 | 68 | if (RawSignal.Pulses[x] > AURIOL_PULSEMAXMIN) 69 | bitstream |= 0x1; // long bit = 1 70 | else 71 | { 72 | if (RawSignal.Pulses[x] < AURIOL_PULSEMIN) 73 | return false; // pulse length too short to be valid? 74 | if (RawSignal.Pulses[x] > AURIOL_PULSEMINMAX) 75 | return false; // pulse length between 2000 - 3000 is invalid 76 | 77 | // bitstream |= 0x0; // short bit = 0 78 | } 79 | } 80 | //================================================================================== 81 | // Perform a quick sanity check 82 | //================================================================================== 83 | if (bitstream == 0) 84 | return false; 85 | //================================================================================== 86 | // Prevent repeating signals from showing up 87 | //================================================================================== 88 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 500 < millis()) || (SignalCRC != bitstream)) 89 | SignalCRC = bitstream; // not seen the RF packet recently 90 | else 91 | return true; // already seen the RF packet recently 92 | //================================================================================== 93 | // Perform checksum calculations 94 | //================================================================================== 95 | for (byte i = 1; i < 32; i++) 96 | { // Perform a checksum calculation to make sure the received packet is a valid Auriol packet 97 | checksumcalc ^= ((bitstream >> i) & 0x01); 98 | } 99 | if (checksumcalc != (bitstream & 0x01)) 100 | return false; 101 | rc = (bitstream >> 20) & 0x07; // get 3 bits to perform another sanity check 102 | if (rc != 0) 103 | return false; // selected bits should always be 000 104 | //================================================================================== 105 | // now process sensor type 106 | //================================================================================== 107 | bat = (bitstream >> 23) & 0x01; // get battery strength indicator 108 | temperature = (bitstream >> 8) & 0xfff; // get 12 temperature bits 109 | rc = (bitstream >> 24) & 0xff; // get rolling code 110 | if (temperature > 3000) 111 | { 112 | temperature = 4096 - temperature; // fix for minus temperatures 113 | if (temperature > 0x258) 114 | return false; // temperature out of range ( > -60.0 degrees) 115 | temperature = temperature | 0x8000; // turn highest bit on for minus values 116 | } 117 | else 118 | { 119 | if (temperature > 0x258) 120 | return false; // temperature out of range ( > 60.0 degrees) 121 | } 122 | //================================================================================== 123 | // Output 124 | //================================================================================== 125 | display_Header(); 126 | display_Name(PSTR("Auriol")); 127 | char c_ID[5]; 128 | sprintf(c_ID, "%02X", rc); 129 | display_IDc(c_ID); 130 | display_TEMP(temperature); 131 | display_BAT(bat); 132 | display_Footer(); 133 | //================================================================================== 134 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 135 | RawSignal.Number = 0; 136 | return true; 137 | } 138 | #endif // PLUGIN_045 139 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_047.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-047: Auriol v4 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol for sensor type Auriol HG02832 7 | * 8 | * Author (original) : StormTeam 2020 - Marc RIVES (aka Couin3) 9 | * Support (original) : https://github.com/couin3/RFLink 10 | 11 | * License : This code is free for use in any open source project when this header is included. 12 | * Usage of any parts of this code in a commercial application is prohibited! 13 | ********************************************************************************************* 14 | * Changelog: v1.0 initial release 15 | ********************************************************************************************* 16 | * Technical Information: 17 | * Decodes signals from a Auriol outdoor unit, (4 sync + 40 bits, 433 MHz). 18 | * 19 | * Auriol Message Format: 20 | * 00111010 00111010 0000 000011110000 10101111 21 | * AAAAAAAA BBBBBBBB CCDD EEEEEEEEEEEE FFFFFFFF 22 | * ID Hum B.Ch Temp CRC 23 | * 24 | * A = Rolling Code, 25 | * B = Humidity 26 | * C = Battery status indicator on highest bit, 1=OK 0=LOW 27 | * D = Channel 28 | * E = Temperature (12 bit, 21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 29 | * F = CRC 30 | * 31 | * 32 | * Sample: 33 | * 20;1F;DEBUG;Pulses=88;Pulses(uSec)=384,768,896,768,896,768,896,768,288,544,288,544,640,192,640,192,640,192,288,544,640,192,288,544,288,544,288,544,640,192,640,192,640,192,288,544,640,192,288,544,288,544,288,544,288,544,288,544,288,544,288,544,288,544,288,544,640,192,640,192,640,192,640,192,288,544,288,544,288,544,288,544,640,192,288,544,640,192,288,544,640,192,640,192,640,192,640,1952 34 | \*********************************************************************************************/ 35 | #define AURIOLV4_PLUGIN_ID 047 36 | #define PLUGIN_DESC_047 "Auriol V4" 37 | #define AURIOLV4_PULSECOUNT 88 38 | 39 | #define AURIOLV4_MIDLO 128 / RAWSIGNAL_SAMPLE_RATE 40 | #define AURIOLV4_MIDHI 672 / RAWSIGNAL_SAMPLE_RATE 41 | 42 | #define AURIOLV4_PULSEMIN 224 / RAWSIGNAL_SAMPLE_RATE 43 | #define AURIOLV4_PULSEMINMAX 352 / RAWSIGNAL_SAMPLE_RATE 44 | #define AURIOLV4_PULSEMAXMIN 576 / RAWSIGNAL_SAMPLE_RATE 45 | #define AURIOLV4_PULSEMAX 768 / RAWSIGNAL_SAMPLE_RATE 46 | 47 | #ifdef PLUGIN_047 48 | #include "../4_Display.h" 49 | #include "../7_Utils.h" 50 | 51 | boolean Plugin_047(byte function, char *string) 52 | { 53 | if ((RawSignal.Number < AURIOLV4_PULSECOUNT - 4) || (RawSignal.Number > AURIOLV4_PULSECOUNT + 2)) 54 | return false; 55 | 56 | unsigned long bitstream = 0L; // holds first 8x4=32 bits 57 | uint8_t checksum = 0; // holds last 2x4=8 bits 58 | byte bitcounter = 0; // counts number of received bits (converted from pulses) 59 | uint8_t checksumcalc = 0; 60 | byte rc = 0; 61 | byte bat = 0; 62 | byte bat0 = 0; 63 | int temperature = 0; 64 | byte humidity = 0; 65 | byte channel = 0; 66 | //================================================================================== 67 | // Get all 40 bits 68 | //================================================================================== 69 | for (byte x = 1; x < RawSignal.Number; x += 2) 70 | { 71 | if ((RawSignal.Pulses[x + 1] < AURIOLV4_MIDLO) || (RawSignal.Pulses[x + 1] > AURIOLV4_MIDHI)) 72 | { 73 | if (bitcounter == 0) // Possible (4) Sync bits 74 | continue; 75 | 76 | if (bitcounter != 39) // in between pulse check 77 | return false; 78 | } 79 | 80 | if (RawSignal.Pulses[x] > AURIOLV4_PULSEMAXMIN) 81 | { 82 | if (RawSignal.Pulses[x] > AURIOLV4_PULSEMAX) 83 | return false; 84 | 85 | if (bitcounter < 32) 86 | { 87 | bitstream <<= 1; 88 | bitstream |= 0x1; 89 | } 90 | else 91 | { 92 | checksum <<= 1; 93 | checksum |= 0x1; 94 | } 95 | } 96 | else 97 | { 98 | if (RawSignal.Pulses[x] < AURIOLV4_PULSEMIN) 99 | return false; 100 | 101 | if (RawSignal.Pulses[x] > AURIOLV4_PULSEMINMAX) 102 | return false; 103 | 104 | if (bitcounter < 32) 105 | bitstream <<= 1; 106 | else 107 | checksum <<= 1; 108 | } 109 | bitcounter++; // only need to count the first 40 bits 110 | if (bitcounter > 39) 111 | break; 112 | } 113 | //================================================================================== 114 | // Perform a quick sanity check 115 | //================================================================================== 116 | if (bitcounter != 40) 117 | return false; 118 | if (bitstream == 0) 119 | return false; 120 | //================================================================================== 121 | // Prevent repeating signals from showing up 122 | //================================================================================== 123 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 500 < millis()) || (SignalCRC != bitstream)) 124 | SignalCRC = bitstream; // not seen the RF packet recently 125 | else 126 | return true; // already seen the RF packet recently 127 | //================================================================================== 128 | // Perform checksum calculations 129 | //================================================================================== 130 | // Source : https://github.com/merbanan/rtl_433/blob/master/src/devices/auriol_hg02832.c 131 | // 132 | // They tried to implement CRC-8 poly 0x31, but (accidentally?) reset the key every new byte. 133 | // (equivalent key stream is 7a 3d 86 43 b9 c4 62 31 repeated 4 times.) 134 | // 135 | for (byte c = 0; c < 4; c++) 136 | checksumcalc ^= ((bitstream >> (8 * c)) & 0xFF); 137 | 138 | if (checksum != crc8(&checksumcalc, 1, 0x31, 0x53)) 139 | return false; 140 | //================================================================================== 141 | // now process the various sensor types 142 | //================================================================================== 143 | rc = (bitstream >> 24) & 0xFF; // get rolling code 144 | bat = !((bitstream >> 15) & 0x1); // get battery strength indicator 145 | bat0 = (bitstream >> 14) & 0x1; // get blank battery strength indicator 146 | if (bat0 != 0) 147 | return false; // blank bat must be 0 148 | 149 | channel = ((bitstream >> 12) & 0x3) + 1; // channel indicator 150 | 151 | temperature = (bitstream & 0xFFF); // get 12 temperature bits 152 | if (temperature > 3000) 153 | { 154 | temperature = 4096 - temperature; // fix for minus temperatures 155 | if (temperature > 0x258) 156 | return false; // temperature out of range ( > -60.0 degrees) 157 | temperature = temperature | 0x8000; // turn highest bit on for minus values 158 | } 159 | else 160 | { 161 | if (temperature > 0x258) 162 | return false; // temperature out of range ( > 60.0 degrees) 163 | } 164 | 165 | humidity = (bitstream >> 16) & 0xFF; 166 | if (humidity > 100) 167 | return false; // humidity out of range ( > 100) 168 | //================================================================================== 169 | // Output 170 | //================================================================================== 171 | display_Header(); 172 | display_Name(PSTR("Auriol V4")); 173 | char c_ID[5]; 174 | sprintf(c_ID, "%02X%02X", rc, channel); 175 | display_IDc(c_ID); 176 | display_TEMP(temperature); 177 | display_HUM(humidity, HUM_HEX); 178 | display_BAT(bat); 179 | display_Footer(); 180 | //================================================================================== 181 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 182 | RawSignal.Number = 0; 183 | return true; 184 | } 185 | #endif // PLUGIN_047 186 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_060.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-060: AlarmSensor ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This protocol provides support for some Alarm sensors that are part of a Varel/Chubb/Ajax alarm 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical data: 18 | * Devices send 25 pulses, first pulse is part of the start bit. Remaining bits are Manchester encoded, 24 bits 19 | * 20 | * The PCB contains a Holtec HT12E Encoder chip 21 | * The PCB has two switch blocks: SW1 with switches 1-8 (Device code?) 22 | * SW2 with switches 1-4 (House code?) 23 | * 24 | * Sample: 25 | * 20;74;DEBUG;Pulses=26;Pulses(uSec)=425,425,800,875,350,875,350,875,350,875,350,875,350,875,350,875,350,400,800,875,350,400,825,875,350; 26 | * 1001101010101010 01100110 27 | * 10000000 1010 28 | \*********************************************************************************************/ 29 | #define ALARMPIRV0_PLUGIN_ID 060 30 | #define PLUGIN_DESC_060 "X10" 31 | 32 | #define ALARMPIRV0_PULSECOUNT 26 33 | 34 | #define ALARMPIRV0_PULSEMID 700 / RAWSIGNAL_SAMPLE_RATE 35 | #define ALARMPIRV0_PULSEMAX 1000 / RAWSIGNAL_SAMPLE_RATE 36 | #define ALARMPIRV0_PULSESHORT 550 / RAWSIGNAL_SAMPLE_RATE 37 | #define ALARMPIRV0_PULSEMIN 250 / RAWSIGNAL_SAMPLE_RATE 38 | 39 | #ifdef PLUGIN_060 40 | #include "../4_Display.h" 41 | 42 | boolean Plugin_060(byte function, char *string) 43 | { 44 | if (RawSignal.Number != ALARMPIRV0_PULSECOUNT) 45 | return false; 46 | 47 | unsigned long bitstream = 0L; 48 | //================================================================================== 49 | // Perform a pre sanity check 50 | //================================================================================== 51 | if (RawSignal.Pulses[1] > ALARMPIRV0_PULSESHORT) 52 | return false; // First pulse is start bit and should be short! 53 | //================================================================================== 54 | // Get all 12 bits 55 | //================================================================================== 56 | for (byte x = 2; x < ALARMPIRV0_PULSECOUNT; x += 2) 57 | { 58 | if (RawSignal.Pulses[x] > ALARMPIRV0_PULSEMID) 59 | { // long pulse 800-875 (700-1000 accepted) 60 | if (RawSignal.Pulses[x] > ALARMPIRV0_PULSEMAX) 61 | return false; // pulse too long 62 | if (RawSignal.Pulses[x + 1] > ALARMPIRV0_PULSEMID) 63 | return false; // invalid manchester code 64 | bitstream = bitstream << 1; 65 | } 66 | else 67 | { // short pulse 350-425 (250-550 accepted) 68 | if (RawSignal.Pulses[x] < ALARMPIRV0_PULSEMIN) 69 | return false; // pulse too short 70 | if (RawSignal.Pulses[x + 1] < ALARMPIRV0_PULSEMID) 71 | return false; // invalid manchester code 72 | bitstream = (bitstream << 1) | 0x1; 73 | } 74 | } 75 | //================================================================================== 76 | // Prevent repeating signals from showing up 77 | //================================================================================== 78 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 2000 < millis())) 79 | { 80 | // not seen the RF packet recently 81 | if (bitstream == 0) 82 | return false; 83 | } 84 | else 85 | { 86 | // already seen the RF packet recently 87 | return true; 88 | } 89 | //================================================================================== 90 | // Output 91 | // ---------------------------------- 92 | display_Header(); 93 | display_Name(PSTR("X10")); 94 | display_IDn((bitstream & 0xFFFF), 4); // "%S%04x" 95 | display_SWITCH(1); 96 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 97 | display_Footer(); 98 | //================================================================================== 99 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 100 | RawSignal.Number = 0; 101 | return true; 102 | } 103 | #endif // PLUGIN_060 104 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_061.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-061: AlarmSensor ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This protocol provides support for some chinese Alarm "gadgets" (Motion detectors and door/window contacts) 7 | * Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly 8 | * 9 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 10 | * Support (present) : https://github.com/couin3/RFLink 11 | * Author (original) : StuntTeam 2015..2016 12 | * Support (original) : http://sourceforge.net/projects/rflink/ 13 | * License : This code is free for use in any open source project when this header is included. 14 | * Usage of any parts of this code in a commercial application is prohibited! 15 | ********************************************************************************************* 16 | * Technical data: 17 | * Devices send 50 pulses. Manchester encoded, 25 bits 18 | * 19 | * PIR Motion detection unit: 20 | * PCB contains 2 chips: biss0001 & ev1527 21 | * BISS0001 = Micro Power PIR Motion Detector IC 22 | * EV1527 = OTP Encoder, max. of 20 bits providing up to 1 million codes. 23 | * 24 | * Sample: 25 | * Pulses=50, Pulses(uSec)=900,225,200,850,225,850,825,225,225,850,225,850,825,225,225,850,200,850,225,850,825,225,225,850,825,225,225,850,825,225,825,225,825,225,825,225,825,225,825,225,825,225,225,850,225,850,825,225,225, 26 | * 100101100101100101011001100110101010101010010110 27 | * 01101101 1101010000000110 6D D406 28 | 29 | * 20;9A;DEBUG;Pulses=50;Pulses(uSec)=475,925,400,950,1150,175,400,950,375,950,1125,200,1100,225,1100,250,1075,250,1075,275,1050,275,1050,275,1050,275,1050,275,275,1050,1050,275,300,1050,1050,275,300,1050,300,1050,1050,275,300,1050,275,1050,1050,275,275; 30 | * 010110010110101010101010101001100110010110010110 31 | * 00100111 1111110101001001 27 FD49 32 | * 11011000 0000001010110110 D8 02B6 33 | 34 | * 1975,275,900,250,225,975,250,975,250,975,225,975,900,250,900,250,900,250,250,950,225,975,900,250,225,950,225,975,250,950,225,975,900,250,900,250,900,250,250,950,900,250,250,950,225,950,925,250,250; 35 | * 101001010101101010010110010101011010100110010110 36 | * 001111000110111100010110 3C6F16 37 | * 110000111001000011101001 c390E9 38 | \*********************************************************************************************/ 39 | #define ALARMPIRV1_PLUGIN_ID 061 40 | #define PLUGIN_DESC_061 "EV1527" 41 | 42 | #define ALARMPIRV1_PULSECOUNT 50 43 | 44 | #define ALARMPIRV1_PULSEMID 600 / RAWSIGNAL_SAMPLE_RATE 45 | #define ALARMPIRV1_PULSEMAX 1300 / RAWSIGNAL_SAMPLE_RATE 46 | #define ALARMPIRV1_PULSEMIN 150 / RAWSIGNAL_SAMPLE_RATE 47 | 48 | #ifdef PLUGIN_061 49 | #include "../4_Display.h" 50 | 51 | boolean Plugin_061(byte function, char *string) 52 | { 53 | if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) 54 | return false; 55 | if (RawSignal.Pulses[0] == 63) 56 | return false; // No need to test, packet for plugin 63 57 | unsigned long bitstream = 0L; 58 | unsigned long bitstream2 = 0L; 59 | //================================================================================== 60 | // Get all 24 bits 61 | //================================================================================== 62 | for (byte x = 2; x <= 48; x += 2) 63 | { 64 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID) 65 | { 66 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) 67 | return false; // pulse too long 68 | if (RawSignal.Pulses[x - 1] > ALARMPIRV1_PULSEMID) 69 | return false; // invalid pulse sequence 10/01 70 | bitstream = bitstream << 1; 71 | } 72 | else 73 | { 74 | if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) 75 | return false; // pulse too short 76 | if (RawSignal.Pulses[x - 1] < ALARMPIRV1_PULSEMID) 77 | return false; // invalid pulse sequence 10/01 78 | bitstream = (bitstream << 1) | 0x1; 79 | } 80 | } 81 | //================================================================================== 82 | // Prevent repeating signals from showing up 83 | //================================================================================== 84 | 85 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 200) < millis()) || (SignalCRC != bitstream)) 86 | { 87 | // not seen the RF packet recently 88 | if (bitstream == 0) 89 | return false; 90 | 91 | SignalCRC = bitstream; 92 | } 93 | else 94 | { 95 | // already seen the RF packet recently 96 | return true; 97 | } 98 | //================================================================================== 99 | bitstream2 = (bitstream) >> 16; 100 | if ((bitstream2) == 0xff) 101 | { 102 | if ((bitstream & 0xffff) == 0xff) 103 | return false; 104 | } 105 | //================================================================================== 106 | // Output 107 | // ---------------------------------- 108 | display_Header(); 109 | display_Name(PSTR("EV1527")); 110 | display_IDn(((bitstream >> 4) & 0x0FFFFF), 6); // "%S%06lx" 111 | display_SWITCH((bitstream & 0x0F)); 112 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 113 | display_Footer(); 114 | //================================================================================== 115 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 116 | RawSignal.Number = 0; 117 | return true; 118 | } 119 | #endif // Plugin_061 120 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_062.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-062: Chuango AlarmSensors ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This protocol provides support for Chuango Alarm sensors (Motion detectors and door/window contacts) 7 | * Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly 8 | * 9 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 10 | * Support (present) : https://github.com/couin3/RFLink 11 | * Author (original) : StuntTeam 2015..2016 12 | * Support (original) : http://sourceforge.net/projects/rflink/ 13 | * License : This code is free for use in any open source project when this header is included. 14 | * Usage of any parts of this code in a commercial application is prohibited! 15 | ********************************************************************************************* 16 | * Technical data: 17 | * Devices send 50 pulses, 24 bits 18 | * 19 | * Sample: 20 | * 20;03;DEBUG;Pulses=50;Pulses(uSec)=1725,325,1650,325,1625,350,575,1400,1600,400,1525,475,450,1550,1475,500,1500,500,450,1475,550,1450, 21 | * 550,1425,1600,400,525,1475,1500,450,1500,525,1475,500,425,1525,475,1475,500,1450,525,1450,1575,400,1550,425,1500,500,400; 22 | * 20;03;DEBUG;Pulses=50;Pulses(uSec)=1620,420,1530,450,1560,390,510,1440,1560,420,1530,420,450,1530,1440,510,1440,540,360,1500,450,1470,480,1470,1560,390,510,1440,1530,420,1500,480,1470,570,330,1590,390,1530,450,1500,480,1470,1530,420,1530,420,1530,420,450,3360; 23 | * 101010011010011010010101100110101001010101101010 0 24 | * 00010010 01110100 01111000 = 0x 12 74 78 25 | \*********************************************************************************************/ 26 | #define ALARMPIRV2_PLUGIN_ID 062 27 | #define PLUGIN_DESC_062 "Chuango" 28 | 29 | #define ALARMPIRV2_PULSECOUNT 50 30 | 31 | #define ALARMPIRV2_PULSEMID 700 / RAWSIGNAL_SAMPLE_RATE 32 | #define ALARMPIRV2_PULSEMAX 2000 / RAWSIGNAL_SAMPLE_RATE 33 | #define ALARMPIRV2_PULSEMIN 150 / RAWSIGNAL_SAMPLE_RATE 34 | 35 | #ifdef PLUGIN_062 36 | #include "../4_Display.h" 37 | 38 | boolean Plugin_062(byte function, char *string) 39 | { 40 | if (RawSignal.Number != ALARMPIRV2_PULSECOUNT) 41 | return false; 42 | if (RawSignal.Pulses[0] == 63) 43 | return false; // No need to test, packet for plugin 63 44 | 45 | unsigned long bitstream = 0L; 46 | //================================================================================== 47 | // Get all 24 bits 48 | //================================================================================== 49 | for (byte x = 2; x <= 48; x += 2) 50 | { 51 | if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMID) 52 | { 53 | if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMAX) 54 | return false; // pulse too long 55 | if (RawSignal.Pulses[x - 1] > ALARMPIRV2_PULSEMID) 56 | return false; // invalid pulse sequence 10/01 57 | bitstream = (bitstream << 1) | 0x1; 58 | } 59 | else 60 | { 61 | if (RawSignal.Pulses[x] < ALARMPIRV2_PULSEMIN) 62 | return false; // pulse too short 63 | if (RawSignal.Pulses[x - 1] < ALARMPIRV2_PULSEMID) 64 | return false; // invalid pulse sequence 10/01 65 | bitstream = bitstream << 1; 66 | } 67 | } 68 | //================================================================================== 69 | // Prevent repeating signals from showing up 70 | //================================================================================== 71 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 200) < millis()) || (SignalCRC != bitstream)) 72 | { 73 | // not seen the RF packet recently 74 | if (bitstream == 0) 75 | return false; 76 | 77 | SignalCRC = bitstream; 78 | } 79 | else 80 | { 81 | // already seen the RF packet recently 82 | return true; 83 | } 84 | //================================================================================== 85 | // Validity checks 86 | //================================================================================== 87 | // Output 88 | // ---------------------------------- 89 | display_Header(); 90 | display_Name(PSTR("Chuango")); 91 | display_IDn((bitstream & 0xFFFFFF), 6); // "%S%06lx" 92 | display_SWITCH(2); 93 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 94 | display_Footer(); 95 | 96 | //================================================================================== 97 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 98 | RawSignal.Number = 0; 99 | return true; 100 | } 101 | #endif // Plugin_062 102 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_063.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-063: Oregon PIR/LED/ALARM ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin provides support for Oregon PIR/LED/ALARM devices 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Technical data: 16 | * Devices send 50/52 pulses using typical Oregon bit encoding 17 | * 18 | * Sample: 19 | * 570,390,570,360,570,360,540,360,540,360,570,360,570,330,570,330,570,330,570,330,570,330,570,360,540,360,540,360,1110,330,570,900,1110,900,540,330,570,330,1110,900,1110,360,540,360,540,900,1110,330,570,330,570,1620 20 | * 00101110 10001000 = 2E88 21 | \*********************************************************************************************/ 22 | #define OREGON_PLA_PLUGIN_ID 063 23 | #define PLUGIN_DESC_063 "X10" 24 | 25 | #define OREGON_PLA_PULSECOUNT 52 26 | 27 | #ifdef PLUGIN_063 28 | #include "../4_Display.h" 29 | 30 | boolean Plugin_063(byte function, char *string) 31 | { 32 | if ((RawSignal.Number < OREGON_PLA_PULSECOUNT - 2) || (RawSignal.Number > OREGON_PLA_PULSECOUNT)) 33 | return false; 34 | 35 | if (RawSignal.Pulses[0] != 63) 36 | return false; // Only accept RF packets converted by plugin 1 37 | RawSignal.Pulses[0] = 0; 38 | 39 | unsigned long bitstream = 0L; 40 | //================================================================================== 41 | // Perform a pre sanity check 42 | //================================================================================== 43 | for (byte x = 1; x < 28; x += 2) 44 | { 45 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 600) 46 | return false; 47 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply > 600) 48 | return false; 49 | } 50 | //================================================================================== 51 | byte bits = 0; 52 | byte rfbit = 1; 53 | //================================================================================== 54 | // Get all 24 bits 55 | //================================================================================== 56 | for (byte x = 29; x <= RawSignal.Number; x++) 57 | { 58 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 600) 59 | { // toggle bit value 60 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 1600) 61 | break; // done.. 62 | rfbit = (~rfbit) & 1; 63 | bitstream = (bitstream << 1) | rfbit; 64 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply < 600) 65 | x++; 66 | } 67 | else 68 | { 69 | bitstream = (bitstream << 1) | rfbit; // short pulse keep bit value 70 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply < 600) 71 | x++; 72 | } 73 | } 74 | //================================================================================== 75 | // Prevent repeating signals from showing up 76 | //================================================================================== 77 | if ((SignalHash != SignalHashPrevious) || (RepeatingTimer + 2000 < millis())) 78 | { 79 | // not seen the RF packet recently 80 | if (bitstream == 0) 81 | return false; 82 | } 83 | else 84 | { 85 | // already seen the RF packet recently 86 | return true; 87 | } 88 | //================================================================================== 89 | // calculate sensor and channel 90 | bitstream = (bitstream) >> 4; 91 | bits = (bitstream)&0x3; 92 | bits = bits + 0x30; // signal 3 for plugin 63 93 | //================================================================================== 94 | // Output 95 | // ---------------------------------- 96 | display_Header(); 97 | display_Name(PSTR("X10")); 98 | display_IDn((bitstream & 0xFFFFFF), 6); // "%S%06lx" 99 | display_SWITCH(bits); // "%02x" 100 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 101 | display_Footer(); 102 | //================================================================================== 103 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 104 | RawSignal.Number = 0; 105 | return true; 106 | } 107 | #endif // Plugin_063 108 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_064.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-064: Atlantic PIR/ALARM ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin provides support for Atlantic and Visonic PIR/ALARM devices 7 | * 8 | * Author : StormTeam 2020 - Cyril PAWELKO - Marc RIVES (aka Couin3) 9 | * Support : https://github.com/couin3/RFLink 10 | * License : This code is free for use in any open source project when this header is included. 11 | * Usage of any parts of this code in a commercial application is prohibited! 12 | ********************************************************************************************* 13 | * Protocol information : 14 | * https://forum.arduino.cc/index.php?topic=289554.0 15 | * Visonic Sensors Documentation Annex 16 | * 17 | * Sample data: 18 | * 20;XX;DEBUG;Pulses=370;Pulses(uSec)=352,416,768,832,352,416,768,832,352,832,352,416,768,832,352,832,352,832,352,416,768,832,352,832,352,416,768,448,736,448,768,416,768,832,352,832,352,832,352,416,768,832,352,832,352,832,352,416,736,832,352,832,352,832,352,416,768,832,352,832,352,416,768,416,736,416,768,832,352,832,352,832,352,4160; 19 | * Only tested with Visonic 433 Mhz (Europe) devices : MCT-302, K-980MCW 20 | * Not tested with real Atlantic devices. Feedback is welcome. 21 | \*********************************************************************************************/ 22 | 23 | #define ATLANTIC_PLUGIN_ID 064 24 | #define PLUGIN_DESC_064 "Atlantic" 25 | #define ATLANTIC_PULSECOUNT 74 26 | 27 | #define ATLANTIC_PULSE_MID 600 / RAWSIGNAL_SAMPLE_RATE 28 | #define ATLANTIC_PULSE_MIN 300 / RAWSIGNAL_SAMPLE_RATE 29 | #define ATLANTIC_PULSE_MAX 900 / RAWSIGNAL_SAMPLE_RATE 30 | 31 | #ifdef PLUGIN_064 32 | #include "../4_Display.h" 33 | 34 | boolean Plugin_064(byte function, char *string) 35 | { 36 | if (RawSignal.Number != ATLANTIC_PULSECOUNT) 37 | return false; 38 | 39 | unsigned long bitstream = 0L; // Only the 32 first bits are processed 40 | 41 | //================================================================================== 42 | // Get first 32 bits : Sensor ID (24 bits) + 8 first bits of data 43 | // Bits are inverted ! 44 | //================================================================================== 45 | 46 | for (byte x = 2; x <= 64; x += 2) 47 | { 48 | if (RawSignal.Pulses[x] > ATLANTIC_PULSE_MID) 49 | { // long pulse = 1 50 | if (RawSignal.Pulses[x] > ATLANTIC_PULSE_MAX) 51 | return false; // pulse too long 52 | if (RawSignal.Pulses[x + 1] > ATLANTIC_PULSE_MAX) 53 | return false; // invalid manchester code 54 | bitstream = (bitstream << 1) | 0x1; 55 | } 56 | else 57 | { // short pulse = 0 58 | if (RawSignal.Pulses[x] < ATLANTIC_PULSE_MIN) 59 | return false; // pulse too short 60 | if (RawSignal.Pulses[x + 1] < ATLANTIC_PULSE_MID) 61 | return false; // invalid manchester code 62 | bitstream = bitstream << 1; 63 | } 64 | } 65 | //================================================================================== 66 | // Prevent repeating signals from showing up 67 | //================================================================================== 68 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer) + 700 < millis()) || (SignalCRC != bitstream)) 69 | SignalCRC = bitstream; 70 | else 71 | return true; // packet already seen 72 | //================================================================================== 73 | // Extract data 74 | //================================================================================== 75 | boolean alarm = (bitstream >> 6) & 0x01; 76 | unsigned long ID = (bitstream >> 8) & 0xFFFFFF; 77 | // ---------------------------------- 78 | // Output 79 | // ---------------------------------- 80 | display_Header(); 81 | display_Name(PSTR("Atlantic")); 82 | display_IDn(ID, 6); 83 | display_SWITCH(1); 84 | display_CMD(CMD_Single, alarm ? CMD_On : CMD_Off); 85 | display_Footer(); 86 | //================================================================================== 87 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 88 | RawSignal.Number = 0; 89 | return true; 90 | } 91 | #endif // Plugin_064 92 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_065.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-065: 640us-based keyfobs ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This protocol provides support for basic keyfobs, used in garage openers 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Technical data: 16 | * Devices send 48 pulses, 24 bits total. 17 | * 18 | * Sample: 19 | * 20;XX;DEBUG;Pulses=49;Pulses(uSec)=192,448,160,480,480,160,480,160,448,192,128,512,128,544,96,544,448,192,128,512,160,512,480,160,128,512,480,160,480,192,128,512,480,160,480,160,128,512,448,192,128,512,128,512,128,512,448,192,96; 20 | * 20;XX;DEBUG;Pulses=49;Pulses(uSec)=160,480,192,448,480,160,480,160,448,192,128,512,128,512,128,512,448,192,96,544,96,512,480,160,128,512,480,160,480,160,128,512,480,160,480,160,128,512,480,160,128,512,128,512,128,512,480,160,96; 21 | * 00111000 10010110 11010001 = 0x3896d1 22 | \*********************************************************************************************/ 23 | #define GARAGE640_PLUGIN_ID 065 24 | #define PLUGIN_DESC_065 "GARAGE640" 25 | 26 | #define GARAGE640_PULSECOUNT 48 27 | 28 | #define GARAGE640_PULSEMID (320 / RAWSIGNAL_SAMPLE_RATE) 29 | #define GARAGE640_PULSEMAX (540 / RAWSIGNAL_SAMPLE_RATE) 30 | #define GARAGE640_PULSEMIN (60 / RAWSIGNAL_SAMPLE_RATE) 31 | 32 | #ifdef PLUGIN_065 33 | #include "../4_Display.h" 34 | 35 | boolean Plugin_065(byte function, char *string) { 36 | if (RawSignal.Number != GARAGE640_PULSECOUNT || RawSignal.Pulses[0] != 65) 37 | return false; 38 | 39 | 40 | unsigned long bitstream = 0L; 41 | //================================================================================== 42 | // Get all 24 bits 43 | //================================================================================== 44 | for (byte x = 1; x < GARAGE640_PULSECOUNT; x += 2) 45 | { 46 | if (RawSignal.Pulses[x] > GARAGE640_PULSEMID) 47 | { 48 | if (RawSignal.Pulses[x] > GARAGE640_PULSEMAX) 49 | return false; // pulse too long 50 | if (RawSignal.Pulses[x + 1] > GARAGE640_PULSEMID) 51 | return false; // invalid pulse sequence 10/01 52 | bitstream = (bitstream << 1) | 0x1; 53 | } 54 | else 55 | { 56 | if (RawSignal.Pulses[x] < GARAGE640_PULSEMIN) 57 | return false; // pulse too short 58 | if (RawSignal.Pulses[x + 1] < GARAGE640_PULSEMID) 59 | return false; // invalid pulse sequence 10/01 60 | bitstream = bitstream << 1; 61 | } 62 | } 63 | //================================================================================== 64 | // Prevent repeating signals from showing up 65 | //================================================================================== 66 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 200) < millis()) || (SignalCRC != bitstream)) 67 | { 68 | // not seen the RF packet recently 69 | if (bitstream == 0) 70 | return false; 71 | 72 | SignalCRC = bitstream; 73 | } 74 | else 75 | { 76 | // already seen the RF packet recently 77 | return true; 78 | } 79 | //================================================================================== 80 | // Validity checks 81 | //================================================================================== 82 | // Output 83 | // ---------------------------------- 84 | display_Header(); 85 | display_Name(PSTR("GARAGE640")); 86 | display_IDn((bitstream & 0xFFFFFF), 6); // "%S%06lx" 87 | display_Footer(); 88 | 89 | //================================================================================== 90 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 91 | RawSignal.Number = 0; 92 | return true; 93 | } 94 | #endif // Plugin_065 95 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_070.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-070 Select Plus Wireless Doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception of the Select Plus wireless doorbell (Sold at Action for 6 euro's) 7 | * PCB markings: Quhwa QH-C-CE-3V aka QH-832AC 8 | * Also sold as "1 by One" and "Delta" wireless doorbell. 9 | * 10 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 11 | * Support (present) : https://github.com/couin3/RFLink 12 | * Author (original) : StuntTeam 2015..2016 13 | * Support (original) : http://sourceforge.net/projects/rflink/ 14 | * License : This code is free for use in any open source project when this header is included. 15 | * Usage of any parts of this code in a commercial application is prohibited! 16 | ********************************************************************************************* 17 | * Changelog: v1.0 initial release 18 | ********************************************************************************************* 19 | * Technical information: 20 | * 21 | * There are two known models: 22 | * SelectPlus (200689103 - Black - Datecode:0614) also sold as "1 by One" (O00 QH-0031) 23 | * PCB details: Quhwa, QH-C-CE-3V, 09.10.16, CPU: MC908T 24 | * SelectPlus (200689101 - White - Datecode:0914) 25 | * PCB details: Quhwa, QH-C-CE-3V, REV1.0, CPU: MC908T 26 | * 27 | * Each frame is 35 pulses long. It is composed of: 28 | * 101011001010110010110011010 10101010 29 | * The first block appears to be an unique ID 30 | * The second block appears to be some kind of identifier which always is 0xAA (10101010) 31 | * Converting the pulses into bits results in a 13 bit unique address and a 4 bit identifier: 32 | * 33 | * B) 1110000110011 0000 => 1C33 0 B)lack push button 34 | * W) 1101110110100 0000 => 1BB4 0 W)hite push button 35 | * 36 | * Note: The transmitter sends 43 times the same packet when the bell button is pressed 37 | * the retransmit is killed to prevent reporting the same press multiple times 38 | * 39 | * Sample: 40 | * B) 20;62;DEBUG;Pulses=36;Pulses(uSec)=1000,1000,225,1000,225,1000,225,300,900,300,900,300,900,300,900,1000,225,1000,225,300,925,300,900,1000,225,1000,225,275,900,300,900,300,900,300,900; 41 | * W) 20;A2;DEBUG;Pulses=36;Pulses(uSec)=325,950,250,950,250,250,925,950,250,950,250,950,250,275,925,950,250,950,250,250,925,950,250,275,925,250,925,275,925,250,925,275,925,275,925; 42 | * w) 20;66;DEBUG;Pulses=36;Pulses(uSec)=650,2000,550,2000,550,550,2000,2000,550,2000,550,2000,550,550,2000,2000,550,2000,550,550,2000,2000,550,550,2000,550,2000,550,1950,550,2000,550,2000,550,2000; 43 | * b) 20;05;DEBUG;Pulses=36;Pulses(uSec)=2100,2100,500,2050,500,2100,500,600,1950,600,1950,600,1950,600,1950,2050,500,2050,500,600,1950,600,1950,2100,500,2050,500,600,1950,600,1950,600,1950,600,1950; 44 | \*********************************************************************************************/ 45 | #define SELECTPLUS_PLUGIN_ID 070 46 | #define PLUGIN_DESC_070 "SelectPlus" 47 | #define SELECTPLUS_PULSECOUNT 36 48 | 49 | #define SELECTPLUS_PULSEMID 650 / RAWSIGNAL_SAMPLE_RATE 50 | #define SELECTPLUS_PULSEMAX 2125 / RAWSIGNAL_SAMPLE_RATE 51 | 52 | #ifdef PLUGIN_070 53 | #include "../4_Display.h" 54 | 55 | boolean Plugin_070(byte function, char *string) 56 | { 57 | if (RawSignal.Number != SELECTPLUS_PULSECOUNT) 58 | return false; 59 | 60 | unsigned long bitstream = 0L; 61 | byte checksum = 0; 62 | //================================================================================== 63 | // Get all 18 bits 64 | //================================================================================== 65 | for (byte x = 2; x < SELECTPLUS_PULSECOUNT; x = x + 2) 66 | { 67 | bitstream <<= 1; // Always shift 68 | if (RawSignal.Pulses[x] < SELECTPLUS_PULSEMID) 69 | { 70 | if (RawSignal.Pulses[x + 1] < SELECTPLUS_PULSEMID) 71 | return false; // invalid pulse sequence 10/01 72 | // bitstream |= 0x0; 73 | } 74 | else 75 | { 76 | if (RawSignal.Pulses[x] > SELECTPLUS_PULSEMAX) 77 | return false; // invalid pulse duration, pulse too long 78 | if (RawSignal.Pulses[x + 1] > SELECTPLUS_PULSEMID) 79 | return false; // invalid pulse sequence 10/01 80 | bitstream |= 0x1; 81 | } 82 | } 83 | //================================================================================== 84 | // Perform a quick sanity check 85 | //================================================================================== 86 | if (bitstream == 0) 87 | return false; 88 | //================================================================================== 89 | // Prevent repeating signals from showing up 90 | //================================================================================== 91 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 1000) < millis()) || (SignalCRC != bitstream)) 92 | SignalCRC = bitstream; // not seen the RF packet recently 93 | else 94 | return true; // already seen the RF packet recently 95 | //================================================================================== 96 | // all bytes received, make sure checksum is okay 97 | //================================================================================== 98 | checksum = (bitstream & 0xF); // Second block 99 | if (checksum != 0) 100 | return false; // last 4 bits should always be 0 101 | //================================================================================== 102 | // Output 103 | //================================================================================== 104 | display_Header(); 105 | display_Name(PSTR("SelectPlus")); 106 | display_IDn(((bitstream >> 4) & 0xFFFF), 4); 107 | display_SWITCH(1); 108 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 109 | display_CHIME(1); 110 | display_Footer(); 111 | //================================================================================== 112 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 113 | RawSignal.Number = 0; // do not process the packet any further 114 | return true; 115 | } 116 | #endif // PLUGIN_070 117 | 118 | #ifdef PLUGIN_TX_070 119 | void SelectPlus_Send(unsigned long address); 120 | 121 | boolean PluginTX_070(byte function, char *string) 122 | { 123 | boolean success = false; 124 | unsigned long bitstream = 0L; 125 | //10;SELECTPLUS;001c33;1;OFF; 126 | //012345678901234567890123456 127 | if (strncasecmp(InputBuffer_Serial + 3, "SELECTPLUS;", 11) == 0) 128 | { 129 | InputBuffer_Serial[12] = 0x30; 130 | InputBuffer_Serial[13] = 0x78; 131 | InputBuffer_Serial[20] = 0; 132 | bitstream = str2int(InputBuffer_Serial + 12); 133 | bitstream = bitstream << 4; 134 | SelectPlus_Send(bitstream); // Send RF packet 135 | success = true; 136 | } 137 | return success; 138 | } 139 | 140 | void SelectPlus_Send(unsigned long address) 141 | { 142 | int fpulse = 364; // Pulse witdh in microseconds 143 | int fretrans = 16; // number of RF packet retransmissions 144 | uint32_t fdatabit; 145 | uint32_t fdatamask = 0x10000; 146 | uint32_t fsendbuff; 147 | 148 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) 149 | { 150 | fsendbuff = address; 151 | // send SYNC 3P High 152 | digitalWrite(PIN_RF_TX_DATA, HIGH); 153 | delayMicroseconds(fpulse * 3); 154 | // end send SYNC 155 | // Send command 156 | for (int i = 0; i < 17; i++) 157 | { // SelectPlus address is only 13 bits, last 4 bits are always zero 158 | // read data bit7 159 | fdatabit = fsendbuff & fdatamask; // Get most left bit 160 | fsendbuff = (fsendbuff << 1); // Shift left 161 | 162 | if (fdatabit != fdatamask) 163 | { // Write 0 164 | digitalWrite(PIN_RF_TX_DATA, LOW); // short low 165 | delayMicroseconds(fpulse * 1); 166 | digitalWrite(PIN_RF_TX_DATA, HIGH); // long high 167 | delayMicroseconds(fpulse * 3); 168 | } 169 | else 170 | { // Write 1 171 | digitalWrite(PIN_RF_TX_DATA, LOW); 172 | delayMicroseconds(fpulse * 3); // long low 173 | digitalWrite(PIN_RF_TX_DATA, HIGH); 174 | delayMicroseconds(fpulse * 1); // short high 175 | } 176 | } 177 | digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal 178 | if (nRepeat < fretrans) 179 | { 180 | delayMicroseconds(fpulse * 16); // delay between RF transmits 181 | } 182 | } 183 | } 184 | #endif // PLUGIN_070 185 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_071.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-071 Plieger York doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Plieger York Doorbell protocol 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical Information: 18 | * Decodes signals from a Plieger York Doorbell, (66 pulses, 32 bits, 433 MHz). 19 | * Plieger Message Format: 20 | * 0000000001010101 00000000 00011100 c2 0x1c 21 | * 00000011 c3 0x03 22 | * 11100000 c1 0xE0 23 | * -------- 8 bits chime number (3 chimes, can be changed with a jumped on the transmitter) 24 | * -------- 8 bits always 0 25 | * ---------------- 16 bits code which can be changed with a button on the inside of the transmitter 26 | * 27 | * Note: The transmitter sends two times the same packet when the bell button is pressed 28 | * the retransmit is killed to prevent reporting the same press twice 29 | * 30 | * Sample packet: (Nodo Pulse timing) 31 | * Pulses=66, Pulses(uSec)=700,250,275,725,750,250,275,725,750,250,275,725,750,250,275,725,750,250, 32 | * 275,725,750,250,275,725,750,250,275,725,750,250,275,725,275,725,275,725,275,725,275,725,275,725, 33 | * 275,725,275,725,275,725,275,725,275,725,275,725,750,250,750,250,750,250,275,725,275,725,225, 34 | * 20;8C;DEBUG;Pulses=66;Pulses(uSec)=1800,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,500,600,1500,1600,550,600,1550,1600,550,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,1600,550,1600,500,1600,550,600,1500,600,1500,450; 35 | * 20;2D;DEBUG;Pulses=66;Pulses(uSec)=875,275,300,750,800,275,300,750,800,275,300,750,800,275,300,750,800,275,300,750,800,250,300,750,800,275,275,750,800,275,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,800,275,800,275,800,250,300,750,300,750,225; 36 | * 20;2E;Plieger York;ID=aaaa;SWITCH=1;CMD=ON;CHIME=02; 37 | \*********************************************************************************************/ 38 | #define PLIEGER_PLUGIN_ID 071 39 | #define PLUGIN_DESC_071 "Plieger" 40 | 41 | #define PLIEGER_PULSECOUNT 66 42 | 43 | #define PLIEGER_PULSEMID 700 / RAWSIGNAL_SAMPLE_RATE 44 | #define PLIEGER_PULSEMAX 1900 / RAWSIGNAL_SAMPLE_RATE 45 | 46 | #ifdef PLUGIN_071 47 | #include "../4_Display.h" 48 | 49 | boolean Plugin_071(byte function, char *string) 50 | { 51 | if (RawSignal.Number != PLIEGER_PULSECOUNT) 52 | return false; 53 | 54 | unsigned long bitstream = 0L; 55 | unsigned int id = 0; 56 | byte chime = 0; 57 | //================================================================================== 58 | // Get all 32 bits 59 | //================================================================================== 60 | for (byte x = 1; x <= PLIEGER_PULSECOUNT - 2; x += 2) 61 | { 62 | bitstream <<= 1; // Always shift 63 | if (RawSignal.Pulses[x] > PLIEGER_PULSEMID) 64 | { 65 | if (RawSignal.Pulses[x] > PLIEGER_PULSEMAX) 66 | return false; 67 | if (RawSignal.Pulses[x + 1] > PLIEGER_PULSEMID) 68 | return false; // Valid Manchester check 69 | bitstream |= 0x1; 70 | } 71 | else 72 | { 73 | if (RawSignal.Pulses[x + 1] < PLIEGER_PULSEMID) 74 | return false; // Valid Manchester check 75 | // bitstream |= 0x0; 76 | } 77 | } 78 | //================================================================================== 79 | // Perform a quick sanity check 80 | //================================================================================== 81 | if (bitstream == 0) 82 | return false; 83 | if (((bitstream >> 8) & 0xFF) != 0x00) 84 | return false; // these 8 bits are always 0 85 | //================================================================================== 86 | // Prevent repeating signals from showing up 87 | //================================================================================== 88 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 1000) < millis()) || (SignalCRC != bitstream)) 89 | SignalCRC = bitstream; // not seen the RF packet recently 90 | else 91 | return true; // already seen the RF packet recently 92 | //================================================================================== 93 | id = ((bitstream >> 16) & 0xFFFF); // get 16 bits unique address 94 | chime = bitstream & 0xFF; 95 | switch (chime) 96 | { 97 | case 0x03: 98 | chime = 0; 99 | break; 100 | case 0xE0: 101 | chime = 1; 102 | break; 103 | case 0x1C: 104 | chime = 2; 105 | break; 106 | default: 107 | return false; // the chime number can only have 3 values 108 | } 109 | //================================================================================== 110 | // Output 111 | //================================================================================== 112 | display_Header(); 113 | display_Name(PSTR("Plieger")); 114 | display_IDn(id, 4); 115 | display_SWITCH(1); 116 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 117 | display_CHIME(chime); 118 | display_Footer(); 119 | //================================================================================== 120 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 121 | RawSignal.Number = 0; // do not process the packet any further 122 | return true; 123 | } 124 | #endif // PLUGIN_071 125 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_073.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-073 Deltronic Doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception And sending of the Deltronic doorbell 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam & Jonas Jespersen 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Technical information: 16 | * 17 | * The doorbell uses the UM3750 circuit which sends out a 12 bit signal: 18 | * 19 | * AAAAAAAA BBBB 20 | * 21 | * A = Always 1 22 | * B = Address (Can be either 1, 5 or 9) 23 | * 24 | * Address 1 25 | * 20;0D;DEBUG;Pulses=26;Pulses(uSec)=600,1150,525,1175,500,1175,475,1200,500,1175,500,1200,475,1175,475,1200,475,575,1075,575,1075,575,1075,1225,450; 26 | * 000000001110 27 | * Address 5 28 | * 20;17;DEBUG;Pulses=26;Pulses(uSec)=550,1075,425,1100,400,1125,425,1100,400,1125,400,1150,375,1125,400,1125,375,550,900,1125,375,550,900,1150,375; 29 | * 000000001010 30 | * Address 9 31 | * 20;1B;DEBUG;Pulses=26;Pulses(uSec)=600,1150,500,1175,525,1175,500,1175,500,1175,500,1175,500,1175,475,1200,500,1200,475,575,1075,600,1075,1200,475; 32 | * 000000000110 33 | \*********************************************************************************************/ 34 | #define DELTRONIC_PLUGIN_ID 073 35 | #define PLUGIN_DESC_073 "Deltronic" 36 | 37 | #define DELTRONIC_PULSECOUNT 26 38 | 39 | #define LENGTH_DEVIATION 300 40 | 41 | #ifdef PLUGIN_073 42 | #include "../4_Display.h" 43 | 44 | boolean Plugin_073(byte function, char *string) 45 | { 46 | if (RawSignal.Number != DELTRONIC_PULSECOUNT) 47 | return false; 48 | 49 | unsigned long bitstream = 0L; 50 | unsigned long checksum = 0L; 51 | //================================================================================== 52 | if (RawSignal.Pulses[1] * RAWSIGNAL_SAMPLE_RATE > 675) 53 | return false; // First pulse is start bit and should be short! 54 | //================================================================================== 55 | // Get all 12 bits 56 | //================================================================================== 57 | for (byte x = 2; x < DELTRONIC_PULSECOUNT; x = x + 2) 58 | { 59 | bitstream <<= 1; // Always shift 60 | if (RawSignal.Pulses[x] * RAWSIGNAL_SAMPLE_RATE > 800) 61 | { // long pulse (800-1275) 62 | if (RawSignal.Pulses[x] * RAWSIGNAL_SAMPLE_RATE > 1275) 63 | return false; // pulse too long to be valid 64 | if (RawSignal.Pulses[x + 1] * RAWSIGNAL_SAMPLE_RATE > 675) 65 | return false; // invalid manchestercode (10 01) 66 | 67 | bitstream |= 0x1; // 10 => 1 bit 68 | } 69 | else 70 | { // short pulse 71 | if (RawSignal.Pulses[x] * RAWSIGNAL_SAMPLE_RATE < 250) 72 | return false; // too short 73 | if (RawSignal.Pulses[x + 1] * RAWSIGNAL_SAMPLE_RATE < 700) 74 | return false; // invalid manchestercode (10 01) 75 | 76 | // bitstream |= 0x0; // 01 => 0 bit 77 | } 78 | } 79 | //================================================================================== 80 | // Perform a quick sanity check 81 | //================================================================================== 82 | if (bitstream == 0) 83 | return false; 84 | checksum = (bitstream)&0x00000FF0L; // First 8 bits should always be 1 85 | if (checksum != 0x00000FF0L) 86 | return false; 87 | //================================================================================== 88 | // Prevent repeating signals from showing up 89 | //================================================================================== 90 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 1000) < millis()) || (SignalCRC != bitstream)) 91 | SignalCRC = bitstream; // not seen the RF packet recently 92 | else 93 | return true; // already seen the RF packet recently 94 | //================================================================================== 95 | // Output 96 | //================================================================================== 97 | display_Header(); 98 | display_Name(PSTR("Deltronic")); 99 | display_IDn((bitstream & 0x0000000FL), 4); 100 | display_SWITCH(1); 101 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 102 | display_CHIME(1); 103 | display_Footer(); 104 | //================================================================================== 105 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 106 | RawSignal.Number = 0; // do not process the packet any further 107 | return true; 108 | } 109 | #endif // PLUGIN_073 110 | 111 | #ifdef PLUGIN_TX_073 112 | void Deltronic_Send(unsigned long address); 113 | 114 | boolean PluginTX_073(byte function, char *string) 115 | { 116 | boolean success = false; 117 | unsigned long bitstream = 0L; 118 | //10;DELTRONIC;001c33;1;OFF; 119 | //012345678901234567890123456 120 | if (strncasecmp(InputBuffer_Serial + 3, "DELTRONIC;", 10) == 0) 121 | { 122 | InputBuffer_Serial[11] = 0x30; 123 | InputBuffer_Serial[12] = 0x78; 124 | InputBuffer_Serial[19] = 0; 125 | bitstream = str2int(InputBuffer_Serial + 11); 126 | bitstream = (bitstream) | 0x00000FF0L; 127 | Deltronic_Send(bitstream); // Send RF packet 128 | success = true; 129 | } 130 | return success; 131 | } 132 | 133 | void Deltronic_Send(unsigned long address) 134 | { 135 | byte repeatTimes = 16; 136 | byte repeat, index; 137 | int periodLong, periodSync; 138 | unsigned long bitmask; 139 | int period = 640; 140 | 141 | periodLong = 2 * period; 142 | periodSync = 36 * period; 143 | 144 | // Send seperator 145 | digitalWrite(PIN_RF_TX_DATA, HIGH); 146 | delayMicroseconds(period); 147 | 148 | // Send sync 149 | digitalWrite(PIN_RF_TX_DATA, LOW); 150 | delayMicroseconds(periodSync); 151 | digitalWrite(PIN_RF_TX_DATA, HIGH); 152 | delayMicroseconds(period); 153 | 154 | for (repeat = 0; repeat < repeatTimes; repeat++) 155 | { 156 | bitmask = 0x00000800L; 157 | for (index = 0; index < 12; index++) 158 | { 159 | if (address & bitmask) 160 | { 161 | // Send 1 162 | digitalWrite(PIN_RF_TX_DATA, LOW); 163 | delayMicroseconds(periodLong); 164 | digitalWrite(PIN_RF_TX_DATA, HIGH); 165 | delayMicroseconds(period); 166 | } 167 | else 168 | { 169 | // Send 0 170 | digitalWrite(PIN_RF_TX_DATA, LOW); 171 | delayMicroseconds(period); 172 | digitalWrite(PIN_RF_TX_DATA, HIGH); 173 | delayMicroseconds(periodLong); 174 | } 175 | bitmask >>= 1; 176 | } 177 | // Send sync 178 | digitalWrite(PIN_RF_TX_DATA, LOW); 179 | delayMicroseconds(periodSync); 180 | digitalWrite(PIN_RF_TX_DATA, HIGH); 181 | delayMicroseconds(period); 182 | } 183 | digitalWrite(PIN_RF_TX_DATA, LOW); 184 | } 185 | #endif // PLUGIN_TX_073 186 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_075.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-075 Lidl doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Lidl/SilverCrest Doorbell protocol for model Z31370-TX 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 9-02-2015 RFLink 1.0 11 | * Support (original) : www.nodo-domotica.nl 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical Information: 18 | * Decodes signals from a Lidl Doorbell, (90 pulses, 40 bits, 433 MHz). 19 | * Lidl Doorbell Message Format: 20 | * 1010 1111 1000 0010 0001 1011 0011 0000 0000 0000 AF821B3000 21 | * -------------- always zero 22 | * 23 | * Sample packet: (Nodo Pulse timing) 24 | * 1850,1200,1400,1200,1400,1200,1400,1200,1400, (Preamble) 25 | * 700,400,200,900,700,400,200,900,700,400,700,400,700,400,700,400,700,400,200,900,200,900,200,900,200,900,200,900,700,400,250,900,200,900,200,900,700, 26 | * 400,700,400,700,400,200,900,700,400,700,400,200,900,200,900,700,400,700,400,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900, 27 | * 200,900,200,900,250,900,200 28 | ********************************************************************************************* 29 | * Technical Information: 30 | * Decodes signals from a Lidl SilverCrest Z31370-TX Doorbell, (114 pulses, 48 bits, 433 MHz). 31 | * SilverCrest Doorbell Message Format: 32 | * 01011100 10100101 10001000 | 00000100 11010110 10111011 10010111 5CA588 04D6BB97 33 | * always the same | device unique number 34 | * 35 | * Sample packet: 36 | * 20;14;DEBUG;Pulses=114;Pulses(uSec)=360,60,60,390,360,60,60,390,60,390,60,390,390,60,360,60,60,390,360,60,60,390,360,60,360,60,60,390,360,60,60,390,60,390,360,60,360,60,360,60,30,390,360,60,360,60,360,60,390,60,360,60,60,390,390,60,360,60,360,60,390,60,360,60,390,60,360,60,360,60,390,60,60,390,60,390,30,390,60,390,60,390,360,60,60,390,60,390,60,390,60,390,360,60,360,60,60,390,60,390,60,390,360,60,60,390,60,390,360,60,60,390,360,1260; 37 | \*********************************************************************************************/ 38 | // ================================================================================== 39 | #define LIDL_PLUGIN_ID 075 40 | #define PLUGIN_DESC_075 "SilverCrest" 41 | 42 | #define LIDL_PULSECOUNT 90 // type 0 43 | #define LIDL_PULSECOUNT2 114 // type 1 44 | 45 | #ifdef PLUGIN_075 46 | #include "../4_Display.h" 47 | 48 | boolean Plugin_075(byte function, char *string) 49 | { 50 | if ((RawSignal.Number != LIDL_PULSECOUNT) && (RawSignal.Number != LIDL_PULSECOUNT2)) 51 | return false; 52 | unsigned long bitstream = 0; 53 | unsigned long bitstream2 = 0; 54 | 55 | int bitcount = 0; 56 | byte type = 0; 57 | //================================================================================== 58 | // Get all 40 bits 59 | //================================================================================== 60 | if (RawSignal.Number == LIDL_PULSECOUNT) 61 | { 62 | if (RawSignal.Pulses[1] * RawSignal.Multiply > 1000 && RawSignal.Pulses[2] * RawSignal.Multiply > 1000 && 63 | RawSignal.Pulses[3] * RawSignal.Multiply > 1000 && RawSignal.Pulses[4] * RawSignal.Multiply > 1000 && 64 | RawSignal.Pulses[5] * RawSignal.Multiply > 1000 && RawSignal.Pulses[6] * RawSignal.Multiply > 1000 && 65 | RawSignal.Pulses[7] * RawSignal.Multiply > 1000 && RawSignal.Pulses[8] * RawSignal.Multiply > 1000 && RawSignal.Pulses[9] * RawSignal.Multiply > 1000) 66 | { 67 | // 68 | } 69 | else 70 | return false; 71 | 72 | for (byte x = 10; x <= 90; x += 2) 73 | { 74 | if (bitcount < 28) 75 | { 76 | bitstream <<= 1; // Always shift 77 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 550) 78 | { 79 | // bitstream |= 0x0; 80 | } 81 | else 82 | { 83 | bitstream |= 0x1; 84 | } 85 | bitcount++; 86 | } 87 | else 88 | { 89 | bitstream2 <<= 1; // Always shift 90 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 550) 91 | { 92 | // bitstream2 |= 0x0; 93 | } 94 | else 95 | { 96 | bitstream2 |= 0x1; 97 | } 98 | bitcount++; 99 | } 100 | } 101 | } 102 | else 103 | { 104 | if (RawSignal.Pulses[0] != LIDL_PLUGIN_ID) 105 | return false; // only accept plugin1 translated packets 106 | type = 1; 107 | for (byte x = 1; x < LIDL_PULSECOUNT2 - 1; x += 2) 108 | { 109 | if (RawSignal.Pulses[x] * RawSignal.Multiply > 200) 110 | { 111 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply > 200) 112 | return false; // invalid pulse length 113 | if (bitcount > 23) 114 | { 115 | bitstream2 <<= 1; 116 | } 117 | else 118 | { 119 | bitstream <<= 1; 120 | } 121 | bitcount++; 122 | } 123 | else 124 | { 125 | if (RawSignal.Pulses[x + 1] * RawSignal.Multiply < 200) 126 | return false; // invalid pulse length 127 | if (bitcount > 23) 128 | { 129 | bitstream2 <<= 1; 130 | bitstream2 |= 0x1; 131 | } 132 | else 133 | { 134 | bitstream <<= 1; 135 | bitstream |= 0x1; 136 | } 137 | bitcount++; 138 | } 139 | } 140 | } 141 | //================================================================================== 142 | // Perform a quick sanity check 143 | //================================================================================== 144 | if (type == 0) 145 | { 146 | if ((bitstream2 & 0xFFF) != 0x000) 147 | return false; // these 12 bits are always 0 148 | } 149 | else 150 | { 151 | if (bitstream != 0x5CA588) 152 | return false; 153 | } 154 | //================================================================================== 155 | // Prevent repeating signals from showing up 156 | //================================================================================== 157 | if ((SignalHash != SignalHashPrevious) || ((RepeatingTimer + 1000) < millis()) || (SignalCRC != bitstream)) 158 | SignalCRC = bitstream; // not seen the RF packet recently 159 | else 160 | return true; // already seen the RF packet recently 161 | //================================================================================== 162 | // Output 163 | //================================================================================== 164 | display_Header(); 165 | display_Name(PSTR("SilverCrest")); 166 | if (type == 0) 167 | display_IDn(bitstream, 8); 168 | else 169 | display_IDn(bitstream2, 8); 170 | display_SWITCH(1); 171 | display_CMD(CMD_Single, CMD_On); // #ALL #ON 172 | display_CHIME(1); 173 | display_Footer(); 174 | //================================================================================== 175 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 176 | RawSignal.Number = 0; // do not process the packet any further 177 | return true; 178 | } 179 | #endif // PLUGIN_075_CORE 180 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_080.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-080 Flamingo FA20RF Rookmelder ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * Dit protocol zorgt voor ontvangst van Flamingo FA20RF rookmelder 7 | * 8 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 9 | * Support (present) : https://github.com/couin3/RFLink 10 | * Author (original) : StuntTeam 2015..2016 11 | * Support (original) : http://sourceforge.net/projects/rflink/ 12 | * License : This code is free for use in any open source project when this header is included. 13 | * Usage of any parts of this code in a commercial application is prohibited! 14 | ********************************************************************************************* 15 | * Changelog: v1.0 initial release 16 | ********************************************************************************************* 17 | * Technical information: 18 | * The Flamingo FA20RF/FA21RF Smokedetector contains both a RF receiver and transmitter. 19 | * Every unit has a unique ID. The detector has a "learn" button to learn the ID of other units. 20 | * That is what links the units to each other. After linking multiple units, they all have the same ID! 21 | * Normally, one unit is used as master and the code of the master is learned to the slaves 22 | * 23 | * Attention: The smoke detector gives an alarm as long as the message is transmitted 24 | * 25 | * Sample: 26 | * 20;32;DEBUG;Pulses=52;Pulses(uSec)=2500,800,650,1250,650,1250,650,1250,650,1250,650,1250,650,1275,650,1250,650,2550,650,1275,650,2550,650,1250,650,1250,650,2550,650,2550,650,1275,650,2550, 27 | * 650,2550,650,1275,650,2550,650,2550,650,1275,650,1275,650,2550,650,1200,650; 28 | * 000000010100110110110010 = 014DB2 29 | * 20;0C;DEBUG;Pulses=52;Pulses(uSec)=2500,825,625,2575,625,1275,625,1300,625,2575,625,1275,625,2575,625,2575,625,2575,625,2575,625,2575,625,2575,625,1275,625,1275,625,1275,625,2575,625,2575, 30 | * 625,2575,625,1275,625,2575,625,2575,625,1300,625,1275,625,2575,625,1225,625; 31 | * 100101111110001110110010 = 97E3B2 32 | * 20;0D;FA20RF;ID=97e3b2;SMOKEALERT=ON; 33 | * 34 | * False positive: 35 | * 20;52;DEBUG;Pulses=52;Pulses(uSec)=420,1860,330,3810,360,3960,360,1950,390,1920,360,3960,360,3960,360,3960,390,3960,390,3960,390,3960,390,1920,390,1920,390,1920,390,1890,480,1800,390,3930,390,1920,390,1920,420,1920,390,1920,420,1890,450,1860,420,1890,390,3930,390,6990; 36 | \*********************************************************************************************/ 37 | #define FA20_PLUGIN_ID 080 38 | #define PLUGIN_DESC_080 "FA20RF" 39 | 40 | #define FA20_PULSECOUNT 52 41 | 42 | #define FA20_MIDHI 1000 / RAWSIGNAL_SAMPLE_RATE 43 | #define FA20_PULSEMIN 1000 / RAWSIGNAL_SAMPLE_RATE 44 | #define FA20_PULSEMINMAX 1500 / RAWSIGNAL_SAMPLE_RATE 45 | #define FA20_PULSEMAXMIN 2000 / RAWSIGNAL_SAMPLE_RATE 46 | #define FA20_PULSEMAX 2800 / RAWSIGNAL_SAMPLE_RATE 47 | 48 | #ifdef PLUGIN_080 49 | #include "../4_Display.h" 50 | 51 | boolean Plugin_080(byte function, char *string) 52 | { 53 | if (RawSignal.Number != FA20_PULSECOUNT) 54 | return false; 55 | 56 | unsigned long bitstream = 0L; 57 | //================================================================================== 58 | // Get all 24 bits 59 | //================================================================================== 60 | for (byte x = 4; x < FA20_PULSECOUNT; x += 2) 61 | { 62 | if (RawSignal.Pulses[x - 1] > FA20_MIDHI) 63 | return false; // every preceding pulse must be below 1000! 64 | 65 | bitstream <<= 1; 66 | 67 | if (RawSignal.Pulses[x] > FA20_PULSEMAXMIN) 68 | { // long pulse 69 | if (RawSignal.Pulses[x] > FA20_PULSEMAX) 70 | return false; // long pulse too long 71 | bitstream |= 0x1; 72 | } 73 | else 74 | { 75 | if (RawSignal.Pulses[x] > FA20_PULSEMINMAX) 76 | return false; // short pulse too long 77 | if (RawSignal.Pulses[x] < FA20_PULSEMIN) 78 | return false; // short pulse too short 79 | // bitstream |= 0x0; 80 | } 81 | } 82 | //================================================================================== 83 | // Perform a quick sanity check 84 | //================================================================================== 85 | if (bitstream == 0) 86 | return false; 87 | if (bitstream == 0xFFFFFF) 88 | return false; 89 | if ((bitstream & 0xFFFF) == 0xFFFF) 90 | return false; 91 | //================================================================================== 92 | // Output 93 | //================================================================================== 94 | display_Header(); 95 | display_Name(PSTR("FA20RF")); 96 | display_IDn(bitstream, 6); 97 | display_SMOKEALERT(SMOKE_On); 98 | display_Footer(); 99 | //================================================================================== 100 | RawSignal.Repeats = true; // suppress repeats of the same RF packet 101 | RawSignal.Number = 0; // do not process the packet any further 102 | return true; 103 | } 104 | #endif // PLUGIN_080 105 | 106 | #ifdef PLUGIN_TX_080 107 | #define FA20RFSTART 3000 // 8000 108 | #define FA20RFSPACE 675 // 800 109 | #define FA20RFLOW 1250 // 1300 110 | #define FA20RFHIGH 2550 // 2600 111 | 112 | boolean PluginTX_080(byte function, char *string) 113 | { 114 | boolean success = false; 115 | //10;FA20RF;67f570;1;ON; 116 | //012345678901234567890 117 | unsigned long bitstream = 0; 118 | if (strncasecmp(InputBuffer_Serial + 3, "FA20RF;", 7) == 0) 119 | { // KAKU Command eg. 120 | if (InputBuffer_Serial[18] != ';') 121 | return false; 122 | InputBuffer_Serial[8] = 0x30; 123 | InputBuffer_Serial[9] = 0x78; 124 | InputBuffer_Serial[16] = 0; 125 | bitstream = str2int(InputBuffer_Serial + 8); 126 | byte cmd = str2cmd(InputBuffer_Serial + 19); // ON/OFF 127 | if (cmd != VALUE_ON) 128 | return true; // pretend command was ok but we dont have to send anything.. 129 | // ---------- SMOKEALERT SEND ----------- 130 | RawSignal.Multiply = 50; 131 | RawSignal.Repeats = 10; 132 | RawSignal.Delay = 20; 133 | RawSignal.Pulses[1] = FA20RFSTART / RawSignal.Multiply; 134 | //RawSignal.Pulses[2]=FA20RFSPACE/RawSignal.Multiply; 135 | //RawSignal.Pulses[3]=FA20RFSPACE/RawSignal.Multiply; 136 | RawSignal.Pulses[2] = (FA20RFSPACE + 125) / RawSignal.Multiply; 137 | RawSignal.Pulses[3] = (FA20RFSPACE + 25) / RawSignal.Multiply; 138 | for (byte x = 49; x >= 3; x = x - 2) 139 | { 140 | RawSignal.Pulses[x] = FA20RFSPACE / RawSignal.Multiply; 141 | if ((bitstream & 1) == 1) 142 | RawSignal.Pulses[x + 1] = FA20RFHIGH / RawSignal.Multiply; 143 | else 144 | RawSignal.Pulses[x + 1] = FA20RFLOW / RawSignal.Multiply; 145 | bitstream = bitstream >> 1; 146 | } 147 | RawSignal.Pulses[51] = FA20RFSPACE / RawSignal.Multiply; 148 | RawSignal.Pulses[52] = 0; 149 | RawSignal.Number = 52; 150 | RawSendRF(); 151 | RawSignal.Multiply = RAWSIGNAL_SAMPLE_RATE; // restore setting 152 | success = true; 153 | } 154 | return success; 155 | } 156 | #endif // PLUGIN_080 157 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_250.old: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-250: Addons ## 4 | //####################################################################################################### 5 | 6 | /*********************************************************************************************\ 7 | * This plugin takes care of addons for Nodo Small boards 8 | * 9 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 10 | * Support (present) : https://github.com/couin3/RFLink 11 | * Author (original) : esp8266nu 2016? RFLink 1.0 12 | * Support (original) : http://www.esp8266.nu/forum 13 | * License : This code is free for use in any open source project when this header is included. 14 | * Usage of any parts of this code in a commercial application is prohibited! 15 | ***********************************************************************************************/ 16 | 17 | #ifdef PLUGIN_TX_250 18 | #include "../4_Display.h" 19 | 20 | // prototyping functions 21 | byte Plugin_250_GetArgv(char *, char *, int); 22 | unsigned long Plugin_250_FreeMem(void); 23 | void Plugin_250_Beep(int, int); 24 | 25 | boolean Plugin_250(byte function, char *string) 26 | { 27 | return false; 28 | } 29 | 30 | boolean PluginTX_250(byte function, char *string) 31 | { 32 | boolean success = false; 33 | char TmpStr1[80]; 34 | TmpStr1[0] = 0; 35 | long Par1 = 0; 36 | long Par2 = 0; 37 | if (Plugin_250_GetArgv(string, TmpStr1, 3)) 38 | Par1 = atol(TmpStr1); 39 | if (Plugin_250_GetArgv(string, TmpStr1, 4)) 40 | Par2 = atol(TmpStr1); 41 | 42 | if (strncasecmp_P(InputBuffer_Serial + 3, PSTR("FREEMEM"), 7) == 0) 43 | { 44 | Serial.println(Plugin_250_FreeMem()); 45 | success = true; 46 | } 47 | 48 | if (strncasecmp_P(InputBuffer_Serial + 3, PSTR("SOUND"), 5) == 0) 49 | { 50 | if (Par2 < 10000) 51 | { 52 | pinMode(PIN_SPEAKER, OUTPUT); 53 | Plugin_250_Beep(Par1, Par2); 54 | } 55 | success = true; 56 | } 57 | 58 | if (strncasecmp_P(InputBuffer_Serial + 3, PSTR("GPIO"), 4) == 0) 59 | { 60 | if (Par1 >= 7 && Par1 <= 10) 61 | { 62 | pinMode(Par1, OUTPUT); 63 | digitalWrite(Par1, Par2); 64 | } 65 | success = true; 66 | } 67 | 68 | if (strncasecmp_P(InputBuffer_Serial + 3, PSTR("STATUS"), 6) == 0) 69 | { 70 | int state = 0; 71 | if (Par1 >= 0 && Par1 <= 3) 72 | state = analogRead(Par1); 73 | if (Par1 >= 7 && Par1 <= 10) 74 | state = digitalRead(Par1); 75 | sprintf_P(pbuffer, PSTR("20;%02X;ESPEASY;PinValue%u"), PKSequenceNumber++, Par1); 76 | Serial.print(pbuffer); 77 | sprintf(pbuffer, "=%u", state); 78 | Serial.println(pbuffer); 79 | success = true; 80 | } 81 | 82 | return success; 83 | } 84 | 85 | void Plugin_250_Scan() 86 | { 87 | static unsigned long timer; 88 | if (millis() - timer > 100) 89 | { 90 | // add timer logic for reporting ana 91 | timer = millis(); 92 | } 93 | } 94 | 95 | byte Plugin_250_GetArgv(char *string, char *argv, int argc) 96 | { 97 | int string_pos = 0, argv_pos = 0, argc_pos = 0; 98 | char c, d; 99 | 100 | while (string_pos < strlen(string)) 101 | { 102 | c = string[string_pos]; 103 | d = string[string_pos + 1]; 104 | 105 | if (c == ' ' && d == ' ') 106 | { 107 | } 108 | else if (c == ' ' && d == ';') 109 | { 110 | } 111 | else if (c == ';' && d == ' ') 112 | { 113 | } 114 | else if (c == ' ' && d >= 33 && d <= 126) 115 | { 116 | } 117 | else if (c == ';' && d >= 33 && d <= 126) 118 | { 119 | } 120 | else 121 | { 122 | if (c != ' ' && c != ';') 123 | { 124 | argv[argv_pos++] = c; 125 | argv[argv_pos] = 0; 126 | } 127 | 128 | if (d == ' ' || d == ';' || d == 0) 129 | { 130 | // Bezig met toevoegen van tekens aan een argument, maar er kwam een scheidingsteken. 131 | argv[argv_pos] = 0; 132 | argc_pos++; 133 | 134 | if (argc_pos == argc) 135 | return string_pos + 1; 136 | 137 | argv[0] = 0; 138 | argv_pos = 0; 139 | string_pos++; 140 | } 141 | } 142 | string_pos++; 143 | } 144 | return 0; 145 | } 146 | 147 | uint8_t *heapptr, *stackptr; 148 | unsigned long Plugin_250_FreeMem(void) 149 | { 150 | stackptr = (uint8_t *)malloc(4); // use stackptr temporarily 151 | heapptr = stackptr; // save value of heap pointer 152 | free(stackptr); // free up the memory again (sets stackptr to 0) 153 | stackptr = (uint8_t *)(SP); // save value of stack pointer 154 | return (stackptr - heapptr); 155 | } 156 | 157 | void Plugin_250_Beep(int frequency, int duration) //Herz,millisec 158 | { 159 | long halfperiod = 500000L / frequency; 160 | long loops = (long)duration * frequency / (long)1000; 161 | 162 | for (loops; loops > 0; loops--) 163 | { 164 | digitalWrite(PIN_SPEAKER, HIGH); 165 | delayMicroseconds(halfperiod); 166 | digitalWrite(PIN_SPEAKER, LOW); 167 | delayMicroseconds(halfperiod); 168 | } 169 | } 170 | 171 | #endif // Plugin_TX_250 172 | -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_251.old: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //#################################### Plugin-251 4-voudige PulseCounter ################################ 3 | //####################################################################################################### 4 | 5 | /*********************************************************************************************\ 6 | * Dit device zorgt voor ondersteuning van een 4-voudige pulsteller met 1 enkele Nodo Mega of Small. 7 | * Is vooral bedoeld als "Meterkast Slave" unit voor het meten van zowel Gas, Elektra en Water met 1 Nodo. 8 | * 9 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 10 | * Support (present) : https://github.com/couin3/RFLink 11 | * Author (original) : esp8266nu 1 Okt 2016 RFLink 1.0 12 | * Support (original) : www.esp8266.nu 13 | * License : This code is free for use in any open source project when this header is included. 14 | * Usage of any parts of this code in a commercial application is prohibited! 15 | *********************************************************************************************** 16 | * Technische beschrijving: 17 | * We gebruiken de Nodo WiredIn aansluitingen als digitale pulstellers. 18 | * Het is n.l. mogelijk om de diverse Atmel pinnen voor alternatieve functies te gebruiken. 19 | * De WiredIn pinnen zijn standaard analoog, maar ook digitaal te gebruiken en daar maken we gebruik van. 20 | * Met dit device is het mogelijk om ook zeer korte pulsen te tellen, hetgeen met de normale Nodo WiredIn functie niet lukt. 21 | * Dit device gebruikt twee variabelen voor elke pulsteller, 1 voor de pulsecount en 1 voor de pulsetime 22 | * Deze variabelen worden alleen gebruikt na het geven van het commando pulse x,y 23 | \*********************************************************************************************/ 24 | 25 | #include "Arduino.h" 26 | // #include 27 | 28 | #ifdef PLUGIN_TX_251 29 | #include "../4_Display.h" 30 | 31 | void SetPinIRQ(byte _receivePin); 32 | inline void pulse_handle_interrupt(); 33 | boolean plugin_251_init = false; 34 | 35 | volatile uint8_t *_receivePortRegister; 36 | volatile unsigned long PulseCounter[4] = {0, 0, 0, 0}; 37 | volatile unsigned long PulseTimer[4] = {0, 0, 0, 0}; 38 | volatile unsigned long PulseTimerPrevious[4] = {0, 0, 0, 0}; 39 | volatile byte PulseState[4] = {0, 0, 0, 0}; 40 | 41 | boolean Plugin_251(byte function, char *string) 42 | { 43 | return false; 44 | } 45 | 46 | boolean PluginTX_251(byte function, char *string) 47 | { 48 | boolean success = false; 49 | char TmpStr1[80]; 50 | TmpStr1[0] = 0; 51 | long Par1 = 0; 52 | long Par2 = 0; 53 | if (Plugin_250_GetArgv(string, TmpStr1, 3)) 54 | Par1 = atol(TmpStr1); 55 | if (Plugin_250_GetArgv(string, TmpStr1, 4)) 56 | Par2 = atol(TmpStr1); 57 | 58 | if (strncasecmp_P(InputBuffer_Serial + 3, PSTR("COUNT"), 5) == 0) 59 | { 60 | if (!plugin_251_init) 61 | { 62 | SetPinIRQ(A0); 63 | SetPinIRQ(A1); 64 | SetPinIRQ(A2); 65 | SetPinIRQ(A3); 66 | } 67 | 68 | // Store countervalue into uservar and reset internal counter 69 | unsigned long counter = PulseCounter[Par1 - 1]; 70 | PulseCounter[Par1 - 1] = 0; 71 | 72 | // If actual time difference > last known pulstime, update pulstimer now. 73 | if ((millis() - PulseTimerPrevious[Par1 - 1]) > PulseTimer[Par1 - 1]) 74 | PulseTimer[Par1 - 1] = millis() - PulseTimerPrevious[Par1 - 1]; 75 | 76 | if (PulseTimer[Par1 - 1] > 999999) 77 | PulseTimer[Par1 - 1] = 999999; // WebApp cannot handle larger values! (bug or by design?) 78 | 79 | sprintf(pbuffer, "20;%02X;ESPEASY;PulseCount%u", PKSequenceNumber++, Par1); 80 | Serial.print(pbuffer); 81 | sprintf(pbuffer, "=%u", counter); 82 | Serial.println(pbuffer); 83 | 84 | delay(200); 85 | unsigned long time = PulseTimer[Par1 - 1]; 86 | sprintf(pbuffer, "20;%02X;ESPEASY;PulseTime%u", PKSequenceNumber++, Par1); 87 | Serial.print(pbuffer); 88 | sprintf(pbuffer, "=%u", time); 89 | Serial.println(pbuffer); 90 | 91 | success = true; 92 | } 93 | 94 | return success; 95 | } 96 | 97 | void SetPinIRQ(byte _receivePin) 98 | { 99 | uint8_t _receiveBitMask; 100 | pinMode(_receivePin, INPUT); 101 | digitalWrite(_receivePin, HIGH); 102 | _receiveBitMask = digitalPinToBitMask(_receivePin); 103 | uint8_t port = digitalPinToPort(_receivePin); 104 | _receivePortRegister = portInputRegister(port); 105 | if (digitalPinToPCICR(_receivePin)) 106 | { 107 | *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); 108 | *digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin)); 109 | } 110 | } 111 | 112 | /*********************************************************************/ 113 | inline void pulse_handle_interrupt() 114 | /*********************************************************************/ 115 | { 116 | byte portstate = *_receivePortRegister & 0xf; 117 | for (byte x = 0; x < 4; x++) 118 | { 119 | if ((portstate & (1 << x)) == 0) 120 | { 121 | if (PulseState[x] == 1) 122 | { 123 | PulseCounter[x]++; 124 | PulseTimer[x] = millis() - PulseTimerPrevious[x]; 125 | PulseTimerPrevious[x] = millis(); 126 | } 127 | PulseState[x] = 0; 128 | } 129 | else 130 | PulseState[x] = 1; 131 | } 132 | } 133 | 134 | #if defined(PCINT1_vect) 135 | ISR(PCINT1_vect) 136 | { 137 | pulse_handle_interrupt(); 138 | } 139 | #endif 140 | #if defined(PCINT2_vect) 141 | ISR(PCINT2_vect) 142 | { 143 | pulse_handle_interrupt(); 144 | } 145 | #endif 146 | 147 | #endif // Plugin_TX_251 -------------------------------------------------------------------------------- /RFLink/Plugins/Plugin_254.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-254: Signal Analyzer ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin shows pulse lengths that have been received on RF and have not been decoded by 7 | * one of the other plugins. The primary use of this plugin is to provide an easy way to debug and 8 | * analyse currently unsupported RF signals 9 | * 10 | * Author (present) : StormTeam 2018..2020 - Marc RIVES (aka Couin3) 11 | * Support (present) : https://github.com/couin3/RFLink 12 | * Author (original) : StuntTeam 2015..2016 13 | * Support (original) : http://sourceforge.net/projects/rflink/ 14 | * License : This code is free for use in any open source project when this header is included. 15 | * Usage of any parts of this code in a commercial application is prohibited! 16 | *********************************************************************************************** 17 | * Technical description: 18 | * This plugin just outputs unsupported RF packets, use this plugin to find signals from new devices 19 | * Even if you do not know what to do with the data yourself you might want to share your data so 20 | * others can analyse it. 21 | \*********************************************************************************************/ 22 | #define P254_PLUGIN_ID 254 23 | #define PLUGIN_DESC_254 "Unidentified Packet debugging" 24 | 25 | #ifdef PLUGIN_254 26 | #include "../4_Display.h" 27 | 28 | boolean Plugin_254(byte function, char *string) 29 | { 30 | int i; 31 | 32 | if ((RFUDebug == false) && (QRFUDebug == false)) // debug is on? 33 | return false; 34 | 35 | if (RawSignal.Number < 24) // make sure the packet is long enough to have a meaning 36 | return false; 37 | 38 | // ---------------------------------- 39 | // Output 40 | // ---------------------------------- 41 | display_Header(); 42 | display_Name(PSTR("DEBUG")); 43 | display_Footer(); 44 | // ---------------------------------- 45 | Serial.print(F("20;XX;DEBUG;Pulses=")); // debug data 46 | Serial.print(RawSignal.Number); // print number of pulses 47 | Serial.print(F(";Pulses(uSec)=")); // print pulse durations 48 | // ---------------------------------- 49 | char dbuffer[3]; 50 | 51 | for (i = 1; i < RawSignal.Number + 1; i++) 52 | { 53 | if (QRFUDebug == true) 54 | { 55 | sprintf(dbuffer, "%02x", RawSignal.Pulses[i]); 56 | Serial.print(dbuffer); 57 | } 58 | else 59 | { 60 | Serial.print(RawSignal.Pulses[i] * RAWSIGNAL_SAMPLE_RATE); 61 | if (i < RawSignal.Number) 62 | Serial.write(','); 63 | } 64 | } 65 | Serial.print(F(";\r\n")); 66 | // ---------------------------------- 67 | RawSignal.Number = 0; // Last plugin, kill packet 68 | return true; // stop processing 69 | } 70 | #endif // PLUGIN_254 71 | -------------------------------------------------------------------------------- /RFLink/Plugins/_Plugin_Config_01.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | // **************************************************************************************************************************************** 9 | // RFLink List of Plugins 10 | // **************************************************************************************************************************************** 11 | // Here are all plugins listed that are supported and used after compilation. 12 | // When needed additional plugins can be added or selected plugins can be enabled/disabled. 13 | // 14 | // BEWARE OF THE PLUGIN_MAX setting!! TX: 51 RX: 24 15 | // **************************************************************************************************************************************** 16 | // Translation Plugin for oversized packets due to their breaks/pause being too short between packets 17 | // Used for Flamingo FA500R and various others, do NOT exclude this plugin. 18 | #define PLUGIN_001 // DO NOT CHANGE OR EXCLUDE!! 19 | // ------------------------------------------------------------------------ 20 | // -- Any of the following protocols can be excluded whenever not needed -- 21 | // ------------------------------------------------------------------------ 22 | #define PLUGIN_002 // Lacrosse v2 2300/3600 23 | #define PLUGIN_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC 24 | #define PLUGIN_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno. 25 | #define PLUGIN_005 // Eurodomest 26 | #define PLUGIN_006 // Blyss 27 | #define PLUGIN_007 // Conrad RSL2 28 | #define PLUGIN_008 // Kambrook 29 | #define PLUGIN_009 // X10 RF 30 | #define PLUGIN_010 // TRC02 RGB Switch 31 | #define PLUGIN_011 // Home Confort 32 | #define PLUGIN_012 // Flamingo FA500R 33 | #define PLUGIN_013 // Powerfix/Quigg 34 | #define PLUGIN_014 // Ikea Koppla 35 | #define PLUGIN_015 // Home Easy EU 36 | // ------------------- 37 | // Weather sensors 38 | // ------------------- 39 | #define PLUGIN_029 // Alecto V2 (WS3000/DWK2012) 434 MHz. 40 | #define PLUGIN_030 // Alecto V1 (WS3500) 434 MHz. 41 | #define PLUGIN_031 // Alecto V3 (WS1100/WS1200/WSD-19) 433.9 MHz. 42 | #define PLUGIN_032 // Alecto V4 43 | #define PLUGIN_033 // Conrad Pool Thermometer 44 | #define PLUGIN_034 // Cresta 45 | #define PLUGIN_035 // Imagintronix 46 | #define PLUGIN_036 // F007_TH 47 | #define PLUGIN_037 // Accurite 986 Thermometer 48 | #define PLUGIN_040 // Mebus 49 | #define PLUGIN_041 // LaCrosse v3 ws7000 50 | #define PLUGIN_042 // UPM/Esic 51 | #define PLUGIN_043 // LaCrosse v1 52 | #define PLUGIN_044 // Auriol v3 53 | #define PLUGIN_045 // Auriol 54 | #define PLUGIN_046 // Auriol v2 / Xiron 55 | #define PLUGIN_047 // Auriol v4 56 | // ------------------- 57 | // Motion Sensors, include when needed 58 | // ------------------- 59 | #define PLUGIN_060 // Ajax Chubb Varel 433 MHz. motion sensors 60 | #define PLUGIN_061 // Chinese PIR motion door and window sensors 61 | #define PLUGIN_062 // Chuango Alarm Devices 62 | #define PLUGIN_063 // Oregon PIR/ALARM/LIGHT 63 | #define PLUGIN_064 // Atlantic (and Visonic) 64 | #define PLUGIN_065 // custom garage doors 65 | // ------------------- 66 | // Doorbells 67 | // ------------------- 68 | #define PLUGIN_070 // Select Plus (Action - Quhwa) 69 | #define PLUGIN_071 // Plieger York 70 | #define PLUGIN_072 // Byron SX doorbell 71 | #define PLUGIN_073 // Deltronic doorbell 72 | #define PLUGIN_074 // RL02 73 | #define PLUGIN_075 // Silvercrest 74 | // ------------------- 75 | // Smoke detectors / Fire Places 76 | // ------------------- 77 | #define PLUGIN_080 // Flamingo FA20 / KD101 smoke detector 78 | #define PLUGIN_081 // Mertik Maxitrol / Dru fireplace 79 | #define PLUGIN_082 // Mertik Maxitrol / Dru fireplace 80 | // ------------------- 81 | // Misc 82 | // ------------------- 83 | // ------------------- 84 | // 868 MHZ 85 | // ------------------- 86 | // ------------------- 87 | // Housekeeping 88 | // ------------------- 89 | #define PLUGIN_254 // Debug to show unsupported packets 90 | // **************************************************************************************************************************************** 91 | // RFLink List of Plugins that have TRANSMIT functionality 92 | // **************************************************************************************************************************************** 93 | // Here are all plugins listed that are supported and used after compilation. 94 | // When needed additional plugins can be added or selected plugins can be enabled/disabled. 95 | // **************************************************************************************************************************************** 96 | // ------------------------------------------------------------------------ 97 | // -- Any of the following protocols can be excluded whenever not needed -- 98 | // ------------------------------------------------------------------------ 99 | // #define PLUGIN_TX_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC 100 | #define PLUGIN_TX_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno. 101 | // #define PLUGIN_TX_005 // Eurodomest 102 | // #define PLUGIN_TX_006 // Blyss 103 | // #define PLUGIN_TX_007 // Conrad RSL2 104 | // #define PLUGIN_TX_008 // Kambrook 105 | // #define PLUGIN_TX_009 // X10 RF 106 | // #define PLUGIN_TX_010 // TRC02 RGB switch 107 | // #define PLUGIN_TX_011 // Home Confort 108 | // #define PLUGIN_TX_012 // Flamingo FA500R (11) 109 | // #define PLUGIN_TX_013 // Powerfix/Quigg 110 | // #define PLUGIN_TX_015 // Home Easy EU (14) 111 | // ------------------- 112 | // Doorbells 113 | // ------------------- 114 | // #define PLUGIN_TX_070 // Select Plus (Action - Quhwa) 115 | // #define PLUGIN_TX_072 // Byron SX doorbell 116 | // #define PLUGIN_TX_073 // Deltronic doorbell 117 | // #define PLUGIN_TX_074 // RL02 118 | // ------------------- 119 | // Smoke detectors 120 | // ------------------- 121 | // #define PLUGIN_TX_080 // Flamingo FA20 / KD101 smoke detector 122 | // #define PLUGIN_TX_082 // Mertik Maxitrol / Dru fireplace 123 | // ------------------- 124 | // -=#=- 125 | // ------------------- 126 | -------------------------------------------------------------------------------- /RFLink/RFLink.h: -------------------------------------------------------------------------------- 1 | // ************************************* // 2 | // * Arduino Project RFLink-esp * // 3 | // * https://github.com/couin3/RFLink * // 4 | // * 2018..2020 Stormteam - Marc RIVES * // 5 | // * More details in RFLink.ino file * // 6 | // ************************************* // 7 | 8 | #ifndef RFLink_h 9 | #define RFLink_h 10 | 11 | #define BUILDNR 0x05 // 0x07 // shown in version 12 | #define REVNR 0x01 // 0X42 // shown in version and startup string 13 | 14 | #define SERIAL_ENABLED // Send RFLink messages over Serial 15 | 16 | #if (defined(ESP32) || defined(ESP8266)) 17 | // OLED display, 0.91" SSD1306 I2C 18 | // #define OLED_ENABLED 19 | #define OLED_CONTRAST 32 // default 255 (max) 20 | #define OLED_FLIP true // default false 21 | 22 | // WIFI 23 | #define WIFI_PWR_0 20 // 0~20.5dBm 24 | 25 | // MQTT messages 26 | #define MQTT_ENABLED // Send RFLink messages over MQTT 27 | #define MQTT_LOOP_MS 1000 // MQTTClient.loop(); call period (in mSec) 28 | #define MQTT_RETAINED_0 false // Retained option 29 | #define MQTT_LWT // Let know if Module is Online or Offline via MQTT Last Will message 30 | // #define MQTT_SSL // Send MQTT messages over SSL 31 | // #define CHECK_CACERT // Send MQTT SSL CA Certificate 32 | #endif 33 | 34 | // Debug default 35 | #define RFDebug_0 false // debug RF signals with plugin 001 (no decode) 36 | #define QRFDebug_0 false // debug RF signals with plugin 001 but no multiplication (faster?, compact) 37 | #define RFUDebug_0 false // debug RF signals with plugin 254 (decode 1st) 38 | #define QRFUDebug_0 false // debug RF signals with plugin 254 but no multiplication (faster?, compact) 39 | 40 | void CallReboot(void); 41 | 42 | #endif -------------------------------------------------------------------------------- /RFLink/RFLink.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************************************************************* 2 | // * Arduino Project RFLink-esp https://github.com/couin3/RFLink (Branch esp) 3 | // * Portions Free Software 2018..2020 StormTeam - Marc RIVES 4 | // * Portions Free Software 2015..2016 StuntTeam - (RFLink R29~R33) 5 | // * Portions © Copyright 2010..2015 Paul Tonkes (original Nodo 3.7 code) 6 | // * 7 | // * RFLink-esp 8 | // * 9 | // ******************************************************************************************************************************** 10 | // * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 11 | // * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 12 | // * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 13 | // * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | // * You received a copy of the GNU General Public License along with this program in file 'COPYING.TXT'. 15 | // * For more information on GPL licensing: http://www.gnu.org/licenses 16 | // ******************************************************************************************************************************** 17 | 18 | // **************************************************************************** 19 | #include 20 | #include "RFLink.h" 21 | #include "1_Radio.h" 22 | #include "2_Signal.h" 23 | #include "3_Serial.h" 24 | #include "4_Display.h" 25 | #include "5_Plugin.h" 26 | #include "6_WiFi_MQTT.h" 27 | #include "8_OLED.h" 28 | 29 | #if (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)) 30 | #include 31 | #endif 32 | //**************************************************************************************************************************************** 33 | void sendMsg(); // See at bottom 34 | 35 | #if (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)) 36 | void (*Reboot)(void) = 0; // reset function on adress 0. 37 | 38 | void CallReboot(void) 39 | { 40 | sendMsg(); 41 | delay(1); 42 | Reboot(); 43 | } 44 | #endif 45 | 46 | #if (defined(ESP8266) || defined(ESP32)) 47 | void CallReboot(void) 48 | { 49 | sendMsg(); 50 | delay(1); 51 | ESP.restart(); 52 | } 53 | #endif 54 | 55 | void setup() 56 | { 57 | #if (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__)) 58 | // Low Power Arduino 59 | ADCSRA = 0; // disable ADC 60 | power_all_disable(); // turn off all modules 61 | power_timer0_enable(); // Timer 0 62 | power_usart0_enable(); // UART 63 | delay(250); // Wait ESP-01S 64 | #ifdef RFM69_ENABLED 65 | power_spi_enable(); // SPI 66 | #endif 67 | #elif defined(ESP32) 68 | btStop(); 69 | #endif 70 | 71 | delay(250); // Time needed to switch back from Upload to Console 72 | Serial.begin(BAUD); // Initialise the serial port 73 | 74 | #if (defined(ESP32) || defined(ESP8266)) 75 | Serial.println(); // ESP "Garbage" message 76 | Serial.print(F("Arduino IDE Version :\t")); 77 | Serial.println(ARDUINO); 78 | #ifdef ESP8266 79 | Serial.print(F("ESP CoreVersion :\t")); 80 | Serial.println(ESP.getCoreVersion()); 81 | #endif // ESP8266 82 | Serial.print(F("Sketch File :\t\t")); 83 | Serial.println(__FILE__); // "RFLink.ino" version is in 20;00 Message 84 | Serial.println(F("Compiled on :\t\t" __DATE__ " at " __TIME__)); 85 | 86 | #ifdef MQTT_ENABLED 87 | setup_WIFI(); 88 | start_WIFI(); 89 | setup_MQTT(); 90 | reconnect(); 91 | #else 92 | setup_WIFI_OFF(); 93 | #endif // MQTT_ENABLED 94 | #endif // ESP32 || ESP8266 95 | 96 | PluginInit(); 97 | PluginTXInit(); 98 | set_Radio_mode(Radio_OFF); 99 | 100 | #if ((defined(ESP8266) || defined(ESP32)) && !defined(RFM69_ENABLED)) 101 | show_Radio_Pin(); 102 | #endif // ESP8266 || ESP32 103 | 104 | #ifdef OLED_ENABLED 105 | setup_OLED(); 106 | #endif 107 | 108 | display_Header(); 109 | display_Splash(); 110 | display_Footer(); 111 | 112 | #ifdef SERIAL_ENABLED 113 | Serial.print(pbuffer); 114 | #endif 115 | #ifdef OLED_ENABLED 116 | splash_OLED(); 117 | #endif 118 | #ifdef MQTT_ENABLED 119 | publishMsg(); 120 | #endif 121 | pbuffer[0] = 0; 122 | set_Radio_mode(Radio_RX); 123 | } 124 | 125 | void loop() 126 | { 127 | #ifdef MQTT_ENABLED 128 | checkMQTTloop(); 129 | sendMsg(); 130 | #endif 131 | 132 | #ifdef SERIAL_ENABLED 133 | #if PIN_RF_TX_DATA_0 != NOT_A_PIN 134 | if (CheckSerial()) 135 | sendMsg(); 136 | #endif 137 | #endif 138 | if (ScanEvent()) 139 | sendMsg(); 140 | } 141 | 142 | void sendMsg() 143 | { 144 | if (pbuffer[0] != 0) 145 | { 146 | #ifdef SERIAL_ENABLED 147 | Serial.print(pbuffer); 148 | #endif 149 | #ifdef MQTT_ENABLED 150 | publishMsg(); 151 | #endif 152 | #ifdef OLED_ENABLED 153 | print_OLED(); 154 | #endif 155 | pbuffer[0] = 0; 156 | } 157 | } 158 | 159 | /*********************************************************************************************/ -------------------------------------------------------------------------------- /include/dummy.txt: -------------------------------------------------------------------------------- 1 | include folder may be required by PlatformIO -------------------------------------------------------------------------------- /pictures/RFLink-ESP_OLED.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/pictures/RFLink-ESP_OLED.jpg -------------------------------------------------------------------------------- /pictures/RFLink-ESP_OLED_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/pictures/RFLink-ESP_OLED_2.jpg -------------------------------------------------------------------------------- /pictures/RFLink-ESP_Pinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/pictures/RFLink-ESP_Pinout.jpg -------------------------------------------------------------------------------- /pictures/RFLink-ESP_RXB6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/pictures/RFLink-ESP_RXB6.jpg -------------------------------------------------------------------------------- /pictures/RFLink-ESP_Receivers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couin3/RFLink/e55d202a1e60aab70bf45d4b2e8e19bf20730b73/pictures/RFLink-ESP_Receivers.jpg -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | src_dir = RFLink 13 | 14 | [env] 15 | framework = arduino 16 | monitor_speed = 921600 17 | lib_ldf_mode = chain+ 18 | 19 | [common] 20 | ESPlibs = 21 | PubSubClient 22 | 23 | OLEDlibs = 24 | Wire 25 | U8g2 26 | 27 | [env:doitESP32] 28 | platform = espressif32 29 | board = esp32doit-devkit-v1 30 | ;board_build.f_cpu = 240000000L 31 | board_build.f_cpu = 160000000L 32 | ;board_build.f_cpu = 80000000L 33 | board_build.f_flash = 40000000L 34 | board_build.flash_mode = dio 35 | upload_speed = 921600 36 | lib_deps = ${common.ESPlibs} 37 | lib_ignore = ${common.OLEDlibs} 38 | 39 | ;[env:d1_mini] 40 | ;platform = espressif8266 41 | ;board = d1_mini 42 | ;upload_speed = 921600 43 | ;lib_deps = ${common.ESPlibs} 44 | ; ESP8266WiFi 45 | ;lib_ignore = ${common.OLEDlibs} 46 | 47 | ;[env:nodemcuv2] 48 | ;platform = espressif8266 49 | ;board = nodemcuv2 50 | ;upload_speed = 256000 51 | ;lib_deps = ${common.ESPlibs} 52 | ; ESP8266WiFi 53 | ;lib_ignore = ${common.OLEDlibs} 54 | ;upload_protocol = espota 55 | ;upload_port = 192.168.1.86 56 | 57 | ;[env:arduino_uno] 58 | ;platform = atmelavr 59 | ;board = uno 60 | ;;board_build.f_cpu = 8000000L 61 | ;lib_deps = 62 | ;lib_ignore = ${common.ESPlibs} ${common.OLEDlibs} 63 | 64 | ;[env:arduino_nano] 65 | ;platform = atmelavr 66 | ;board = nanoatmega328 67 | ;;board_build.f_cpu = 8000000L 68 | ;lib_ignore = ${common.ESPlibs} ${common.OLEDlibs} 69 | 70 | ;[env:arduino_promini8] 71 | ;platform = atmelavr 72 | ;board = pro8MHzatmega328 73 | ;lib_ignore = ${common.ESPlibs} ${common.OLEDlibs} 74 | 75 | ;[env:arduino_mega] 76 | ;platform = atmelavr 77 | ;board = megaatmega2560 78 | ;lib_ignore = ${common.ESPlibs} ${common.OLEDlibs} 79 | --------------------------------------------------------------------------------