├── License.txt ├── Doc ├── RFLink Schematic.jpg ├── Readme_Loader.txt ├── RFLink Protocol Reference.txt └── Supported Device List.txt ├── RFLink.ino ├── README.md ├── Misc.ino ├── Plugins ├── Plugin_254.c ├── Plugin_060.c ├── Plugin_062.c ├── Plugin_063.c ├── Plugin_033.c ├── Plugin_061.c ├── Plugin_071.c ├── Plugin_044.c ├── Plugin_035.c ├── Plugin_045.c ├── Plugin_080.c ├── Plugin_014.c ├── Plugin_032.c ├── Plugin_040.c ├── Plugin_046.c ├── Plugin_100.c ├── Plugin_075.c ├── Plugin_073.c ├── Plugin_082.c ├── Plugin_081.c ├── Plugin_070.c ├── Plugin_031.c ├── Plugin_074.c ├── Plugin_005.c └── Plugin_072.c ├── Config └── Config_01.c └── RawSignal.ino /License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jwdb/rflink/HEAD/License.txt -------------------------------------------------------------------------------- /Doc/RFLink Schematic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jwdb/rflink/HEAD/Doc/RFLink Schematic.jpg -------------------------------------------------------------------------------- /Doc/Readme_Loader.txt: -------------------------------------------------------------------------------- 1 | RFLink Loader Version 1.02 2 | 3 | 4 | The RFLink Loader program runs on Windows and can program an Arduino Mega 2560 board 5 | with the RFLink software. 6 | You do not need any Arduino IDE/Compiler etc. 7 | 8 | 9 | Steps: 10 | ------ 11 | - Launch the program 12 | - Select the file you want to program (rflink.cpp.hex) 13 | - Select the serial port to which the Arduino is connected. 14 | - Hit the "program" button and wait for the process to finish. 15 | 16 | 17 | 18 | History: 19 | -------- 20 | 1.02 Fixed: could not use serial ports > 9 21 | 1.01 Fixed: could not load the hex file if the path name contained a space 22 | Added: test serial port availability before trying to program the Arduino 23 | 1.00 Initial Release 24 | -------------------------------------------------------------------------------- /RFLink.ino: -------------------------------------------------------------------------------- 1 | // ********************************************************************************************************************************* 2 | // * Arduino project "Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1" 3 | // * © Copyright 2015 StuntTeam - NodoRFLink 4 | // * Portions © Copyright 2010..2015 Paul Tonkes (original Nodo 3.7 code) 5 | // * 6 | // * Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1 7 | // * 8 | // ******************************************************************************************************************************** 9 | // * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 10 | // * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 11 | // * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 12 | // * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | // * You received a copy of the GNU General Public License along with this program in file 'COPYING.TXT'. 14 | // * For more information on GPL licensing: http://www.gnu.org/licenses 15 | // ******************************************************************************************************************************** 16 | 17 | // ================================================================================================================================ 18 | // Supply the full path to the RFLink files in the define below 19 | // 20 | // Geef in onderstaande "define" regel het volledige pad op waar de .ino bestanden zich bevinden die je nu geopend hebt. 21 | // ================================================================================================================================ 22 | 23 | #define SKETCH_PATH D:\arduino\RFLink 24 | 25 | // ================================================================================================================================ 26 | // IMPORTANT NOTE: This code only runs on an Arduino MEGA !!!!!!!!!!!!!!!!!!!!!! It was designed that way for various reasons. 27 | // ================================================================================================================================ 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ! ============================================================================ 2 | ! Only for educational purposes, this source is not be synchronized with the 3 | ! latest release! 4 | ! For normal operation, use the RFLink Loader that includes the latest release 5 | ! This source code tree is made available so that you can develop your own plugins 6 | ! ============================================================================ 7 | 8 | Please note that the RFLink Gateway is a freeware project. 9 | Stuntteam is not making money in any way. 10 | This means that there are no unlimited funds to purchase test devices, 11 | it also means the project has to rely on you, the user, to send debug data. 12 | 13 | If you want to contribute to this project, you can send a donation which is more than welcome (see www.nemcon.nl/blog2 donation button), 14 | or help with sending debug data of unsupported devices (you can even write and contribute plugins and/or code fixes), 15 | or donate the device that you would like to see supported. 16 | 17 | Right now we are looking for some older remotes and/or switches. 18 | Like for example: Impuls, Ikea Koppla, Powerfix, Blyss, Home Confort, Conrad, Kambrook, Everflourish 19 | For the implementation of the planned 2.4Ghz support we could use some simple MySensor devices. 20 | For the implementation of the planned 868Mhz support we could use some devices as well. 21 | If you have anything that you do not use, send a mail to frankzirrone@gmail.com 22 | Thanks in advance! 23 | 24 | ------------------------ 25 | Synology NAS: 26 | If you want to use RFLink with a Synology NAS you can use: 27 | - an Arduino Mega clone based on CH340 USB/serial chip 28 | In all other cases: 29 | - connect a 10 uF capacitor between reset and ground on the Arduino. 30 | Simply stick the pins of the capacitor in the power connector socket. 31 | When you want to update the firmware of the Arduino, remove the capacitor and reconnect it when done. 32 | For details about the Domoticz Synology package check out: http://www.jadahl.com 33 | ------------------------ 34 | RFlink via Network Connection: 35 | It is possible to use RFlink via a network connection using ser2net. 36 | ------------------------ 37 | You can now use the RFLink Gateway with the following home automation software: 38 | Domoticz 39 | Jeedom 40 | ------------------------ 41 | -------------------------------------------------------------------------------- /Misc.ino: -------------------------------------------------------------------------------- 1 | /*********************************************************************************************\ 2 | * Convert HEX or DEC tring to unsigned long HEX, DEC 3 | \*********************************************************************************************/ 4 | unsigned long str2int(char *string) { 5 | return(strtoul(string,NULL,0)); 6 | } 7 | /*********************************************************************************************\ 8 | * Convert string to command code 9 | \*********************************************************************************************/ 10 | int str2cmd(char *command) { 11 | if(strcasecmp(command,"ON") == 0) return VALUE_ON; 12 | if(strcasecmp(command,"OFF") == 0) return VALUE_OFF; 13 | if(strcasecmp(command,"ALLON") == 0) return VALUE_ALLON; 14 | if(strcasecmp(command,"ALLOFF") == 0) return VALUE_ALLOFF; 15 | if(strcasecmp(command,"PAIR") == 0) return VALUE_PAIR; 16 | if(strcasecmp(command,"DIM") == 0) return VALUE_DIM; 17 | if(strcasecmp(command,"BRIGHT") == 0) return VALUE_BRIGHT; 18 | if(strcasecmp(command,"UP") == 0) return VALUE_UP; 19 | if(strcasecmp(command,"DOWN") == 0) return VALUE_DOWN; 20 | if(strcasecmp(command,"STOP") == 0) return VALUE_STOP; 21 | if(strcasecmp(command,"CONFIRM") == 0) return VALUE_CONFIRM; 22 | if(strcasecmp(command,"LIMIT") == 0) return VALUE_LIMIT; 23 | return false; 24 | } 25 | /********************************************************************************************\ 26 | * Convert unsigned long to float long through memory 27 | \*********************************************************************************************/ 28 | float ul2float(unsigned long ul) { 29 | float f; 30 | memcpy(&f, &ul,4); 31 | return f; 32 | } 33 | /*********************************************************************************************/ 34 | void PrintHex8(uint8_t *data, uint8_t length) { // prints 8-bit data in hex (lowercase) 35 | char tmp[length*2+1]; 36 | byte first ; 37 | int j=0; 38 | for (uint8_t i=0; i> 4) | 48; 40 | if (first > 57) tmp[j] = first + (byte)39; 41 | else tmp[j] = first ; 42 | j++; 43 | 44 | first = (data[i] & 0x0F) | 48; 45 | if (first > 57) tmp[j] = first + (byte)39; 46 | else tmp[j] = first; 47 | j++; 48 | } 49 | tmp[length*2] = 0; 50 | Serial.print(tmp); 51 | } 52 | /*********************************************************************************************/ 53 | // todo: make uppercase? 3a = 3 or 48 (0x30) = 0x33 >57 (0x39) a>3a >39 > +27 54 | void PrintHexByte(uint8_t data) { // prints 8-bit value in hex (single byte) 55 | char tmp[3]; 56 | byte first ; 57 | first = (data >> 4) | 48; // or with 0x30 58 | if (first > 57) tmp[0] = first + (byte)7; // 39; // if > 0x39 add 0x27 59 | else tmp[0] = first ; 60 | 61 | first = (data & 0x0F) | 48; 62 | if (first > 57) tmp[1] = first + (byte)7; // 39; 63 | else tmp[1] = first; 64 | tmp[2] = 0; 65 | Serial.print(tmp); 66 | } 67 | /*********************************************************************************************/ 68 | // Reverse all bits in a byte 69 | byte reverseBits(byte data) { 70 | byte b = data; 71 | for (byte i = 0; i < 8; ++i) { 72 | data = (data << 1) | (b & 1); 73 | b >>= 1; 74 | } 75 | return data; 76 | } 77 | /*********************************************************************************************/ 78 | 79 | -------------------------------------------------------------------------------- /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 : StuntTeam 11 | * Support : 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 description: 16 | * This plugin just outputs unsupported RF packets, use this plugin to find signals from new devices 17 | * Even if you do not know what to do with the data yourself you might want to share your data so 18 | * others can analyse it. 19 | \*********************************************************************************************/ 20 | #ifdef PLUGIN_254 21 | boolean Plugin_254(byte function, char *string) { 22 | if (QRFDebug==true) { // debug is on? 23 | if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning 24 | // ---------------------------------- 25 | // Output 26 | // ---------------------------------- 27 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 28 | Serial.print( pbuffer ); 29 | // ---------------------------------- 30 | Serial.print(F("DEBUG;Pulses=")); // debug data 31 | Serial.print(RawSignal.Number); // print number of pulses 32 | Serial.print(F(";Pulses(uSec)=")); // print pulse durations 33 | //PrintHex8(RawSignal.Pulses+1,RawSignal.Number-1); 34 | PrintHex8(RawSignal.Pulses+1,RawSignal.Number); 35 | } else { 36 | if (RFUDebug==false) return false; // debug is on? 37 | if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning 38 | // ---------------------------------- 39 | // Output 40 | // ---------------------------------- 41 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 42 | Serial.print( pbuffer ); 43 | // ---------------------------------- 44 | Serial.print(F("DEBUG;Pulses=")); // debug data 45 | Serial.print(RawSignal.Number); // print number of pulses 46 | Serial.print(F(";Pulses(uSec)=")); // print pulse durations 47 | //for(int x=1;x ALARMPIRV2_PULSESHORT) return false; // First pulse is start bit and should be short! 40 | for(byte x=2;x < ALARMPIRV2_PULSECOUNT;x=x+2) { 41 | if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMID) { // long pulse 800-875 (700-1000 accepted) 42 | if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMAX) return false; // pulse too long 43 | if (RawSignal.Pulses[x+1] > ALARMPIRV2_PULSEMID) return false; // invalid manchester code 44 | bitstream = bitstream << 1; 45 | } else { // short pulse 350-425 (250-550 accepted) 46 | if (RawSignal.Pulses[x] < ALARMPIRV2_PULSEMIN) return false; // pulse too short 47 | if (RawSignal.Pulses[x+1] < ALARMPIRV2_PULSEMID) return false; // invalid manchester code 48 | bitstream = (bitstream << 1) | 0x1; 49 | } 50 | } 51 | //================================================================================== 52 | // Prevent repeating signals from showing up 53 | //================================================================================== 54 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000 ALARMPIRV1_PULSEMID) { 38 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long 39 | if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 40 | bitstream = (bitstream << 1) | 0x1; 41 | } else { 42 | if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short 43 | if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 44 | bitstream = bitstream << 1; 45 | } 46 | } 47 | //================================================================================== 48 | // Prevent repeating signals from showing up 49 | //================================================================================== 50 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000 OREGON_PLA_PULSECOUNT) ) return false; 27 | unsigned long bitstream=0L; 28 | //================================================================================== 29 | byte bits=0; 30 | byte rfbit = 1; 31 | 32 | if ( (RawSignal.Number < 50) || (RawSignal.Number > 52)) return false; 33 | // Check preamble 34 | for(byte x=1;x<28;x=x+2){ 35 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) return false; 36 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 600) return false; 37 | } 38 | // Check bits 39 | for(byte x=29;x<=RawSignal.Number;x++){ 40 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) { // toggle bit value 41 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 1600) break; // done.. 42 | rfbit = (~rfbit)&1; 43 | bitstream = (bitstream << 1) | rfbit; 44 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++; 45 | } else { 46 | bitstream = (bitstream << 1) | rfbit; // short pulse keep bit value 47 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++; 48 | } 49 | } 50 | //================================================================================== 51 | // Prevent repeating signals from showing up 52 | //================================================================================== 53 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000>4; 63 | bits=(bitstream)&0x3; 64 | bits=bits+0x30; // signal 3 for plugin 63 65 | //================================================================================== 66 | // Output 67 | // ---------------------------------- 68 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 69 | Serial.print( pbuffer ); 70 | // ---------------------------------- 71 | Serial.print(F("X10;")); // Label 72 | sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID + channel number 73 | Serial.print( pbuffer ); 74 | sprintf(pbuffer, "SWITCH=%02x;", bits); // channel number 75 | Serial.print( pbuffer ); 76 | Serial.print(F("CMD=ON;")); // this device reports movement only 77 | Serial.println(); 78 | //================================================================================== 79 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 80 | RawSignal.Number=0; 81 | return true; 82 | } 83 | #endif // Plugin_063 84 | -------------------------------------------------------------------------------- /Plugins/Plugin_033.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-33 Conrad ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding Conrad Pool Thermomether model 9771 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical information: 16 | * Decodes signals from a Conrad Model 9771 Pool Thermometer, (80 pulses, 40 bits, 433 MHz). 17 | * Message Format: 18 | * AAAAAAAA BBBBBBBB CCCCCCCCCC DD EEEE FFFF GGGG 19 | * 00000000 00010010 1100101101 01 1001 0001 1001 20 | * 21 | * A = Always 0 ? 22 | * B = Device id ? 23 | * C = Temperature digits 24 | * D = Temperature ones 25 | * E = Temperature tens 26 | * F = Always 1? 27 | * G = Unknown 28 | * 29 | * Sample: 30 | * 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; 31 | \*********************************************************************************************/ 32 | #define CONRAD_PULSECOUNT 80 33 | #define CONRAD_PULSEMAX 5000/RAWSIGNAL_SAMPLE_RATE 34 | #define CONRAD_PULSEMIN 2300/RAWSIGNAL_SAMPLE_RATE 35 | 36 | #ifdef PLUGIN_033 37 | boolean Plugin_033(byte function, char *string) { 38 | if (RawSignal.Number != CONRAD_PULSECOUNT) return false; 39 | unsigned long bitstream=0L; 40 | unsigned int temperature=0; 41 | unsigned int rc=0; 42 | byte checksum=0; 43 | byte bitcount=0; // bit counter (counting first 8 bits that need 44 | //================================================================================== 45 | // get all 28 bits 46 | for(byte x=1;x <=CONRAD_PULSECOUNT-1;x+=2) { 47 | if (RawSignal.Pulses[x] > CONRAD_PULSEMAX) { 48 | if (RawSignal.Pulses[x+1] > CONRAD_PULSEMAX) if ( (x+1) < CONRAD_PULSECOUNT ) return false; // invalid pulse length 49 | if (bitcount > 7) { 50 | bitstream = (bitstream << 1) | 0x1; 51 | } else { 52 | return false; // first 8 bits should all be zeros 53 | } 54 | bitcount++; 55 | } else { 56 | if (RawSignal.Pulses[x] > CONRAD_PULSEMIN) return false; // invalid pulse length 57 | if (RawSignal.Pulses[x+1] < CONRAD_PULSEMIN) return false; // invalid pulse length 58 | if (bitcount > 7) bitstream = (bitstream << 1); 59 | bitcount++; 60 | } 61 | } 62 | //================================================================================== 63 | // Prevent repeating signals from showing up 64 | //================================================================================== 65 | Serial.println(bitstream,HEX); 66 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000> 4) & 0x0f; 74 | if (checksum != 0x01) return false; 75 | 76 | rc=(bitstream >> 24); 77 | temperature=(bitstream >> 14) & 0x3ff; 78 | temperature=temperature-500; 79 | //================================================================================== 80 | // Output 81 | // ---------------------------------- 82 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 83 | Serial.print( pbuffer ); 84 | Serial.print(F("Conrad;")); // Label 85 | sprintf(pbuffer, "ID=%04x;", rc); // ID 86 | Serial.print( pbuffer ); 87 | sprintf(pbuffer, "TEMP=%04x;", temperature); 88 | Serial.print( pbuffer ); 89 | Serial.println(); 90 | //================================================================================== 91 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 92 | RawSignal.Number=0; 93 | return true; 94 | } 95 | #endif // PLUGIN_033 96 | -------------------------------------------------------------------------------- /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 : StuntTeam 10 | * Support : http://sourceforge.net/projects/rflink/ 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 | * Technical data: 15 | * Devices send 50 pulses. Manchester encoded, 25 bits 16 | * 17 | * PIR Motion detection unit: 18 | * PCB contains 2 chips: biss0001 & ev1527 19 | * BISS0001 = Micro Power PIR Motion Detector IC 20 | * EV1527 = OTP Encoder, max. of 20 bits providing up to 1 million codes. 21 | * 22 | * Sample: 23 | * 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, 24 | * 100101100101100101011001100110101010101010010110 25 | * 01101101 1101010000000110 6D D406 26 | 27 | * 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; 28 | * 010110010110101010101010101001100110010110010110 29 | * 00100111 1111110101001001 27 FD49 30 | * 11011000 0000001010110110 D8 02B6 31 | 32 | * 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; 33 | * 101001010101101010010110010101011010100110010110 34 | * 001111000110111100010110 3C6F16 35 | * 110000111001000011101001 c390E9 36 | \*********************************************************************************************/ 37 | #define ALARMPIRV1_PULSECOUNT 50 38 | 39 | #define ALARMPIRV1_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE 40 | #define ALARMPIRV1_PULSEMAX 1300/RAWSIGNAL_SAMPLE_RATE 41 | #define ALARMPIRV1_PULSEMIN 150/RAWSIGNAL_SAMPLE_RATE 42 | 43 | #ifdef PLUGIN_061 44 | boolean Plugin_061(byte function, char *string) { 45 | if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) return false; 46 | if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63 47 | unsigned long bitstream=0L; 48 | unsigned long bitstream2=0L; 49 | //================================================================================== 50 | for(byte x=2;x<=48;x=x+2) { 51 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID) { 52 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long 53 | if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 54 | bitstream = bitstream << 1; 55 | } else { 56 | if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short 57 | if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 58 | bitstream = (bitstream << 1) | 0x1; 59 | } 60 | } 61 | //================================================================================== 62 | // Prevent repeating signals from showing up 63 | //================================================================================== 64 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000>16; 73 | if ( (bitstream2)==0xff) { 74 | if ( (bitstream)&0xffff==0xff) return false; 75 | } 76 | //================================================================================== 77 | // Output 78 | // ---------------------------------- 79 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 80 | Serial.print( pbuffer ); 81 | // ---------------------------------- 82 | Serial.print(F("X10;")); // Label 83 | sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID 84 | Serial.print( pbuffer ); 85 | Serial.print(F("SWITCH=01;")); 86 | Serial.print(F("CMD=ON;")); // this device reports movement only 87 | Serial.println(); 88 | //================================================================================== 89 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 90 | RawSignal.Number=0; 91 | return true; 92 | } 93 | #endif // Plugin_061 94 | -------------------------------------------------------------------------------- /Plugins/Plugin_071.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-71 Plieger York doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Plieger York Doorbell protocol 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical Information: 16 | * Decodes signals from a Plieger York Doorbell, (66 pulses, 32 bits, 433 MHz). 17 | * Plieger Message Format: 18 | * 0000000001010101 00000000 00011100 c2 0x1c 19 | * 00000011 c3 0x03 20 | * 11100000 c1 0xE0 21 | * -------- 8 bits chime number (3 chimes, can be changed with a jumped on the transmitter) 22 | * -------- 8 bits always 0 23 | * ---------------- 16 bits code which can be changed with a button on the inside of the transmitter 24 | * 25 | * Note: The transmitter sends two times the same packet when the bell button is pressed 26 | * the retransmit is killed to prevent reporting the same press twice 27 | * 28 | * Sample packet: (Nodo Pulse timing) 29 | * Pulses=66, Pulses(uSec)=700,250,275,725,750,250,275,725,750,250,275,725,750,250,275,725,750,250, 30 | * 275,725,750,250,275,725,750,250,275,725,750,250,275,725,275,725,275,725,275,725,275,725,275,725, 31 | * 275,725,275,725,275,725,275,725,275,725,275,725,750,250,750,250,750,250,275,725,275,725,225, 32 | * 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; 33 | * 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; 34 | * 20;2E;Plieger York;ID=aaaa;SWITCH=1;CMD=ON;CHIME=02; 35 | \*********************************************************************************************/ 36 | #define PLIEGER_PULSECOUNT 66 37 | #define PLIEGER_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE 38 | #define PLIEGER_PULSEMAX 1900/RAWSIGNAL_SAMPLE_RATE 39 | 40 | #ifdef PLUGIN_071 41 | boolean Plugin_071(byte function, char *string) { 42 | if (RawSignal.Number != PLIEGER_PULSECOUNT) return false; 43 | unsigned long bitstream=0L; 44 | unsigned int id=0; 45 | byte chime=0; 46 | //================================================================================== 47 | // get all 32 bits 48 | for(byte x=1;x <=PLIEGER_PULSECOUNT-2;x+=2) { 49 | if(RawSignal.Pulses[x] > PLIEGER_PULSEMID) { 50 | if (RawSignal.Pulses[x] > PLIEGER_PULSEMAX) return false; 51 | if (RawSignal.Pulses[x+1] > PLIEGER_PULSEMID) return false; // Valid Manchester check 52 | bitstream = (bitstream << 1) | 0x1; 53 | } else { 54 | if (RawSignal.Pulses[x+1] < PLIEGER_PULSEMID) return false; // Valid Manchester check 55 | bitstream = (bitstream << 1); 56 | } 57 | } 58 | //================================================================================== 59 | // Prevent repeating signals from showing up 60 | //================================================================================== 61 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000> 8) &0xff) != 0x00) return false; // these 8 bits are always 0 71 | chime=bitstream &0xff; 72 | if (chime != 0x1c && chime !=0x03 && chime != 0xE0) return false; // the chime number can only have 3 values 73 | //================================================================================== 74 | id=(bitstream >> 16) & 0xffff; // get 16 bits unique address 75 | if (chime == 0xE0) chime =1; 76 | if (chime == 0x1C) chime =2; 77 | //================================================================================== 78 | // Output 79 | // ---------------------------------- 80 | Serial.print("20;"); 81 | PrintHexByte(PKSequenceNumber++); 82 | Serial.print(F(";Plieger;")); // Label 83 | // ---------------------------------- 84 | sprintf(pbuffer, "ID=%04x;", id); // ID 85 | Serial.print( pbuffer ); 86 | Serial.print("SWITCH=1;CMD=ON;"); 87 | sprintf(pbuffer, "CHIME=%02x;", chime); // chime number 88 | Serial.print( pbuffer ); 89 | Serial.println(); 90 | //================================================================================== 91 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 92 | RawSignal.Number=0; // do not process the packet any further 93 | return true; 94 | } 95 | #endif // PLUGIN_071 96 | -------------------------------------------------------------------------------- /Plugins/Plugin_044.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-44 Auriol V3 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol for sensor type Z32171A 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical Information: 16 | * Decodes signals from a Auriol Weatherstation outdoor unit, (40 bits, 433 MHz). 17 | * 18 | * Auriol Message Format: 19 | * 1011 1111 1001 1010 0110 0001 1011 0100 1001 0001 20 | * B F 9 A 6 1 B 4 9 1 21 | * AAAA AAAA BBBB CCDD EEEE EEEE EEEE FFFF FFFF GGHH 22 | * 23 | * A = ID? 24 | * B = Rolling code? 25 | * C = possibly battery indicator ? 26 | * D = trend (2 bits) indicating temp equal/up/down ? 27 | * E = Temperature => 0x61b (0x61b-0x4c4)=0x157 *5)=0x6b3 /9)=0xBE => 0xBE = 190 decimal! 28 | * F = humidity: 49% 29 | * G = ? 30 | * H = channel: 1 (2 bits) 31 | * 32 | * Sample: 33 | * 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; 34 | \*********************************************************************************************/ 35 | #define AURIOLV3_PULSECOUNT 82 36 | 37 | #ifdef PLUGIN_044 38 | boolean Plugin_044(byte function, char *string) { 39 | if (RawSignal.Number != AURIOLV3_PULSECOUNT) return false; 40 | unsigned long bitstream1=0L; 41 | unsigned long bitstream2=0L; 42 | byte rc=0; 43 | byte channel=0; 44 | byte bitcounter=0; 45 | unsigned long temperature=0; 46 | byte humidity=0; 47 | //================================================================================== 48 | // get all the bits we need (40 bits) 49 | for(int x=2;x < AURIOLV3_PULSECOUNT;x+=2) { 50 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 650) return false; 51 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 3500) { 52 | if (bitcounter < 16) { 53 | bitstream1 = (bitstream1 << 1) | 0x1; 54 | bitcounter++; // only need to count the first 10 bits 55 | } else { 56 | bitstream2 = (bitstream2 << 1) | 0x1; 57 | } 58 | } else { 59 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false; 60 | if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false; 61 | if (bitcounter < 16) { 62 | bitstream1 = (bitstream1 << 1); 63 | bitcounter++; // only need to count the first 10 bits 64 | } else { 65 | bitstream2 = (bitstream2 << 1); 66 | } 67 | } 68 | } 69 | //================================================================================== 70 | // Perform sanity checks and prevent repeating signals from showing up 71 | //================================================================================== 72 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer> 8) & 0xff ; // get rolling code 80 | temperature = ((bitstream2)>>12) & 0xfff; // get 12 temperature bits 81 | temperature = (temperature - 0x4c4) & 0xffff; 82 | temperature = (((temperature) * 5) / 9) & 0xffff; 83 | if (temperature > 3000) { 84 | temperature=4096-temperature; // fix for minus temperatures 85 | if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees) 86 | temperature=temperature | 0x8000; // turn highest bit on for minus values 87 | } else { 88 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 89 | } 90 | humidity = (bitstream2 >> 4) & 0xff ; // humidity 91 | channel=(bitstream2) & 0x03; // channel number 92 | //================================================================================== 93 | // Output 94 | // ---------------------------------- 95 | Serial.print("20;"); 96 | PrintHexByte(PKSequenceNumber++); 97 | Serial.print(F(";Auriol V3;ID=")); // Label 98 | PrintHexByte(rc); 99 | PrintHexByte(channel); 100 | // ---------------------------------- 101 | sprintf(pbuffer, ";TEMP=%04x;", temperature); // temp 102 | Serial.print( pbuffer ); 103 | sprintf(pbuffer, "HUM=%02x;", humidity); // hum 104 | Serial.print( pbuffer ); 105 | Serial.println(); 106 | //================================================================================== 107 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 108 | RawSignal.Number=0; 109 | return true; 110 | } 111 | #endif // PLUGIN_044 112 | -------------------------------------------------------------------------------- /Config/Config_01.c: -------------------------------------------------------------------------------- 1 | // **************************************************************************************************************************************** 2 | // RFLink List of Plugins 3 | // **************************************************************************************************************************************** 4 | // Here are all plugins listed that are supported and used after compilation. 5 | // When needed additional plugins can be added or selected plugins can be enabled/disabled. 6 | // 7 | // BEWARE OF THE PLUGIN_MAX setting!! TX: 51 RX: 24 8 | // **************************************************************************************************************************************** 9 | // Translation Plugin for oversized packets due to their breaks/pause being too short between packets 10 | // Used for Flamingo FA500R and various others, do NOT exclude this plugin. 11 | #define PLUGIN_001 // DO NOT CHANGE OR EXCLUDE!! 12 | // ------------------------------------------------------------------------ 13 | // -- Any of the following protocols can be excluded whenever not needed -- 14 | // ------------------------------------------------------------------------ 15 | #define PLUGIN_002 // Lacrosse v2 2300/3600 16 | #define PLUGIN_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC 17 | #define PLUGIN_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno. 18 | #define PLUGIN_005 // Eurodomest 19 | #define PLUGIN_006 // Blyss 20 | #define PLUGIN_007 // Conrad RSL2 21 | #define PLUGIN_008 // Kambrook 22 | #define PLUGIN_009 // X10 RF 23 | #define PLUGIN_010 // TRC02 RGB Switch 24 | #define PLUGIN_011 // Home Confort 25 | #define PLUGIN_012 // Flamingo FA500R 26 | #define PLUGIN_013 // Powerfix/Quigg 27 | #define PLUGIN_014 // Ikea Koppla 28 | #define PLUGIN_015 // Home Easy EU 29 | // ------------------- 30 | // Weather sensors 31 | // ------------------- 32 | #define PLUGIN_030 // Alecto V1 (WS3500) 434 MHz. 33 | #define PLUGIN_031 // Alecto V3 (WS1100/WS1200/WSD-19) 433.9 MHz. 34 | #define PLUGIN_032 // Alecto V4 35 | #define PLUGIN_033 // Conrad Pool Thermometer 36 | #define PLUGIN_034 // Cresta 37 | #define PLUGIN_035 // Imagintronix 38 | #define PLUGIN_040 // Mebus 39 | #define PLUGIN_041 // LaCrosse v3 ws7000 40 | #define PLUGIN_042 // UPM/Esic 41 | #define PLUGIN_043 // LaCrosse v1 42 | #define PLUGIN_044 // Auriol v3 43 | #define PLUGIN_045 // Auriol 44 | #define PLUGIN_046 // Auriol v2 / Xiron 45 | #define PLUGIN_048 // Oregon V1/2/3 46 | // ------------------- 47 | // Motion Sensors, include when needed 48 | // ------------------- 49 | #define PLUGIN_060 // Ajax Chubb Varel 433 MHz. motion sensors 50 | #define PLUGIN_061 // Chinese PIR motion door and window sensors 51 | #define PLUGIN_062 // Chuango Alarm Devices 52 | #define PLUGIN_063 // Oregon PIR/ALARM/LIGHT 53 | // ------------------- 54 | // Doorbells 55 | // ------------------- 56 | #define PLUGIN_070 // Select Plus (Action - Quhwa) 57 | #define PLUGIN_071 // Plieger York 58 | #define PLUGIN_072 // Byron SX doorbell 59 | #define PLUGIN_073 // Deltronic doorbell 60 | #define PLUGIN_074 // RL02 61 | #define PLUGIN_075 // Silvercrest 62 | // ------------------- 63 | // Smoke detectors / Fire Places 64 | // ------------------- 65 | #define PLUGIN_080 // Flamingo FA20 / KD101 smoke detector 66 | #define PLUGIN_082 // Mertik Maxitrol / Dru fireplace 67 | //#define PLUGIN_083 // Alecto SA33 68 | // ------------------- 69 | // 868 MHZ 70 | // ------------------- 71 | #define PLUGIN_100 // Alecto V2 (DKW2012/ACH2010) 868 MHz. => PLANNED 72 | // ------------------- 73 | // Housekeeping 74 | // ------------------- 75 | #define PLUGIN_090 // Nodo Slave conversion plugin 76 | #define PLUGIN_254 // Debug to show unsupported packets 77 | // **************************************************************************************************************************************** 78 | // RFLink List of Plugins that have TRANSMIT functionality 79 | // **************************************************************************************************************************************** 80 | // Here are all plugins listed that are supported and used after compilation. 81 | // When needed additional plugins can be added or selected plugins can be enabled/disabled. 82 | // **************************************************************************************************************************************** 83 | // ------------------------------------------------------------------------ 84 | // -- Any of the following protocols can be excluded whenever not needed -- 85 | // ------------------------------------------------------------------------ 86 | #define PLUGIN_TX_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC 87 | #define PLUGIN_TX_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno. 88 | #define PLUGIN_TX_005 // Eurodomest 89 | #define PLUGIN_TX_006 // Blyss 90 | #define PLUGIN_TX_007 // Conrad RSL2 91 | #define PLUGIN_TX_008 // Kambrook 92 | #define PLUGIN_TX_009 // X10 RF 93 | #define PLUGIN_TX_010 // TRC02 RGB switch 94 | #define PLUGIN_TX_011 // Home Confort 95 | #define PLUGIN_TX_012 // Flamingo FA500R (11) 96 | #define PLUGIN_TX_013 // Powerfix/Quigg 97 | #define PLUGIN_TX_015 // Home Easy EU (14) 98 | // ------------------- 99 | // Doorbells 100 | // ------------------- 101 | #define PLUGIN_TX_070 // Select Plus (Action - Quhwa) 102 | #define PLUGIN_TX_072 // Byron SX doorbell 103 | #define PLUGIN_TX_073 // Deltronic doorbell 104 | #define PLUGIN_TX_074 // RL02 105 | // ------------------- 106 | // Smoke detectors 107 | // ------------------- 108 | #define PLUGIN_TX_080 // Flamingo FA20 / KD101 smoke detector 109 | #define PLUGIN_TX_082 // Mertik Maxitrol / Dru fireplace 110 | // ------------------- 111 | // -=#=- 112 | // ------------------- 113 | -------------------------------------------------------------------------------- /Plugins/Plugin_035.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-35 Imagintronix ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding Imagintronix sensors 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical information: 16 | * 17 | * ~0.5ms high puls followed by ~1ms pause = high 18 | * ~1.5ms high puls followed by ~1ms pause = low 19 | * 20 | * Message Format: 21 | * 11111111 01010101 00000101 01000101 11111111 10011110 22 | * FF550545FF9E 23 | * AABCDDEEFFGG 24 | * 25 | * A = Preamble, always FF 26 | * B = TX type, always 5 27 | * C = Address (5/6/7) > low 2 bits = 1/2/3 28 | * D = Soil moisture 05% 29 | * E = temperature 30 | * F = security code, always F 31 | * G = Checksum 55+05+45+FF=19E CRC value = 9E 32 | * 33 | * Sample: 34 | * 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; 35 | * 111111110101010100000101010001011111111110011110 36 | \*********************************************************************************************/ 37 | #define IMAGINTRONIX_PULSECOUNT 96 38 | #define IMAGINTRONIX_PULSEMID 1000/RAWSIGNAL_SAMPLE_RATE 39 | #define IMAGINTRONIX_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE 40 | 41 | #ifdef PLUGIN_035 42 | boolean Plugin_035(byte function, char *string) { 43 | if (RawSignal.Number != IMAGINTRONIX_PULSECOUNT) return false; 44 | unsigned int temperature=0; 45 | unsigned int rc=0; 46 | 47 | byte checksum=0; 48 | byte data[8]; 49 | unsigned long bitstream=0L; 50 | //================================================================================== 51 | byte bytecounter=0; // used for counting the number of received bytes 52 | byte bitcounter=0; // counts number of received bits (converted from pulses) 53 | // get bits 54 | for(byte x=1;x < IMAGINTRONIX_PULSECOUNT;x=x+2) { 55 | if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSEMID) { // long pulse = 0 bit 56 | if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false; 57 | data[bytecounter] = (data[bytecounter] << 1); // 0 bit 58 | bitcounter++; // received a bit 59 | } else { // Short pulse = 1 bit 60 | if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSESHORT) return false; // Short pulse too long? 61 | if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false; 62 | data[bytecounter] = (data[bytecounter] << 1) | 0x1; // 1 bit 63 | bitcounter++; // received a bit 64 | } 65 | // prepare for next bit/byte 66 | if (bitcounter==8) { // received 8 bits? 67 | bitcounter=0; // reset for next byte 68 | bytecounter++; // byte received, increase counter 69 | if (bytecounter > 7) return false; // overflow, should not happen 70 | } 71 | } 72 | //================================================================================== 73 | // Verify packet and calculate checksum 74 | //================================================================================== 75 | if (data[0] != 0xff) return false; 76 | checksum=data[1]+data[2]+data[3]+data[4]; 77 | if (((checksum)&0xff) != data[5]) return false; 78 | if ( (data[1] >>4) != 0x5) return false; 79 | if (data[4] != 0xff) return false; 80 | //================================================================================== 81 | // Prevent repeating signals from showing up 82 | //================================================================================== 83 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000 550) return false; // inbetween pulses should not exceed a length of 550 47 | if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) { // long bit = 1 48 | bitstream = (bitstream << 1) | 0x1; 49 | } else { 50 | if(RawSignal.Pulses[x]*RawSignal.Multiply < 1600) return false; // pulse length too short to be valid? 51 | if(RawSignal.Pulses[x]*RawSignal.Multiply > 2200) return false; // pulse length between 2000 - 3000 is invalid 52 | bitstream = (bitstream << 1); // short bit = 0 53 | } 54 | } 55 | } 56 | //================================================================================== 57 | // Prevent repeating signals from showing up 58 | //================================================================================== 59 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000>i)&0x01); 69 | } 70 | if (checksumcalc != (bitstream&0x01) ) return false; 71 | rc = (bitstream >> 20) & 0x07; // get 3 bits to perform another sanity check 72 | if (rc != 0) return false; // selected bits should always be 000 73 | //================================================================================== 74 | bat= (bitstream >> 23) & 0x01; // get battery strength indicator 75 | temperature = (bitstream >> 8) & 0xfff; // get 12 temperature bits 76 | rc = (bitstream >> 24) & 0xff; // get rolling code 77 | if (temperature > 3000) { 78 | temperature=4096-temperature; // fix for minus temperatures 79 | if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees) 80 | temperature=temperature | 0x8000; // turn highest bit on for minus values 81 | } else { 82 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 83 | } 84 | //================================================================================== 85 | // Output 86 | // ---------------------------------- 87 | Serial.print("20;"); 88 | PrintHexByte(PKSequenceNumber++); 89 | Serial.print(F(";Auriol;ID=00")); // Label 90 | PrintHexByte(rc); 91 | // ---------------------------------- 92 | sprintf(pbuffer, ";TEMP=%04x;", temperature); 93 | Serial.print( pbuffer ); 94 | if (bat==0) { // battery status 95 | Serial.print(F("BAT=LOW;")); 96 | } else { 97 | Serial.print(F("BAT=OK;")); 98 | } 99 | Serial.println(); 100 | //================================================================================== 101 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 102 | RawSignal.Number=0; 103 | return true; 104 | } 105 | #endif // PLUGIN_045 106 | -------------------------------------------------------------------------------- /Plugins/Plugin_080.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-80 Flamingo FA20RF Rookmelder ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * Dit protocol zorgt voor ontvangst van Flamingo FA20RF rookmelder 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical information: 16 | * The Flamingo FA20RF/FA21RF Smokedetector contains both a RF receiver and transmitter. 17 | * Every unit has a unique ID. The detector has a "learn" button to learn the ID of other units. 18 | * That is what links the units to each other. After linking multiple units, they all have the same ID! 19 | * Normally, one unit is used as master and the code of the master is learned to the slaves 20 | * 21 | * Attention: The smoke detector gives an alarm as long as the message is transmitted 22 | * 23 | * Sample: 24 | * 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, 25 | * 650,2550,650,1275,650,2550,650,2550,650,1275,650,1275,650,2550,650,1200,650; 26 | * 000000010100110110110010 = 014DB2 27 | * 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, 28 | * 625,2575,625,1275,625,2575,625,2575,625,1300,625,1275,625,2575,625,1225,625; 29 | * 100101111110001110110010 = 97E3B2 30 | * 20;0D;FA20RF;ID=97e3b2;SMOKEALERT=ON; 31 | * 32 | * False positive: 33 | * 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; 34 | \*********************************************************************************************/ 35 | #define FA20RFSTART 3000 // 8000 36 | #define FA20RFSPACE 675 // 800 37 | #define FA20RFLOW 1250 // 1300 38 | #define FA20RFHIGH 2550 // 2600 39 | #define FA20_PULSECOUNT 52 40 | 41 | #ifdef PLUGIN_080 42 | boolean Plugin_080(byte function, char *string) { 43 | if (RawSignal.Number != FA20_PULSECOUNT) return false; 44 | unsigned long bitstream=0L; 45 | //================================================================================== 46 | for(byte x=4;x<=FA20_PULSECOUNT-2;x=x+2) { 47 | if (RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE > 1000) return false; // every preceding pulse must be below 1000! 48 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2000) { // long pulse 49 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2800) return false; // long pulse too long 50 | bitstream = (bitstream << 1) | 0x1; 51 | } else { 52 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1500) return false; // short pulse too long 53 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 1000) return false; // short pulse too short 54 | bitstream = bitstream << 1; 55 | } 56 | } 57 | //================================================================================== 58 | if (bitstream == 0) return false; 59 | if (bitstream == 0xFFFFFF) return false; 60 | if (((bitstream)&0xffff) == 0xffff) return false; 61 | //================================================================================== 62 | // Output 63 | // ---------------------------------- 64 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number 65 | Serial.print( pbuffer ); 66 | // ---------------------------------- 67 | Serial.print(F("FA20RF;")); // Label 68 | sprintf(pbuffer, "ID=%06lx;", bitstream ); // ID 69 | Serial.print( pbuffer ); 70 | Serial.print(F("SMOKEALERT=ON;")); 71 | Serial.println(); 72 | //================================================================================== 73 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 74 | RawSignal.Number=0; // do not process the packet any further 75 | return true; 76 | } 77 | #endif // PLUGIN_080 78 | 79 | #ifdef PLUGIN_TX_080 80 | boolean PluginTX_080(byte function, char *string) { 81 | boolean success=false; 82 | //10;FA20RF;67f570;1;ON; 83 | //012345678901234567890 84 | unsigned long bitstream=0; 85 | if (strncasecmp(InputBuffer_Serial+3,"FA20RF;",7) == 0) { // KAKU Command eg. 86 | if (InputBuffer_Serial[18] != ';') return false; 87 | InputBuffer_Serial[8]=0x30; 88 | InputBuffer_Serial[9]=0x78; 89 | InputBuffer_Serial[16]=0; 90 | bitstream=str2int(InputBuffer_Serial+8); 91 | byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF 92 | if (cmd!=VALUE_ON) return true; // pretend command was ok but we dont have to send anything.. 93 | // ---------- SMOKEALERT SEND ----------- 94 | RawSignal.Multiply=50; 95 | RawSignal.Repeats=10; 96 | RawSignal.Delay=20; 97 | RawSignal.Pulses[1]=FA20RFSTART/RawSignal.Multiply; 98 | //RawSignal.Pulses[2]=FA20RFSPACE/RawSignal.Multiply; 99 | //RawSignal.Pulses[3]=FA20RFSPACE/RawSignal.Multiply; 100 | RawSignal.Pulses[2]=(FA20RFSPACE+125)/RawSignal.Multiply; 101 | RawSignal.Pulses[3]=(FA20RFSPACE+25)/RawSignal.Multiply; 102 | for(byte x=49;x>=3;x=x-2) { 103 | RawSignal.Pulses[x]=FA20RFSPACE/RawSignal.Multiply; 104 | if ((bitstream & 1) == 1) 105 | RawSignal.Pulses[x+1] = FA20RFHIGH/RawSignal.Multiply; 106 | else 107 | RawSignal.Pulses[x+1] = FA20RFLOW/RawSignal.Multiply; 108 | bitstream = bitstream >> 1; 109 | } 110 | RawSignal.Pulses[51]=FA20RFSPACE/RawSignal.Multiply; 111 | RawSignal.Pulses[52]=0; 112 | RawSignal.Number=52; 113 | RawSendRF(); 114 | RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // restore setting 115 | success=true; 116 | } 117 | return success; 118 | } 119 | #endif // PLUGIN_080 120 | -------------------------------------------------------------------------------- /Plugins/Plugin_014.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-14: Ikea Koppla ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of sending and receiving the Ikea Koppla protocol 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Technical information: 14 | * Packets are variable length as zero bits are 2 pulses and 1 bits are single pulses. 15 | * Pulse lengths are ~1600 for a 0 bit and two times ~750 for a 1 bit 16 | * Packets contain 28 bits 17 | * 18 | * AAAA BBBB CCCCCCCCCC DD EEEEEE FF 19 | * 1110 0011 0000000001 01 000010 01 on 20 | * 1110 0011 0000000001 01 010110 01 off 21 | * 1110 1111 1111111111 00 001110 10 Pair 22 | * 23 | * A = Preamble, Always '1110' 24 | * B = System code 0-0x0f 25 | * C = Unit code bit selection, order: ch10,1,2,3,4,5,6,7,8,9 26 | * D = Checksum on B 27 | * E = Level and Fade 28 | * F = Checksum on D 29 | * 30 | * Sample: 31 | * 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; 32 | * 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; 33 | \*********************************************************************************************/ 34 | #define KOPPLA_PulseLength_MIN 36 35 | #define KOPPLA_PulseLength_MAX 52 36 | #define KOPPLA_PULSEMID 1300/RAWSIGNAL_SAMPLE_RATE 37 | #define KOPPLA_PULSEMAX 1850/RAWSIGNAL_SAMPLE_RATE 38 | #define KOPPLA_PULSEMIN 650/RAWSIGNAL_SAMPLE_RATE 39 | 40 | #ifdef PLUGIN_014 41 | boolean Plugin_014(byte function, char *string) { 42 | if ((RawSignal.Number < KOPPLA_PulseLength_MIN) || (RawSignal.Number > KOPPLA_PulseLength_MAX) ) return false; 43 | unsigned long bitstream=0L; 44 | 45 | byte preamble=0; 46 | unsigned int sysunit=0; 47 | byte levelfade=0; 48 | byte command=0; 49 | byte level=0; 50 | int i=0; 51 | 52 | byte checksum1=0; 53 | byte checksum2=0; 54 | byte checksum=0x03; 55 | byte tempcrc=0; 56 | // ========================================================================== 57 | for (byte x=1;x < RawSignal.Number;x++) { 58 | if (RawSignal.Pulses[x] > KOPPLA_PULSEMID) { // long pulse, 0 bit 59 | if (RawSignal.Pulses[x] > KOPPLA_PULSEMAX) return false; // long pulse is too long 60 | bitstream = (bitstream << 1); // 0 bit 61 | } else { // Short pulse 62 | if (RawSignal.Pulses[x] < KOPPLA_PULSEMIN) return false; // short pulse is too short 63 | if (RawSignal.Pulses[x+1] > KOPPLA_PULSEMID) return false; // need 2 short pulses for a 1 bit 64 | if (RawSignal.Pulses[x+1] < KOPPLA_PULSEMIN) return false; // second short pulse is too short 65 | x++; // skip second short pulse 66 | bitstream = (bitstream << 1) | 0x1; // 1 bit 67 | } 68 | } 69 | //================================================================================== 70 | // Sort data and perform sanity checks 71 | //================================================================================== 72 | if (bitstream==0) return false; // No bits detected? 73 | if ((((bitstream) >> 24)&0x0f) != 0x0e) return false; // Preamble should always be '1110' 74 | sysunit=(((bitstream) >> 10)& 0x03fff); // 4 bits system code and 10 bits unit code 75 | checksum1=(((bitstream) >> 8) &0x03); // first checksum 76 | levelfade=(((bitstream) >> 2)& 0x3f); // 6 bits level and face code 77 | checksum2=((bitstream)&0x03); // second checksum 78 | // calculate checksum 1 79 | checksum=3; 80 | for (i=0;i<7;i++) { 81 | tempcrc=((sysunit) >> (i*2)) & 3; 82 | checksum=checksum ^ tempcrc; 83 | } 84 | if (checksum1 != checksum) return false; 85 | // calculate checksum 2 86 | checksum=3; 87 | for (i=0;i<3;i++) { 88 | tempcrc=((levelfade) >> (i*2)) & 3; 89 | checksum=checksum ^ tempcrc; 90 | } 91 | if (checksum2 != checksum) return false; 92 | // sort command / dim bits 93 | if ((levelfade) == 0x2) { // on 94 | command=1; 95 | } else 96 | if ((levelfade) == 0x16) { // off 97 | command=0; 98 | } else 99 | if ((levelfade) == 0x0) { // up 100 | command=2; 101 | } else 102 | if ((levelfade) == 0x4) { // down 103 | command=3; 104 | } else { 105 | command=4; 106 | for (i=2;i<6;i++) { 107 | level=level<<1; 108 | level=level | ((levelfade)>>i)&0x01; 109 | } 110 | } 111 | //================================================================================== 112 | // ---------------------------------- 113 | // Output 114 | // ---------------------------------- 115 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 116 | Serial.print( pbuffer ); 117 | // ---------------------------------- 118 | Serial.print(F("Ikea Koppla;")); // Label 119 | sprintf(pbuffer, "ID=%04x;", sysunit); // ID 120 | Serial.print( pbuffer ); 121 | sprintf(pbuffer, "SWITCH=%02x;", levelfade); // ID 122 | Serial.print( pbuffer ); 123 | Serial.print(F("CMD=")); 124 | 125 | if ( command == 0) { 126 | Serial.print(F("OFF;")); 127 | } else 128 | if ( command == 1) { 129 | Serial.print(F("ON;")); 130 | } else 131 | if ( command == 2) { 132 | Serial.print(F("BRIGHT;")); 133 | } else 134 | if ( command == 3) { 135 | Serial.print(F("DIM;")); 136 | } else { 137 | sprintf(pbuffer, "SET_LEVEL=%d;", level ); 138 | Serial.print( pbuffer ); 139 | } 140 | Serial.println(); 141 | // ---------------------------------- 142 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 143 | RawSignal.Number=0; 144 | return true; 145 | } 146 | #endif //PLUGIN_014 147 | 148 | -------------------------------------------------------------------------------- /Plugins/Plugin_032.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-32 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 : StuntTeam 12 | * Support : 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 | * Technische informatie: 17 | * Message Format: (9 nibbles, 36 bits): 18 | * 19 | * Format for Temperature Humidity 20 | * AAAAAAAA AAAA BCDD EEEE EEEE EEEE FFFFFFFF 21 | * 01011100 0001 1000 1111 0111 1011 00001110 22 | 01110000 0000 1111 1011 0000 0000 00000101 23 | 10110101 0000 1x00 01001001 24 | 25 | 01000101 1000 0110 1111 0000 1100 00100110 26 | 01011111 1101 1000 0000 1111 0001 00001110 27 | 01000101 1000 0010 28 | * 29 | * A = Rolling Code 30 | * B = 1 (fixed value) 31 | * C = 0=scheduled transmission, 1=requested transmission (button press) 32 | * D = Channel number (00=ch1 01=ch2 10=ch3) 33 | * E = Temperature (two's complement) 34 | * F = Humidity BCD format 35 | * 36 | * 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; 37 | * 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; 38 | * 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; 39 | \*********************************************************************************************/ 40 | #ifdef PLUGIN_032 41 | boolean Plugin_032(byte function, char *string) { 42 | if (RawSignal.Number < 74 || RawSignal.Number > 78 ) return false; 43 | unsigned long bitstream=0L; 44 | int temperature=0; 45 | int humidity=0; 46 | byte rc=0; 47 | byte rc2=0; 48 | 49 | //================================================================================== 50 | byte start=0; 51 | if (RawSignal.Number == 78) start=4; 52 | if (RawSignal.Number == 76) start=2; 53 | for(int x=2+start; x<=56+start; x=x+2) { // Get first 28 bits 54 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; 55 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 3000) { 56 | bitstream = (bitstream << 1) | 0x01; 57 | } else { 58 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 1500) { 59 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false; 60 | bitstream = (bitstream << 1); 61 | } else { 62 | return false; 63 | } 64 | } 65 | } 66 | for(int x=58+start;x<=72+start; x=x+2) { // Get remaining 8 bits 67 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; 68 | if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) { 69 | humidity = (humidity << 1) | 0x01; 70 | } else { 71 | humidity = (humidity << 1); 72 | } 73 | } 74 | //================================================================================== 75 | // Prevent repeating signals from showing up 76 | //================================================================================== 77 | if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+3000) < millis()) ) { // 1000 78 | // not seen the RF packet recently 79 | if (bitstream == 0) return false; // Sanity check 80 | if (humidity==0) return false; // Sanity check 81 | } else { 82 | // already seen the RF packet recently 83 | return true; 84 | } 85 | //================================================================================== 86 | // Sort data 87 | rc = (bitstream >> 20) & 0xff; 88 | rc2= (bitstream >> 12) & 0xfb; 89 | if ( ((rc2)&0x08) != 0x08) return false; // needs to be 1 90 | temperature = (bitstream) & 0xfff; 91 | //fix 12 bit signed number conversion 92 | if ((temperature & 0x800) == 0x800) { 93 | temperature=4096-temperature; // fix for minus temperatures 94 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 95 | temperature=temperature | 0x8000; // turn highest bit on for minus values 96 | } else { 97 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 98 | } 99 | if (humidity > 99) return false; // Humidity out of range 100 | //================================================================================== 101 | // Output 102 | // ---------------------------------- 103 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number 104 | Serial.print( pbuffer ); 105 | // ---------------------------------- 106 | Serial.print(F("Alecto V4;")); // Label 107 | sprintf(pbuffer, "ID=%02x%02x;", rc, rc2); // ID 108 | Serial.print( pbuffer ); 109 | sprintf(pbuffer, "TEMP=%04x;", temperature); 110 | Serial.print( pbuffer ); 111 | if (humidity < 99) { // Only report valid humidty values 112 | sprintf(pbuffer, "HUM=%02d;", humidity); // decimal value.. 113 | Serial.print( pbuffer ); 114 | } 115 | Serial.println(); 116 | //================================================================================== 117 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 118 | RawSignal.Number=0; 119 | return true; 120 | } 121 | #endif // PLUGIN_032 122 | -------------------------------------------------------------------------------- /Plugins/Plugin_040.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-40 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 : StuntTeam 11 | * Support : 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 Mebus Weatherstation outdoor unit, (58 pulses, 28 bits, 433 MHz). 19 | * Mebus Message Format: 20 | * AAAA BBBB BBBB CCCC CCCC CCCC DDEF 21 | * 22 | * A = Checksum value AAAA=((BBBB+BBBB+CCCC+CCCC+DDEF)-1)&0x0f 23 | * B = Changes after each reset, no change during normal operation. (Device 'Session' ID) 24 | * 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) 25 | * D = Channel number 1/2/3 26 | * E = Always 1 27 | * F = 0 when "normal" data transmit, 1 when "requested" data transmit (TX button press) 28 | * 29 | * 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; 30 | * 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; 31 | * 20;81;Mebus;ID=6701;TEMP=010c; 32 | \*********************************************************************************************/ 33 | // ================================================================================== 34 | // MEBUS bit packets 35 | // 0000 1101 1001 0000 1100 1000 0111 36 | // 0100 1101 1001 0000 1101 1100 0110 37 | // 0100 1101 1001 0000 1100 1101 0110 38 | // 1001 1101 1001 0000 1101 1100 1011 39 | // 1011 1101 1001 0001 0000 1111 0110 27.1 40 | // 0010 0110 1110 0000 0000 1001 0110 0.9 41 | // 0011 0110 1110 1111 1000 0011 0110 -12.5 (1111 1000 0011=3971, 4096-3971=125 42 | // |----------|----------> temperature 0 - 51.1 43 | // |-|---------------------> set when minus temperatures -51.2 - 0 44 | // ================================================================================== 45 | #define MEBUS_PULSECOUNT 58 46 | 47 | #ifdef PLUGIN_040 48 | boolean Plugin_040(byte function, char *string) { 49 | if (RawSignal.Number != MEBUS_PULSECOUNT) return false; 50 | unsigned long bitstream=0L; 51 | unsigned int temperature=0; 52 | byte rc=0; 53 | byte checksum=0; 54 | byte data[7]; 55 | byte channel=0; 56 | //================================================================================== 57 | // get all 28 bits 58 | for(byte x=2;x <=MEBUS_PULSECOUNT-2;x+=2) { 59 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; // make sure inbetween pulses are not too long 60 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 3400) { 61 | bitstream = (bitstream << 1) | 0x1; 62 | } else { 63 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false; // invalid pulse length 64 | if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false; // invalid pulse length 65 | bitstream = (bitstream << 1); 66 | } 67 | } 68 | //================================================================================== 69 | // Prevent repeating signals from showing up 70 | //================================================================================== 71 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000> 24) & 0x0f; // prepare nibbles from bit stream 79 | data[1] = (bitstream >> 20) & 0x0f; 80 | data[2] = (bitstream >> 16) & 0x0f; 81 | data[3] = (bitstream >> 12) & 0x0f; 82 | data[4] = (bitstream >> 8) & 0x0f; 83 | data[5] = (bitstream >> 4) & 0x0f; 84 | data[6] = (bitstream >> 0) & 0x0f; 85 | //================================================================================== 86 | // first perform a checksum check to make sure the packet is a valid mebus packet 87 | checksum=data[1]+data[2]+data[3]+data[4]+data[5]+data[6]; 88 | checksum=(checksum-1)&0xf; 89 | if (checksum != data[0]) return false; 90 | //================================================================================== 91 | rc=(data[1]<<4) + data[2]; 92 | channel=(data[6])>>2; 93 | temperature=(data[3]<<8)+(data[4]<<4)+data[5]; 94 | if (temperature > 3000) { 95 | temperature=4096-temperature; // fix for minus temperatures 96 | if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees) 97 | temperature=temperature | 0x8000; // turn highest bit on for minus values 98 | } else { 99 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 100 | } 101 | //================================================================================== 102 | // Output 103 | // ---------------------------------- 104 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 105 | Serial.print( pbuffer ); 106 | Serial.print(F("Mebus;")); // Label 107 | sprintf(pbuffer, "ID=%02x%02x;", rc, channel);// ID 108 | Serial.print( pbuffer ); 109 | sprintf(pbuffer, "TEMP=%04x;", temperature); 110 | Serial.print( pbuffer ); 111 | Serial.println(); 112 | //================================================================================== 113 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 114 | RawSignal.Number=0; 115 | return true; 116 | } 117 | #endif // PLUGIN_040 118 | -------------------------------------------------------------------------------- /RawSignal.ino: -------------------------------------------------------------------------------- 1 | /*********************************************************************************************/ 2 | boolean ScanEvent(void) { // Deze routine maakt deel uit van de hoofdloop en wordt iedere 125uSec. doorlopen 3 | unsigned long Timer=millis()+SCAN_HIGH_TIME; 4 | 5 | while(Timer>millis() || RepeatingTimer>millis()) { 6 | if (FetchSignal(PIN_RF_RX_DATA,HIGH)) { // RF: *** data start *** 7 | if ( PluginRXCall(0,0) ) { // Check all plugins to see which plugin can handle the received signal. 8 | RepeatingTimer=millis()+SIGNAL_REPEAT_TIME; 9 | return true; 10 | } 11 | } 12 | }// while 13 | return false; 14 | } 15 | /**********************************************************************************************\ 16 | * Haal de pulsen en plaats in buffer. 17 | * bij de TSOP1738 is in rust is de uitgang hoog. StateSignal moet LOW zijn 18 | * bij de 433RX is in rust is de uitgang laag. StateSignal moet HIGH zijn 19 | * 20 | \*********************************************************************************************/ 21 | const unsigned long LoopsPerMilli=345; 22 | const unsigned long Overhead=0; 23 | 24 | // Because this is a time critical routine, we use global variables so that the variables 25 | // do not need to be initialized at each function call. 26 | int RawCodeLength=0; 27 | unsigned long PulseLength=0L; 28 | unsigned long numloops=0L; 29 | unsigned long maxloops=0L; 30 | 31 | boolean Ftoggle=false; 32 | uint8_t Fbit=0; 33 | uint8_t Fport=0; 34 | uint8_t FstateMask=0; 35 | /*********************************************************************************************/ 36 | boolean FetchSignal(byte DataPin, boolean StateSignal) { 37 | uint8_t Fbit = digitalPinToBitMask(DataPin); 38 | uint8_t Fport = digitalPinToPort(DataPin); 39 | uint8_t FstateMask = (StateSignal ? Fbit : 0); 40 | 41 | if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is 42 | // Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze 43 | // routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit 44 | // geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte 45 | // rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht. 46 | if (RawSignal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel... 47 | if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer! 48 | PulseLength=micros()+SIGNAL_TIMEOUT*1000; // delay 49 | while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros()) 50 | if ((*portInputRegister(Fport) & Fbit) == FstateMask) 51 | PulseLength=micros()+SIGNAL_TIMEOUT*1000; 52 | while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && (*portInputRegister(Fport) & Fbit) != FstateMask); 53 | } 54 | } 55 | RawCodeLength=1; // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc. 56 | Ftoggle=false; 57 | maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli); 58 | do{ // read the pulses in microseconds and place them in temporary buffer RawSignal 59 | numloops = 0; 60 | while (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) // while() loop *A* 61 | if (numloops++ == maxloops) break; // timeout 62 | PulseLength=((numloops + Overhead)* 1000) / LoopsPerMilli; // Contains pulslength in microseconds 63 | if (PulseLength=MIN_RAW_PULSES) { 68 | RawSignal.Repeats=0; // no repeats 69 | RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // sample size. 70 | RawSignal.Number=RawCodeLength-1; // Number of received pulse times (pulsen *2) 71 | RawSignal.Pulses[RawSignal.Number+1]=0; // Last element contains the timeout. 72 | RawSignal.Time=millis(); // Time the RF packet was received (to keep track of retransmits 73 | return true; 74 | } else { 75 | RawSignal.Number=0; 76 | } 77 | } 78 | return false; 79 | } 80 | /*********************************************************************************************/ 81 | // RFLink Board specific: Generate a short pulse to switch the Aurel Transceiver from TX to RX mode. 82 | void RFLinkHW( void ) { 83 | delayMicroseconds(36); 84 | digitalWrite(PIN_BSF_0,LOW); 85 | delayMicroseconds(16); 86 | digitalWrite(PIN_BSF_0,HIGH); 87 | return; 88 | } 89 | /*********************************************************************************************\ 90 | * Send rawsignal buffer to RF * DEPRICATED * DO NOT USE * 91 | \*********************************************************************************************/ 92 | void RawSendRF(void) { // * DEPRICATED * DO NOT USE * 93 | int x; 94 | digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen. 95 | digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan 96 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 97 | 98 | RawSignal.Pulses[RawSignal.Number]=1; // due to a bug in Arduino 1.0.1 99 | 100 | for(byte y=0; y 700) return false; 64 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 1400) { 65 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false; 66 | if (bitcounter < 24) { 67 | bitstream1 = (bitstream1 << 1) | 0x1; 68 | bitcounter++; // only need to count the first 10 bits 69 | } else { 70 | bitstream2 = (bitstream2 << 1) | 0x1; 71 | } 72 | } else { 73 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 1100) return false; 74 | if (RawSignal.Pulses[x]*RawSignal.Multiply < 500) return false; 75 | if (bitcounter < 24) { 76 | bitstream1 = (bitstream1 << 1); 77 | bitcounter++; // only need to count the first 10 bits 78 | } else { 79 | bitstream2 = (bitstream2 << 1); 80 | } 81 | } 82 | } 83 | //================================================================================== 84 | if (bitstream1==0) return false; // Perform sanity check 85 | if ((bitstream2 & 0xF00) != 0xF00) return false; // check if 'E' has all 4 bits set 86 | if ((bitstream2 & 0xfff) != 0xF00) { 87 | type=1; // Xiron 88 | if (RawSignal.Pulses[0] != PLUGIN_ID) { 89 | return false; // only accept plugin_001 translated Xiron packets 90 | } 91 | } else { 92 | type=0; // Auriol 93 | rc = (bitstream1 >> 12) & 0x07; // get 3 bits 94 | if (rc != 0) return false; // should always be '000' 95 | } 96 | //================================================================================== 97 | bat= (bitstream1 >> 15) & 0x01; // get battery strength indicator 98 | rc = (bitstream1 >> 16) & 0xff; // get rolling code 99 | channel = ((bitstream1 >> 12) & 0x3)+1; // channel indicator 100 | temperature = (bitstream1) & 0xfff; // get 12 temperature bits 101 | if (temperature > 3000) { 102 | temperature=4096-temperature; // fix for minus temperatures 103 | if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees) 104 | temperature=temperature | 0x8000; // turn highest bit on for minus values 105 | } else { 106 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 107 | } 108 | if (type == 1) { 109 | humidity = (bitstream2) & 0xff ; // humidity 110 | } 111 | //================================================================================== 112 | // Output 113 | // ---------------------------------- 114 | Serial.print("20;"); 115 | PrintHexByte(PKSequenceNumber++); 116 | if (type == 0) { 117 | Serial.print(F(";Auriol V2;ID=")); // Label 118 | } else { 119 | Serial.print(F(";Xiron;ID=")); // Label 120 | } 121 | PrintHexByte(rc); 122 | PrintHexByte(channel); 123 | // ---------------------------------- 124 | sprintf(pbuffer, ";TEMP=%04x;", temperature); 125 | Serial.print( pbuffer ); 126 | if (type == 1) { 127 | sprintf(pbuffer, "HUM=%02d;", humidity); 128 | Serial.print( pbuffer ); 129 | } 130 | if (bat==0) { // battery status 131 | Serial.print(F("BAT=LOW;")); 132 | } else { 133 | Serial.print(F("BAT=OK;")); 134 | } 135 | Serial.println(); 136 | //================================================================================== 137 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 138 | RawSignal.Number=0; 139 | return true; 140 | } 141 | #endif // PLUGIN_046 142 | -------------------------------------------------------------------------------- /Plugins/Plugin_100.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-100 AlectoV2 ## 4 | //## > 868 MHz Plugin < ## 5 | //####################################################################################################### 6 | 7 | /*********************************************************************************************\ 8 | * Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren 9 | * 10 | * Author : Martinus van den Broek 11 | * Support : 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 | * Technische informatie: 16 | * DKW2012 Message Format: (11 Bytes, 88 bits): 17 | * AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH IIIIIIII 18 | * Temperature Humidity Windspd_ Windgust Rain____ ________ Winddir Checksum 19 | * A = start/unknown, first 8 bits are always 11111111 20 | * B = Rolling code 21 | * C = Temperature (10 bit value with -400 base) 22 | * D = Humidity 23 | * E = windspeed (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108)) 24 | * F = windgust (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108)) 25 | * G = Rain ( * 0.3 mm) 26 | * H = winddirection (0 = north, 4 = east, 8 = south 12 = west) 27 | * I = Checksum, calculation is still under investigation 28 | * 29 | * WS3000 and ACH2010 systems have no winddirection, message format is 8 bit shorter 30 | * Message Format: (10 Bytes, 80 bits): 31 | * AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH 32 | * Temperature Humidity Windspd_ Windgust Rain____ ________ Checksum 33 | * 34 | * -------------------------------------------------------------------------------------------- 35 | * DCF Time Message Format: (NOT DECODED!, we already have time sync through webapp) 36 | * AAAAAAAA BBBBCCCC DDDDDDDD EFFFFFFF GGGGGGGG HHHHHHHH IIIIIIII JJJJJJJJ KKKKKKKK LLLLLLLL MMMMMMMM 37 | * 11 Hours Minutes Seconds Year Month Day ? Checksum 38 | * B = 11 = DCF 39 | * C = ? 40 | * D = ? 41 | * E = ? 42 | * F = Hours BCD format (7 bits only for this byte, MSB could be '1') 43 | * G = Minutes BCD format 44 | * H = Seconds BCD format 45 | * I = Year BCD format (only two digits!) 46 | * J = Month BCD format 47 | * K = Day BCD format 48 | * L = ? 49 | * M = Checksum 50 | \*********************************************************************************************/ 51 | #define DKW2012_MIN_PULSECOUNT 164 52 | #define DKW2012_MAX_PULSECOUNT 176 53 | #define ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception 54 | #define ACH2010_MAX_PULSECOUNT 160 55 | 56 | #ifdef PLUGIN_100 57 | 58 | uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len); 59 | 60 | boolean Plugin_100(byte function, char *string) { 61 | if (!(((RawSignal.Number >= ACH2010_MIN_PULSECOUNT) && (RawSignal.Number <= ACH2010_MAX_PULSECOUNT)) || ((RawSignal.Number >= DKW2012_MIN_PULSECOUNT) && (RawSignal.Number <= DKW2012_MAX_PULSECOUNT)))) return false; 62 | 63 | byte c=0; 64 | byte rfbit; 65 | byte data[10]; 66 | byte msgtype=0; 67 | byte rc=0; 68 | byte checksum=0; 69 | byte checksumcalc=0; 70 | byte maxidx = 8; 71 | //================================================================================== 72 | if(RawSignal.Number > ACH2010_MAX_PULSECOUNT) maxidx = 9; 73 | // Get message back to front as the header is almost never received complete for ACH2010 74 | byte idx = maxidx; 75 | for(byte x=RawSignal.Number; x>0; x=x-2) { 76 | if(RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE < 0x300) rfbit = 0x80; else rfbit = 0; 77 | data[idx] = (data[idx] >> 1) | rfbit; 78 | c++; 79 | if (c == 8) { 80 | if (idx == 0) break; 81 | c = 0; 82 | idx--; 83 | } 84 | } 85 | //================================================================================== 86 | checksum = data[maxidx]; 87 | checksumcalc = Plugin_100_ProtocolAlectoCRC8(data, maxidx); 88 | 89 | msgtype = (data[0] >> 4) & 0xf; // msg type must be 5 or 10 90 | rc = (data[0] << 4) | (data[1] >> 4); // rolling code 91 | 92 | if (checksum != checksumcalc) return false; 93 | if ((msgtype != 10) && (msgtype != 5)) return true; // why true? 94 | //================================================================================== 95 | unsigned int temp = 0; 96 | unsigned int rain=0; 97 | byte hum = 0; 98 | int wdir = 0; 99 | int wspeed = 0; 100 | int wgust = 0; 101 | 102 | temp = (((data[1] & 0x3) * 256 + data[2]) - 400); 103 | hum = data[3]; 104 | wspeed = data[4] * 108; 105 | wspeed = wspeed / 10; 106 | wgust = data[5] * 108; 107 | wgust = wgust / 10; 108 | rain = (data[6] * 256) + data[7]; 109 | if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) { 110 | wdir = (data[8] & 0xf); 111 | } 112 | // ---------------------------------- 113 | // Output 114 | // ---------------------------------- 115 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 116 | Serial.print( pbuffer ); 117 | // ---------------------------------- 118 | if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) { 119 | Serial.print("DKW2012;"); // Label 120 | } else { 121 | Serial.print("Alecto V2;"); // Label 122 | } 123 | sprintf(pbuffer, "ID=00%02x;", rc); // ID 124 | Serial.print( pbuffer ); 125 | sprintf(pbuffer, "TEMP=%04x;", temp); 126 | Serial.print( pbuffer ); 127 | sprintf(pbuffer, "HUM=%02x;", hum); 128 | Serial.print( pbuffer ); 129 | sprintf(pbuffer, "WINSP=%04x;", wspeed); 130 | Serial.print( pbuffer ); 131 | sprintf(pbuffer, "WINGS=%04x;", wgust); 132 | Serial.print( pbuffer ); 133 | sprintf(pbuffer, "RAIN=%04x;", rain); 134 | Serial.print( pbuffer ); 135 | if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) { 136 | sprintf(pbuffer, "WINDIR=%04d;", wdir); 137 | Serial.print( pbuffer ); 138 | } 139 | Serial.println(); 140 | // ---------------------------------- 141 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 142 | RawSignal.Number=0; // do not process the packet any further 143 | return true; 144 | } 145 | 146 | /*********************************************************************************************\ 147 | * Calculates CRC-8 checksum 148 | * reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/ 149 | * http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/ 150 | * https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp 151 | \*********************************************************************************************/ 152 | uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len) { 153 | uint8_t crc = 0; 154 | // Indicated changes are from reference CRC-8 function in OneWire library 155 | while (len--) { 156 | uint8_t inbyte = *addr++; 157 | for (uint8_t i = 8; i; i--) { 158 | uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01 159 | crc <<= 1; // changed from right shift 160 | if (mix) crc ^= 0x31;// changed from 0x8C; 161 | inbyte <<= 1; // changed from right shift 162 | } 163 | } 164 | return crc; 165 | } 166 | #endif // PLUGIN_100 167 | -------------------------------------------------------------------------------- /Plugins/Plugin_075.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-75 Lidl doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Lidl/SilverCrest Doorbell protocol for model Z31370-TX 7 | * 8 | * Author : StuntTeam 9 | * Support : www.nodo-domotica.nl 10 | * Date : 9-02-2015 11 | * Version : 1.0 12 | * Compatibility : RFLink 1.0 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 | * Changelog: v1.0 initial release 17 | ********************************************************************************************* 18 | * Technical Information: 19 | * Decodes signals from a Lidl Doorbell, (90 pulses, 40 bits, 433 MHz). 20 | * Lidl Doorbell Message Format: 21 | * 1010 1111 1000 0010 0001 1011 0011 0000 0000 0000 AF821B3000 22 | * -------------- always zero 23 | * 24 | * Sample packet: (Nodo Pulse timing) 25 | * 1850,1200,1400,1200,1400,1200,1400,1200,1400, (Preamble) 26 | * 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, 27 | * 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, 28 | * 200,900,200,900,250,900,200 29 | ********************************************************************************************* 30 | * Technical Information: 31 | * Decodes signals from a Lidl SilverCrest Z31370-TX Doorbell, (114 pulses, 48 bits, 433 MHz). 32 | * SilverCrest Doorbell Message Format: 33 | * 01011100 10100101 10001000 | 00000100 11010110 10111011 10010111 5CA588 04D6BB97 34 | * always the same | device unique number 35 | * 36 | * Sample packet: 37 | * 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; 38 | \*********************************************************************************************/ 39 | // ================================================================================== 40 | #define LIDL_PULSECOUNT 90 // type 0 41 | #define LIDL_PULSECOUNT2 114 // type 1 42 | #define PLUGIN_ID 75 43 | 44 | #ifdef PLUGIN_075 45 | boolean Plugin_075(byte function, char *string) { 46 | if ((RawSignal.Number != LIDL_PULSECOUNT) && (RawSignal.Number != LIDL_PULSECOUNT2)) return false; 47 | unsigned long bitstream=0; 48 | unsigned long bitstream2=0; 49 | 50 | int bitcount=0; 51 | byte type=0; 52 | //================================================================================== 53 | // get all bits 54 | if (RawSignal.Number == LIDL_PULSECOUNT) { 55 | if (RawSignal.Pulses[1]*RawSignal.Multiply > 1000 && RawSignal.Pulses[2]*RawSignal.Multiply > 1000 && 56 | RawSignal.Pulses[3]*RawSignal.Multiply > 1000 && RawSignal.Pulses[4]*RawSignal.Multiply > 1000 && 57 | RawSignal.Pulses[5]*RawSignal.Multiply > 1000 && RawSignal.Pulses[6]*RawSignal.Multiply > 1000 && 58 | RawSignal.Pulses[7]*RawSignal.Multiply > 1000 && RawSignal.Pulses[8]*RawSignal.Multiply > 1000 && RawSignal.Pulses[9]*RawSignal.Multiply > 1000 ) { 59 | // 60 | } else { 61 | return false; 62 | } 63 | for(int x=10;x <=90;x+=2) { 64 | if (bitcount < 28){ 65 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) { 66 | bitstream = (bitstream << 1); 67 | bitcount++; 68 | } else { 69 | bitstream = (bitstream << 1) | 0x1; 70 | bitcount++; 71 | } 72 | } else { 73 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) { 74 | bitstream2 = (bitstream2 << 1); 75 | bitcount++; 76 | } else { 77 | bitstream2 = (bitstream2 << 1) | 0x1; 78 | bitcount++; 79 | } 80 | } 81 | } 82 | } else { 83 | if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets 84 | type=1; 85 | for(byte x=1;x < LIDL_PULSECOUNT2-1;x+=2) { 86 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 200) { 87 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 200) return false; // invalid pulse length 88 | if (bitcount > 23) { 89 | bitstream2 = (bitstream2 << 1); 90 | } else { 91 | bitstream = (bitstream << 1); 92 | } 93 | bitcount++; 94 | } else { 95 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 200) return false; // invalid pulse length 96 | if (bitcount > 23) { 97 | bitstream2 = (bitstream2 << 1) | 0x1; 98 | } else { 99 | bitstream = (bitstream << 1) | 0x1; 100 | } 101 | bitcount++; 102 | } 103 | } 104 | } 105 | //================================================================================== 106 | // all bytes received, make sure checksum is okay 107 | //================================================================================== 108 | if (type==0) { 109 | if ((bitstream2 &0xfff) != 0x00) return false; // these 8 bits are always 0 110 | } else { 111 | if (bitstream != 0x5ca588) return false; 112 | } 113 | //================================================================================== 114 | // Prevent repeating signals from showing up 115 | //================================================================================== 116 | if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000) 675) return false; // First pulse is start bit and should be short! 43 | for(byte x=2;x < DELTRONIC_PULSECOUNT;x=x+2) { 44 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 800) { // long pulse (800-1275) 45 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1275) return false; // pulse too long to be valid 46 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 675) return false; // invalid manchestercode (10 01) 47 | bitstream = (bitstream << 1) | 0x1; // 10 => 1 bit 48 | } else { // short pulse 49 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 250) return false; // too short 50 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 700) return false; // invalid manchestercode (10 01) 51 | bitstream = bitstream << 1; // 01 => 0 bit 52 | } 53 | } 54 | //================================================================================== 55 | // Prevent repeating signals from showing up 56 | //================================================================================== 57 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000>= 1; 152 | } 153 | // Send sync 154 | digitalWrite(PIN_RF_TX_DATA, LOW); 155 | delayMicroseconds(periodSync); 156 | digitalWrite(PIN_RF_TX_DATA, HIGH); 157 | delayMicroseconds(period); 158 | } 159 | 160 | digitalWrite(PIN_RF_TX_DATA, LOW); 161 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 162 | digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter 163 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver 164 | RFLinkHW(); 165 | } 166 | #endif // PLUGIN_TX_073 167 | -------------------------------------------------------------------------------- /Doc/RFLink Protocol Reference.txt: -------------------------------------------------------------------------------- 1 | RFLink Gateway Commands and Data fields 2 | 3 | The use of this protocol is free for both server and client sides of the implementation 4 | Data is send serial (via USB) as "text" at a speed of 57600 baud (N,8,1) 5 | It is sufficient to open a port and listen to the data. 6 | Each text line contains information that has been received via RF signals. 7 | 8 | 9 | Packet structure - Received data from RF: 10 | ----------------------------------------- 11 | 20;ID=9999;Name;LABEL=data; 12 | 13 | 20 => Node number 20 means from the RFLink Gateway to the master, 10 means from the master to the RFLink Gateway 14 | ; => field separator 15 | NAME => Device name (can be used to display in applications etc.) 16 | LABEL=data => contains the field type and data for that field, can be present multiple times per device 17 | 18 | 19 | Data Fields: (LABEL=data) 20 | ------------ 21 | ID=9999 => device ID (often a rolling code and/or device channel number) 22 | SWITCH=A16 => House/Unit code like A1, P2, B16 or a button number etc. 23 | CMD=ON => Command (ON/OFF/ALLON/ALLOFF) 24 | SET_LEVEL=15 => Direct dimming level setting value 25 | TEMP=9999 => Temperature (hexadecimal), high bit contains negative sign, needs devision by 10 26 | HUM=99 => Humidity (hexadecimal) 27 | BARO=9999 => Barometric pressure (hexadecimal) 28 | HSTATUS=99 => 0=Normal, 1=Comfortable, 2=Dry, 3=Wet 29 | BFORECAST=99 => 0=No Info/Unknown, 1=Sunny, 2=Partly Cloudy, 3=Cloudy, 4=Rain 30 | UV=9999 => UV intensity (hexadecimal) 31 | LUX=9999 => Light intensity (hexadecimal) 32 | BAT=OK => Battery status indicator (OK/LOW) 33 | RAIN=1234 => rain rate in mm. (hexadecimal) 34 | RAINTOT=1234 => total rain in mm. (hexadecimal) 35 | WINSP=9999 => Wind speed in km. p/h (hexadecimal) needs devision by 10 36 | AWINSP=9999 => Average Wind speed in km. p/h (hexadecimal) needs devision by 10 37 | WINGS=9999 => Wind Gust in km. p/h (hexadecimal) 38 | WINDIR=123 => Wind direction 0-15 reflecting 0-360 degrees in 22.5 degree steps (decimal) 39 | WINCHL => wind chill (hexadecimal) 40 | WINTMP=1234 => Wind meter temperature reading (hexadecimal) 41 | CHIME=123 => Chime/Doorbell melody number 42 | SMOKEALERT=ON => ON/OFF 43 | PIR=ON => ON/OFF 44 | CO2=1234 => CO2 air quality 45 | SOUND=1234 => Noise level 46 | KWATT=1234 => KWatt 47 | WATT=1234 => Watt 48 | DIST=1234 => Distance 49 | METER=1234 => Water flow meter 50 | VOLT=1234 => Voltage 51 | CURRENT=1234 => Current 52 | 53 | 54 | Sample data of received RF packets: 55 | ----------------------------------- 56 | 20;2D;UPM/Esic;ID=0001;TEMP=00cf;HUM=16;BAT=OK; 57 | 20;6A;UPM/Esic;ID=1002;WINSP=0041;WINDIR=5A;BAT=OK; 58 | 20;08;UPM/Esic;ID=1003;RAIN=0010;BAT=OK; 59 | 20;31;Mebus;ID=c201;TEMP=00cf; 60 | 20;32;Auriol;ID=008f;TEMP=00d3;BAT=OK; 61 | 20;A2;Auriol V2;ID=008f;TEMP=00a3;BAT=LOW; 62 | 20;33;Cresta;ID=3001;TEMP=00b0;HUM=50; 63 | 20;0C;Cresta;ID=8001;RAIN=001c; 64 | 20;47;Cresta;ID=8001;WINDIR=0002;WINSP=0060;WINGS=0088;WINCHL=b0; 65 | 20;47;Cresta;ID=8001;TEMP=00b0;UV=00d0; 66 | 20;36;Alecto V1;ID=ec02;TEMP=00d1;HUM=14; 67 | 20;07;Mebus;ID=ea01;TEMP=0017; 68 | 20;3D;Alecto V1;ID=2000;TEMP=0011;HUM=61; 69 | 20;26;Alecto V1;ID=0086;RAIN=02ac; 70 | 20;30;Alecto V1;ID=0020;WINSP=0068; 71 | 20;16;Alecto V1;ID=0020;WINSP=0020; 72 | 20;17;Alecto V1;ID=0020;WINDIR=0002;WINGS=0088; 73 | 20;36;Alecto V1;ID=0020;WINDIR=0002;WINGS=0040; 74 | 20;74;Oregon TempHygro;ID=0ACC;TEMP=00be;HUM=40;BAT=OK; 75 | 20;b3;Oregon TempHygro;ID=1a2d;TEMP=00dd;HUM=43;BAT=OK; 76 | 20;e5;Oregon BTHR;ID=5a6d;TEMP=00be;HUM=40;BARO=03d7;BAT=OK; 77 | 20;46;Oregon Rain;ID=2a1d;RAIN=0012;RAINTOT=0012;BAT=OK; 78 | 20;83;Oregon Rain2;ID=2a19;RAIN=002a;RAINTOT=0054;BAT=OK; 79 | 20;32;Oregon Wind;ID=1a89;WDIR=0045;WINSP=0068;AWINSP=0050;BAT=OK; 80 | 20;4a;Oregon Wind2;ID=3a0d;WDIR=0021;WINSP=0040;AWINSP=005a;BAT=OK; 81 | 20;ba;Oregon UVN128/138;ID=ea7c;UV=0030;BAT=OK; 82 | 20;AF;SelectPlus;ID=1bb4;CHIME=01; 83 | 20;FC;Plieger York;ID=dd01;CHIME=02; 84 | 20;47;Byron SX;ID=a66a;CHIME=A9; 85 | 20;12;Pir;ID=aa66;PIR=ON; 86 | 20;63;SmokeAlert;ID=123456;SMOKEALERT=ON; 87 | 20;06;Kaku;ID=41;SWITCH=1;CMD=ON; 88 | 20;0C;Kaku;ID=41;SWITCH=2;CMD=OFF; 89 | 20;0D;Kaku;ID=41;SWITCH=2;CMD=ON; 90 | 20;46;Kaku;ID=44;SWITCH=4;CMD=OFF; 91 | 20;E0;NewKaku;ID=cac142;SWITCH=1;CMD=ALLOFF; 92 | 20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF; 93 | 20;0B;NewKaku;ID=000005;SWITCH=2;CMD=ON; 94 | 20;0E;NewKaku;ID=000005;SWITCH=2;CMD=OFF; 95 | 20;12;NewKaku;ID=000002;SWITCH=2;CMD=OFF; 96 | 20;1E;NewKaku;ID=00000a;SWITCH=2;CMD=OFF; 97 | 20;1F;NewKaku;ID=00000a;SWITCH=2;CMD=ON; 98 | 20;01;NewKaku;ID=000007;SWITCH=2;CMD=OFF; 99 | 20;04;NewKaku;ID=000007;SWITCH=2;CMD=ON; 100 | 20;04;NewKaku;ID=000007;SWITCH=2;CMD=SET_LEVEL=14; 101 | 20;0C;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLON; 102 | 20;AD;FA500;ID=0d00b900;SWITCH=0001;CMD=UNKOWN; 103 | 20;AE;FA500;ID=0a01;SWITCH=0a01;CMD=OFF; 104 | 20;03;Eurodomest;ID=03696b;SWITCH=00;CMD=OFF; 105 | 20;04;Eurodomest;ID=03696b;SWITCH=07;CMD=ALLOFF; 106 | 20;41;Conrad RSL2;ID=010002;SWITCH=03;CMD=ON; 107 | 20;47;Blyss;ID=ff98;SWITCH=A1;CMD=ON; 108 | 20;73;Kambrook;ID=010203;SWITCH=A1;CMD=OFF; 109 | 110 | Note that for sensors that only report values like temperature, only the data and the ID are required. 111 | Name labels can be thrown away or used for cosmetic purposes. 112 | 113 | For switches, the protocol name has to be stored and re-used on the transmission side. 114 | Thus, when a remote control is used to control a device data like below will be send from the RFLink Gateway over USB: 115 | 20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF; 116 | When the state of this switch needs to be changed the following command has to be send: 117 | 10;NewKaku;0cac142;3;ON; 118 | The name label (here "NewKaku") is used to tell the RFLink Gateway what protocol it has to use for the RF broadcast. 119 | 120 | 121 | 122 | Special Control Commands - Send: 123 | -------------------------------- 124 | 10;REBOOT; => Reboot RFLink Gateway hardware 125 | 10;PING; => a "keep alive" function. Is replied with: 20;99;PONG; 126 | 10;VERSION; => Version and build indicator. Is replied with: 20;99;"RFLink Gateway software version"; 127 | 10;RFDEBUG=ON; => ON/OFF to Enable/Disable showing of RF packets. Is replied with: 20;99;RFDEBUG="state"; 128 | 10;RFUDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;RFUDEBUG="state"; 129 | 10;QRFDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;QRFDEBUG="state"; 130 | QRFDEBUG is a faster version of RFUDEBUG but all pulse times are shown in hexadecimal and need to be multiplied by 30 131 | 132 | 133 | Packet structure - To Send data via RF: 134 | --------------------------------------- 135 | 10;Protocol Name;device address,button number;action; 136 | 137 | Sample data of transmitted RF packets: 138 | -------------------------------------- 139 | 10;Kaku;00004d;1;OFF; => Kaku/ARC protocol;address;action (ON/OFF) 140 | 10;AB400D;00004d;1;OFF; => Sartano protocol;address;action (ON/OFF) 141 | 10;Impuls;00004d;1;OFF; => Impuls protocol;address;action (ON/OFF) 142 | 10;NewKaku;00c142;1;ON; => Newkaku/AC protocol;address (24 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level) 143 | 10;NewKaku;128ac4d;1;OFF; => Newkaku/AC protocol;address (28 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level) 144 | 10;Eurodomest;123456;01;ON; => Eurodomest protocol;address;button number;action (ON/OFF/ALLON/ALLOFF) 145 | 10;Blyss;ff98;A1;OFF; => Blyss protocol;address;button;action (ON/OFF/ALLON/ALLOFF) 146 | 10;Conrad;ff0607;1;OFF; => Conrad RSL protocol, address, button number, action (ON/OFF/ALLON/ALLOFF) 147 | 10;Kambrook;050325;a1;ON; => Kambrook protocol, address, unit/button number, action (ON/OFF) 148 | 10;X10;000041;1;OFF; => X10 protocol;address;action (ON/OFF) 149 | 10;HomeConfort;01b523;D3;ON;=> HomeConfort protocol;address;action (ON/OFF) 150 | 10;FA500;001b523;D3;ON; => Flamingo protocol;address;action (ON/OFF) 151 | 10;Powerfix;000080;0;ON; => Powerfix/Quigg/Chacon protocol;address;action (ON/OFF) 152 | 10;Ikea Koppla;000080;0;ON; => Koppla protocol;address;action (ON/OFF) 153 | 10;HomeEasy;7900b100;3;ON; => Home Easy protocol;address;action (ON/OFF/ALLON/ALLOFF) 154 | 10;EV1527;000080;0;ON; => EV1527 protocol;address;device 0x00-0x0f,action ON/OFF 155 | 10;Chuango;000080;2;ON; => Chuango Protocol;address;action (ON/OFF/ALLON/ALLOFF) 156 | 10;Selectplus;001c33; => SelectPlus protocol;address 157 | 10;Byron;112233;01;OFF; => Dyron SX protocol;address;ringtone 158 | 10;DELTRONIC;001c33; => Deltronic protocol;address 159 | 10;BYRON;00009F;01;ON; => Byron protocol;address;chime number,command 160 | 10;FA20RF;67f570;1;ON; => Flamingo FA20RF / FA21 / KD101 protocol, address, button number, action (ON/OFF/ALLON/ALLOFF) 161 | 10;MERTIK;64;UP; => Mertik protocol, address, command 162 | -------------------------------------------------------------------------------- /Plugins/Plugin_082.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-082 Mertik Maxitrol ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces 7 | * PCB markings: G6R H4T1. 8 | * 9 | * Author : StuntTeam 10 | * Support : http://sourceforge.net/projects/rflink/ 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 | * 18 | * 0001100101101001011001101 19 | * ----------------------- data bits (10=1 01=0) 20 | * -- preamble, always 00? 21 | * Shortened: (10=1 01=0) 22 | * 01100101101001011001101 23 | * 0 1 0 0 1 1 0 0 1 0 1 1 24 | * 25 | * 010011001011 26 | * ---- command => 4 bits 27 | * -------- address => 8 bits 28 | * 29 | * command bits: 30 | * 0111 7 off 31 | * 0011 3 on 32 | * 1011 b up 33 | * 1101 d down 34 | * 1000 8 stop 35 | * 1010 a go up 36 | * 1100 c go down 37 | * 38 | * Sample RF packet: 39 | * Pulses=26;Pulses(uSec)=475,300,325,700,325,700,325,700,325,700,725,300,725,300,725,300,725,300,725,300,325,700,725,300,725; 40 | \*********************************************************************************************/ 41 | #define MAXITROL_PULSECOUNT 26 42 | 43 | #define PLUGIN_082_RFSTART 100 44 | #define PLUGIN_082_RFSPACE 250 45 | #define PLUGIN_082_RFLOW 400 46 | #define PLUGIN_082_RFHIGH 750 47 | 48 | #ifdef PLUGIN_082 49 | boolean Plugin_082(byte function, char *string) { 50 | if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false; 51 | unsigned int bitstream=0L; 52 | byte address=0; 53 | byte command=0; 54 | byte status=0; 55 | //================================================================================== 56 | // get bits 57 | for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) { 58 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) { 59 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false; 60 | bitstream = (bitstream << 1); // 0 61 | } else { 62 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false; 63 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 64 | bitstream = (bitstream << 1) | 0x1; // 1 65 | } 66 | } 67 | //================================================================================== 68 | // all bytes received, make sure packet is valid 69 | if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 70 | if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 71 | //================================================================================== 72 | // Prevent repeating signals from showing up 73 | //================================================================================== 74 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer>4)&0xff; 84 | if (command == 0xB) status=1; // up 85 | else if (command == 0xD) status=2; // down 86 | else if (command == 0x7) status=3; // off 87 | else if (command == 0x3) status=4; // on 88 | else if (command == 0x8) status=5; // stop 89 | else if (command == 0xa) status=6; // go up 90 | else if (command == 0xc) status=7; // go down 91 | else { 92 | return false; 93 | } 94 | //================================================================================== 95 | // Output 96 | // ---------------------------------- 97 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 98 | Serial.print( pbuffer ); 99 | Serial.print(F("Mertik;")); // Label 100 | sprintf(pbuffer, "ID=%02x;", address); // ID 101 | Serial.print( pbuffer ); 102 | sprintf(pbuffer, "SWITCH=%02x;", status); 103 | Serial.print( pbuffer ); 104 | Serial.print(F("CMD=")); 105 | if (status==1) Serial.print(F("UP;")); 106 | if (status==2) Serial.print(F("DOWN;")); 107 | if (status==3) Serial.print(F("OFF;")); 108 | if (status==4) Serial.print(F("ON;")); 109 | if (status==5) Serial.print(F("STOP;")); 110 | if (status==6) Serial.print(F("GOUP;")); 111 | if (status==7) Serial.print(F("GODOWN;")); 112 | Serial.println(); 113 | //================================================================================== 114 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 115 | RawSignal.Number=0; 116 | return true; 117 | } 118 | #endif // PLUGIN_082 119 | 120 | #ifdef PLUGIN_TX_082 121 | boolean PluginTX_082(byte function, char *string) { 122 | boolean success=false; 123 | unsigned long bitstream=0L; 124 | //10;MERTIK;64;UP; 125 | //0123456789012345 126 | if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg. 127 | if (InputBuffer_Serial[12] != ';') return false; 128 | unsigned int bitstream2=0; // holds last 8 bits 129 | 130 | InputBuffer_Serial[8]=0x30; 131 | InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value 132 | InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value 133 | bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits) 134 | 135 | if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8; 136 | else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3; 137 | else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7; 138 | else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB; 139 | else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD; 140 | else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA; 141 | else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC; 142 | if (bitstream2==0) return false; 143 | //----------------------------------------------- 144 | RawSignal.Multiply=50; 145 | RawSignal.Repeats=10; 146 | RawSignal.Delay=20; 147 | RawSignal.Pulses[1]=PLUGIN_082_RFLOW/RawSignal.Multiply; 148 | RawSignal.Pulses[2]=PLUGIN_082_RFLOW/RawSignal.Multiply; 149 | for(byte x=18;x>=3;x=x-2) { 150 | if ((bitstream & 1) == 1) { 151 | RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply; 152 | RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply; 153 | } else { 154 | RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply; 155 | RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply; 156 | } 157 | bitstream = bitstream >> 1; 158 | } 159 | for(byte x=26;x>=19;x=x-2) { 160 | if ((bitstream2 & 1) == 1) { 161 | RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply; 162 | RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply; 163 | } else { 164 | RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply; 165 | RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply; 166 | } 167 | bitstream2 = bitstream2 >> 1; 168 | } 169 | RawSignal.Pulses[27]=PLUGIN_082_RFSTART/RawSignal.Multiply; 170 | RawSignal.Number=27; 171 | RawSendRF(); 172 | success=true; 173 | //----------------------------------------------- 174 | } 175 | return success; 176 | } 177 | #endif // PLUGIN_082 178 | -------------------------------------------------------------------------------- /Plugins/Plugin_081.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-082 Mertik Maxitrol ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces 7 | * PCB markings: G6R H4TB / G6R 4HT. 8 | * 9 | * Author : StuntTeam 10 | * Support : http://sourceforge.net/projects/rflink/ 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 | * 18 | * 0001100101101001011001101 19 | * ----------------------- data bits (10=1 01=0) 20 | * -- preamble, always 00? 21 | * Shortened: (10=1 01=0) 22 | * 01100101101001011001101 23 | * 0 1 0 0 1 1 0 0 1 0 1 1 24 | * 25 | * 010011001011 26 | * ---- command => 4 bits 27 | * -------- address => 8 bits 28 | * 29 | * command bits: 30 | * 0111 7 off 31 | * 0011 3 on 32 | * 1011 b up 33 | * 1101 d down 34 | * 1000 8 stop 35 | * 1010 a go up 36 | * 1100 c go down 37 | * 38 | * Sample RF packet: 39 | * Pulses=26;Pulses(uSec)=475,300,325,700,325,700,325,700,325,700,725,300,725,300,725,300,725,300,725,300,325,700,725,300,725; 40 | \*********************************************************************************************/ 41 | #define MAXITROL_PULSECOUNT 46 42 | 43 | #define PLUGIN_081_RFSTART 100 44 | #define PLUGIN_081_RFSPACE 250 45 | #define PLUGIN_081_RFLOW 400 46 | #define PLUGIN_081_RFHIGH 750 47 | 48 | #ifdef PLUGIN_081 49 | boolean Plugin_081(byte function, char *string) { 50 | if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false; 51 | unsigned int bitstream=0L; 52 | byte address=0; 53 | byte command=0; 54 | byte status=0; 55 | //================================================================================== 56 | // get bits 57 | for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) { 58 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) { 59 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false; 60 | bitstream = (bitstream << 1); // 0 61 | } else { 62 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false; 63 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 64 | bitstream = (bitstream << 1) | 0x1; // 1 65 | } 66 | } 67 | //================================================================================== 68 | // all bytes received, make sure packet is valid 69 | if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 70 | if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false; 71 | //================================================================================== 72 | // Prevent repeating signals from showing up 73 | //================================================================================== 74 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer>4)&0xff; 84 | if (command == 0xB) status=1; // up 85 | else if (command == 0xD) status=2; // down 86 | else if (command == 0x7) status=3; // off 87 | else if (command == 0x3) status=4; // on 88 | else if (command == 0x8) status=5; // stop 89 | else if (command == 0xa) status=6; // go up 90 | else if (command == 0xc) status=7; // go down 91 | else { 92 | return false; 93 | } 94 | //================================================================================== 95 | // Output 96 | // ---------------------------------- 97 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 98 | Serial.print( pbuffer ); 99 | Serial.print(F("Mertik;")); // Label 100 | sprintf(pbuffer, "ID=%02x;", address); // ID 101 | Serial.print( pbuffer ); 102 | sprintf(pbuffer, "SWITCH=%02x;", status); 103 | Serial.print( pbuffer ); 104 | Serial.print(F("CMD=")); 105 | if (status==1) Serial.print(F("UP;")); 106 | if (status==2) Serial.print(F("DOWN;")); 107 | if (status==3) Serial.print(F("OFF;")); 108 | if (status==4) Serial.print(F("ON;")); 109 | if (status==5) Serial.print(F("STOP;")); 110 | if (status==6) Serial.print(F("GOUP;")); 111 | if (status==7) Serial.print(F("GODOWN;")); 112 | Serial.println(); 113 | //================================================================================== 114 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 115 | RawSignal.Number=0; 116 | return true; 117 | } 118 | #endif // PLUGIN_081 119 | 120 | #ifdef PLUGIN_TX_081 121 | boolean PluginTX_081(byte function, char *string) { 122 | boolean success=false; 123 | unsigned long bitstream=0L; 124 | //10;MERTIK;64;UP; 125 | //0123456789012345 126 | if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg. 127 | if (InputBuffer_Serial[12] != ';') return false; 128 | unsigned int bitstream2=0; // holds last 8 bits 129 | 130 | InputBuffer_Serial[8]=0x30; 131 | InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value 132 | InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value 133 | bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits) 134 | 135 | if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8; 136 | else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3; 137 | else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7; 138 | else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB; 139 | else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD; 140 | else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA; 141 | else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC; 142 | if (bitstream2==0) return false; 143 | //----------------------------------------------- 144 | RawSignal.Multiply=50; 145 | RawSignal.Repeats=10; 146 | RawSignal.Delay=20; 147 | RawSignal.Pulses[1]=PLUGIN_081_RFLOW/RawSignal.Multiply; 148 | RawSignal.Pulses[2]=PLUGIN_081_RFLOW/RawSignal.Multiply; 149 | for(byte x=18;x>=3;x=x-2) { 150 | if ((bitstream & 1) == 1) { 151 | RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply; 152 | RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply; 153 | } else { 154 | RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply; 155 | RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply; 156 | } 157 | bitstream = bitstream >> 1; 158 | } 159 | for(byte x=26;x>=19;x=x-2) { 160 | if ((bitstream2 & 1) == 1) { 161 | RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply; 162 | RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply; 163 | } else { 164 | RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply; 165 | RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply; 166 | } 167 | bitstream2 = bitstream2 >> 1; 168 | } 169 | RawSignal.Pulses[27]=PLUGIN_081_RFSTART/RawSignal.Multiply; 170 | RawSignal.Number=27; 171 | RawSendRF(); 172 | success=true; 173 | //----------------------------------------------- 174 | } 175 | return success; 176 | } 177 | #endif // PLUGIN_081 178 | -------------------------------------------------------------------------------- /Plugins/Plugin_070.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-70 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 : StuntTeam 11 | * Support : 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 | * There are two known models: 20 | * SelectPlus (200689103 - Black - Datecode:0614) also sold as "1 by One" (O00 QH-0031) 21 | * PCB details: Quhwa, QH-C-CE-3V, 09.10.16, CPU: MC908T 22 | * SelectPlus (200689101 - White - Datecode:0914) 23 | * PCB details: Quhwa, QH-C-CE-3V, REV1.0, CPU: MC908T 24 | * 25 | * Each frame is 35 pulses long. It is composed of: 26 | * 101011001010110010110011010 10101010 27 | * The first block appears to be an unique ID 28 | * The second block appears to be some kind of identifier which always is 0xAA (10101010) 29 | * Converting the pulses into bits results in a 13 bit unique address and a 4 bit identifier: 30 | * 31 | * B) 1110000110011 0000 => 1C33 0 B)lack push button 32 | * W) 1101110110100 0000 => 1BB4 0 W)hite push button 33 | * 34 | * Note: The transmitter sends 43 times the same packet when the bell button is pressed 35 | * the retransmit is killed to prevent reporting the same press multiple times 36 | * 37 | * Sample: 38 | * 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; 39 | * 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; 40 | * 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; 41 | * 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; 42 | \*********************************************************************************************/ 43 | #define SELECTPLUS_PULSECOUNT 36 44 | #define SELECTPLUS_PULSEMID 650/RAWSIGNAL_SAMPLE_RATE 45 | #define SELECTPLUS_PULSEMAX 2125/RAWSIGNAL_SAMPLE_RATE 46 | 47 | #ifdef PLUGIN_070 48 | boolean Plugin_070(byte function, char *string) { 49 | if (RawSignal.Number !=SELECTPLUS_PULSECOUNT) return false; 50 | unsigned long bitstream=0L; 51 | byte checksum=0; 52 | //================================================================================== 53 | // get bytes 54 | for(byte x=2;x < SELECTPLUS_PULSECOUNT;x=x+2) { 55 | if (RawSignal.Pulses[x] < SELECTPLUS_PULSEMID) { 56 | if (RawSignal.Pulses[x+1] < SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01 57 | bitstream = (bitstream << 1); 58 | } else { 59 | if (RawSignal.Pulses[x] > SELECTPLUS_PULSEMAX) return false; // invalid pulse duration, pulse too long 60 | if (RawSignal.Pulses[x+1] > SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01 61 | bitstream = (bitstream << 1) | 0x1; 62 | } 63 | } 64 | if (bitstream == 0) return false; // sanity check 65 | //================================================================================== 66 | // Prevent repeating signals from showing up 67 | //================================================================================== 68 | if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000)>4)&0xffff ); // ID 86 | Serial.print( pbuffer ); 87 | Serial.print(F("SWITCH=1;CMD=ON;")); 88 | Serial.print(F("CHIME=01;")); 89 | Serial.println(); 90 | //================================================================================== 91 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 92 | RawSignal.Number=0; // do not process the packet any further 93 | return true; 94 | } 95 | #endif // PLUGIN_070 96 | 97 | #ifdef PLUGIN_TX_070 98 | void SelectPlus_Send(unsigned long address); 99 | 100 | boolean PluginTX_070(byte function, char *string) { 101 | boolean success=false; 102 | unsigned long bitstream=0L; 103 | //10;SELECTPLUS;001c33;1;OFF; 104 | //012345678901234567890123456 105 | if (strncasecmp(InputBuffer_Serial+3,"SELECTPLUS;",11) == 0) { 106 | InputBuffer_Serial[12]=0x30; 107 | InputBuffer_Serial[13]=0x78; 108 | InputBuffer_Serial[20]=0; 109 | bitstream=str2int(InputBuffer_Serial+12); 110 | bitstream=bitstream << 4; 111 | SelectPlus_Send(bitstream); // Send RF packet 112 | success=true; 113 | } 114 | return success; 115 | } 116 | 117 | void SelectPlus_Send(unsigned long address) { 118 | int fpulse = 364; // Pulse witdh in microseconds 119 | int fretrans = 16; // number of RF packet retransmissions 120 | uint32_t fdatabit; 121 | uint32_t fdatamask = 0x10000; 122 | uint32_t fsendbuff; 123 | 124 | digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver (if wired that way) to protect against interference 125 | digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable 433Mhz transmitter 126 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 127 | 128 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { 129 | fsendbuff=address; 130 | // send SYNC 3P High 131 | digitalWrite(PIN_RF_TX_DATA, HIGH); 132 | delayMicroseconds(fpulse * 3); 133 | // end send SYNC 134 | // Send command 135 | for (int i = 0; i < 17;i++) { // SelectPlus address is only 13 bits, last 4 bits are always zero 136 | // read data bit7 137 | fdatabit = fsendbuff & fdatamask; // Get most left bit 138 | fsendbuff = (fsendbuff << 1); // Shift left 139 | 140 | if (fdatabit != fdatamask) { // Write 0 141 | digitalWrite(PIN_RF_TX_DATA, LOW); // short low 142 | delayMicroseconds(fpulse * 1); 143 | digitalWrite(PIN_RF_TX_DATA, HIGH); // long high 144 | delayMicroseconds(fpulse * 3); 145 | } else { // Write 1 146 | digitalWrite(PIN_RF_TX_DATA, LOW); 147 | delayMicroseconds(fpulse * 3); // long low 148 | digitalWrite(PIN_RF_TX_DATA, HIGH); 149 | delayMicroseconds(fpulse * 1); // short high 150 | } 151 | } 152 | digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal 153 | if (nRepeat < fretrans) { 154 | delayMicroseconds(fpulse * 16); // delay between RF transmits 155 | } 156 | 157 | } 158 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 159 | digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter 160 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver 161 | RFLinkHW(); 162 | } 163 | #endif // PLUGIN_070 164 | -------------------------------------------------------------------------------- /Plugins/Plugin_031.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-31 AlectoV3 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren 7 | * WS1100, WS1200, WSD-19 8 | * 9 | * Author : StuntTeam 10 | * Support : http://sourceforge.net/projects/rflink/ 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 | * Technische informatie: 17 | * Decodes signals from Alecto Weatherstation outdoor unit, type 3 (94/126 pulses, 47/63 bits, 433 MHz). 18 | * WS1100 Message Format: (7 bits preamble, 5 Bytes, 40 bits): 19 | * AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE 20 | * Temperature Humidity Checksum 21 | * A = start/unknown, first 8 bits are always 11111111 22 | * B = Rolling code 23 | * C = Temperature (10 bit value with -400 base) 24 | * D = Checksum 25 | * E = Humidity 26 | * 27 | * WS1200 Message Format: (7 bits preamble, 7 Bytes, 56 bits): 28 | * AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF 29 | * Temperature Rain LSB Rain MSB ???????? Checksum 30 | * A = start/unknown, first 8 bits are always 11111111 31 | * B = Rolling code 32 | * C = Temperature (10 bit value with -400 base) 33 | * D = Rain ( * 0.3 mm) 34 | * E = ? 35 | * F = Checksum 36 | 37 | AAAAAAA AAAABBBB BBBBCCCC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF 38 | 1111111 00111010 01010010 10000010 00000000 00000000 11111111 10111010 1 24,2 gr 0 mm 39 | 1111111 00111010 01010010 10000010 00000001 00000000 11111111 11111100 0 24,2 gr 0,3 mm 40 | 1111111 00111010 01010010 10000010 00000010 00000000 11111111 00110110 0 24,2 gr 0,6 mm 41 | 1111111 00111010 01010010 10000010 00001000 00000000 11111111 11101000 1 24,2 gr 2,4 mm 42 | 1111111 00111010 01010010 10000010 00001101 00000000 11111111 10000111 0 24,2 gr 3.9 mm 43 | 1111111 00111010 01010010 01110001 00001101 00000000 11111111 01000010 0 22,5 gr 3,9 mm 44 | 1111111 00111010 01010010 01010111 00001101 00000000 11111111 00111011 1 19,9 gr 3,9 mm 45 | 1111111 00111010 01010010 00111110 00010010 00000000 11111111 00111001 1 17,4 gr 5,4 mm 46 | 1111111 00111010 01010010 00101000 00010010 00000000 11111111 00001000 0 15,2 gr 5,4 mm 47 | 48 | 1111111 00111010 01010001 00101011 10011010 00000001 11111111 10100011 -10,1 gr/123,0 mm 49 | WS1200 temp:-101 50 | WS1200 rain LSB:154 51 | WS1200 rain MSB:1 52 | WS1200 rain:1230 53 | 54 | 1111111 00111010 01010001 10101101 10011111 00000001 11111111 00110100 2,9 gr/124,5mm 55 | WS1200 temp:29 56 | WS1200 rain LSB:159 57 | WS1200 rain MSB:1 58 | WS1200 rain:1245 59 | 60 | 61 | * 20;AE;DEBUG;Pulses=126;Pulses(uSec)=900,950,825,450,325,450,325,950,325,450,325,450,825,950,825,450,325,950,825,450,350,950,325,450,825,950,825,450,325,450,325,950,825,925,350,450,825,950,825,925,350,450,825,450,350,925,825,450,350,450,325,950,350,450,825,950,325,450,350,450,325,450,825,450,325,450,325,450,325,450,325,950,825,950,325,450,825,950,325,450,825,450,325,950,325,450,325,450,825,925,350,450,350,450,825,950,825,925,350,425,350,450,350,450,350,450,350,450,825,950,825,950,325,450,350,450,825,950,825,950,825,950,325,450,325; 62 | * 20;AF;Alecto V3;ID=009a;TEMP=ffe7;RAIN=7a; 63 | \*********************************************************************************************/ 64 | #define WS1100_PULSECOUNT 94 65 | #define WS1200_PULSECOUNT 126 66 | #define ALECTOV3_PULSEMID 300/RAWSIGNAL_SAMPLE_RATE 67 | 68 | #ifdef PLUGIN_031 69 | uint8_t Plugin_031_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len); 70 | unsigned int Plugin_031_ProtocolAlectoRainBase=0; 71 | 72 | boolean Plugin_031(byte function, char *string) { 73 | if ((RawSignal.Number != WS1100_PULSECOUNT) && (RawSignal.Number != WS1200_PULSECOUNT)) return false; 74 | 75 | unsigned long bitstream1=0L; 76 | unsigned long bitstream2=0L; 77 | byte rc=0; 78 | int temperature=0; 79 | byte humidity=0; 80 | unsigned int rain=0; 81 | byte checksum=0; 82 | byte checksumcalc=0; 83 | byte data[6]; 84 | //================================================================================== 85 | for (byte x=15; x<=77; x=x+2) { // get first 32 relevant bits 86 | if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) { 87 | bitstream1 = (bitstream1 << 1) | 0x1; 88 | } else { 89 | bitstream1 = (bitstream1 << 1); 90 | } 91 | } 92 | for (byte x=79; x<=141; x=x+2) { // get second 32 relevant bits 93 | if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) { 94 | bitstream2 = (bitstream2 << 1) | 0x1; 95 | } else { 96 | bitstream2 = (bitstream2 << 1); 97 | } 98 | } 99 | //================================================================================== 100 | if (bitstream1 == 0) return false; // Sanity check 101 | data[0] = (bitstream1 >> 24) & 0xff; // Sort data 102 | data[1] = (bitstream1 >> 16) & 0xff; 103 | data[2] = (bitstream1 >> 8) & 0xff; 104 | data[3] = (bitstream1 >> 0) & 0xff; 105 | data[4] = (bitstream2 >> 24) & 0xff; 106 | data[5] = (bitstream2 >> 16) & 0xff; 107 | // ---------------------------------- 108 | if (RawSignal.Number == WS1200_PULSECOUNT) { // verify checksum 109 | checksum = (bitstream2 >> 8) & 0xff; 110 | checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 6); 111 | } else { 112 | checksum = (bitstream2 >> 24) & 0xff; 113 | checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 4); 114 | } 115 | if (checksum != checksumcalc) return false; 116 | // ---------------------------------- 117 | rc = (bitstream1 >> 20) & 0xff; 118 | temperature = ((bitstream1 >> 8) & 0x3ff); // 299=12b -400 (0x190) = FF9b 119 | //temperature = ((bitstream1 >> 8) & 0x3ff) - 400; // 299=12b -400 (0x190) = FF9b 120 | if (temperature < 400) { // negative temperature value 121 | temperature = 400 - temperature; 122 | temperature=temperature | 0x8000; // turn highest bit on for minus values 123 | } else { 124 | if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees) 125 | } 126 | //================================================================================== 127 | // Output 128 | // ---------------------------------- 129 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 130 | Serial.print( pbuffer ); 131 | // ---------------------------------- 132 | Serial.print(F("Alecto V3;")); // Label 133 | sprintf(pbuffer, "ID=00%02x;", rc); // ID 134 | Serial.print( pbuffer ); 135 | sprintf(pbuffer, "TEMP=%04x;", temperature); 136 | Serial.print( pbuffer ); 137 | 138 | if (RawSignal.Number == WS1100_PULSECOUNT) { 139 | humidity = bitstream1 & 0xff; // alleen op WS1100? 140 | sprintf(pbuffer, "HUM=%02x;", humidity); 141 | Serial.print( pbuffer ); 142 | } else { 143 | rain = (((bitstream2 >> 24) & 0xff) * 256) + ((bitstream1 >> 0) & 0xff); 144 | // check if rain unit has been reset! 145 | if (rain < Plugin_031_ProtocolAlectoRainBase) Plugin_031_ProtocolAlectoRainBase=rain; 146 | if (Plugin_031_ProtocolAlectoRainBase > 0) { 147 | //UserVar[basevar+1 -1] += ((float)rain - Plugin_031_ProtocolAlectoRainBase) * 0.30; 148 | sprintf(pbuffer, "RAIN=%02x;", (rain)&0xff); 149 | Serial.print( pbuffer ); 150 | } 151 | Plugin_031_ProtocolAlectoRainBase = rain; 152 | } 153 | Serial.println(); 154 | //================================================================================== 155 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 156 | RawSignal.Number=0; // do not process the packet any further 157 | return true; 158 | } 159 | 160 | /*********************************************************************************************\ 161 | * Calculates CRC-8 checksum 162 | * reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/ 163 | * http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/ 164 | * https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp 165 | \*********************************************************************************************/ 166 | uint8_t Plugin_031_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len) 167 | { 168 | uint8_t crc = 0; 169 | // Indicated changes are from reference CRC-8 function in OneWire library 170 | while (len--) { 171 | uint8_t inbyte = *addr++; 172 | for (uint8_t i = 8; i; i--) { 173 | uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01 174 | crc <<= 1; // changed from right shift 175 | if (mix) crc ^= 0x31;// changed from 0x8C; 176 | inbyte <<= 1; // changed from right shift 177 | } 178 | } 179 | return crc; 180 | } 181 | #endif // PLUGIN_031 182 | -------------------------------------------------------------------------------- /Plugins/Plugin_074.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-74: RL-02 Digital Doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of sending and receiving the RL-02 Digital Doorbell protocol. 7 | * 8 | * Author : Jonas Jespersen 9 | * Support : http://sourceforge.net/projects/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 | * Technical information: 14 | * 15 | * The RL-02 Digital Doorbell uses a protocol similar to PT2262 which send 12 bits that can be either 16 | * 1, 0 or f (float). 17 | * 18 | * The doorbell transmitter has 2 buttons; One for ringing the doorbell and a button inside the transmitter 19 | * for changing the chime. Everytime the change chime button is pressed the doorbell toggles through a number 20 | * of available chimes, and when ring button is pressed the chime last selected with the change chime button 21 | * will sound. 22 | * 23 | * AAAAAAAAAAA B 24 | * 25 | * A = Always f0ff0f0ffff 26 | * B = f or 1 (f = Change chime button, 1 = Ring button) 27 | * 28 | * Ring: 29 | * 20;6D;DEBUG;Pulses=50;Pulses(uSec)=175,400,450,50,100,400,100,400,100,400,450,50,100,400,450,50,100,425,100,400,100,400,450,50,100,400,100,400,100,400,450,50,100,400,425,75,100,400,425,75,100,400,450,75,425,75,425,75,75; 30 | * 31 | * Change chime: 32 | * 20;0B;DEBUG;Pulses=50;Pulses(uSec)=175,400,450,50,100,400,100,400,100,400,450,50,100,400,450,50,100,400,100,400,100,400,425,50,100,400,100,400,100,400,450,50,100,400,425,50,100,400,425,50,100,400,425,75,100,400,425,75,100; 33 | \*********************************************************************************************/ 34 | #define RL02_CodeLength 12 35 | #define RL02_T 125 // 175 uS 36 | 37 | #ifdef PLUGIN_074 38 | boolean Plugin_074(byte function, char *string) { 39 | if (RawSignal.Number != (RL02_CodeLength * 4) + 2) return false; 40 | 41 | unsigned long bitstream = 0L; 42 | unsigned long checksum = 0L; 43 | int i, j; 44 | boolean error = false; 45 | // ========================================================================== 46 | for (i = 0; i < RL02_CodeLength; i++) { 47 | j = (RL02_T * 2) / RAWSIGNAL_SAMPLE_RATE; 48 | 49 | if (RawSignal.Pulses[4 * i + 1] < j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] < j && RawSignal.Pulses[4 * i + 4] > j) { // 0101 50 | bitstream = (bitstream >> 1); // 0 51 | } else 52 | if (RawSignal.Pulses[4 * i + 1] < j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] > j && RawSignal.Pulses[4 * i + 4] < j) { // 0110 53 | bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // float 54 | } else 55 | if (RawSignal.Pulses[4 * i + 1] > j && RawSignal.Pulses[4 * i + 2] < j && RawSignal.Pulses[4 * i + 3] > j && RawSignal.Pulses[4 * i + 4] < j) { // 1010 56 | bitstream = (bitstream >> 1); // 1 57 | } else { 58 | if (i == 0) { 59 | if (RawSignal.Pulses[4 * i + 1] > j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] < j && RawSignal.Pulses[4 * i + 4] > j) { // 1101 60 | bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // 1 61 | } else { 62 | error = true; 63 | } 64 | } else { 65 | error = true; 66 | } 67 | } 68 | } 69 | // ========================================================================== 70 | // all bytes received, make sure packet is valid and checksum is okay 71 | // ========================================================================== 72 | if (error == true) return false; 73 | if (bitstream == 0) return false; // sanity check 74 | checksum = (bitstream) & 0x000007FFL; 75 | if (checksum != 0x000007ADL) return false; 76 | if (bitstream == 0) return false; // sanity check 77 | // ========================================================================== 78 | // ---------------------------------- 79 | // Output 80 | // ---------------------------------- 81 | Serial.print("20;"); 82 | PrintHexByte(PKSequenceNumber++); 83 | Serial.print(F(";Byron MP;")); // Label 84 | // ---------------------------------- 85 | sprintf(pbuffer, "ID=%04x;", (bitstream & 0x00000800L) ? 1 : 0); // ID: 0 = Ring button, 1 = Change chime button 86 | Serial.print( pbuffer ); 87 | Serial.print(F("SWITCH=1;CMD=ON;")); 88 | Serial.print(F("CHIME=01;")); 89 | Serial.println(); 90 | // ---------------------------------- 91 | RawSignal.Repeats=true; 92 | RawSignal.Number=0; 93 | return true; 94 | } 95 | #endif //PLUGIN_074 96 | 97 | #ifdef PLUGIN_TX_074 98 | void RL02_Send(unsigned long address); 99 | 100 | boolean PluginTX_074(byte function, char *string) { 101 | boolean success=false; 102 | unsigned long bitstream=0; 103 | //10;Byron MP;001c33;1;OFF; 104 | //012345678901234567890123456 105 | if (strncasecmp(InputBuffer_Serial+3,"BYRON MP;",9) == 0) { 106 | InputBuffer_Serial[10]=0x30; 107 | InputBuffer_Serial[11]=0x78; 108 | InputBuffer_Serial[18]=0; 109 | bitstream=str2int(InputBuffer_Serial+10); 110 | bitstream = ((bitstream) << 11) | 0x000007ADL; 111 | RL02_Send(bitstream); // Send RF packet 112 | success=true; 113 | } 114 | return success; 115 | } 116 | 117 | void RL02_Send(unsigned long address) { 118 | int fpulse = 175; // Pulse witdh in microseconds 119 | int fretrans = 7; // Number of code retransmissions 120 | uint32_t fdatabit; 121 | uint32_t fdatamask = 0x00000001; 122 | uint32_t fsendbuff; 123 | 124 | digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver 125 | digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter 126 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 127 | 128 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { 129 | fsendbuff = address; 130 | // Send command 131 | 132 | for (int i = 0; i < 11; i++) { // RL-02 packet is 12 bits 133 | // read data bit 134 | fdatabit = fsendbuff & fdatamask; // Get most right bit 135 | fsendbuff = (fsendbuff >> 1); // Shift right 136 | 137 | // PT2262 data can be 0, 1 or float. 138 | if (fdatabit != fdatamask) { // Write 0 139 | digitalWrite(PIN_RF_TX_DATA, HIGH); 140 | delayMicroseconds(fpulse); 141 | digitalWrite(PIN_RF_TX_DATA, LOW); 142 | delayMicroseconds(fpulse * 3); 143 | digitalWrite(PIN_RF_TX_DATA, HIGH); 144 | delayMicroseconds(fpulse); 145 | digitalWrite(PIN_RF_TX_DATA, LOW); 146 | delayMicroseconds(fpulse * 3); 147 | } else { // Write float 148 | digitalWrite(PIN_RF_TX_DATA, HIGH); 149 | delayMicroseconds(fpulse * 1); 150 | digitalWrite(PIN_RF_TX_DATA, LOW); 151 | delayMicroseconds(fpulse * 3); 152 | digitalWrite(PIN_RF_TX_DATA, HIGH); 153 | delayMicroseconds(fpulse * 3); 154 | digitalWrite(PIN_RF_TX_DATA, LOW); 155 | delayMicroseconds(fpulse * 1); 156 | } 157 | } 158 | 159 | fdatabit = fsendbuff & fdatamask; // Get most right bit 160 | // Send last bit. Can be either 1 or float 161 | if (fdatabit != fdatamask) { // Write 1 162 | digitalWrite(PIN_RF_TX_DATA, HIGH); 163 | delayMicroseconds(fpulse * 3); 164 | digitalWrite(PIN_RF_TX_DATA, LOW); 165 | delayMicroseconds(fpulse); 166 | digitalWrite(PIN_RF_TX_DATA, HIGH); 167 | delayMicroseconds(fpulse * 3); 168 | digitalWrite(PIN_RF_TX_DATA, LOW); 169 | delayMicroseconds(fpulse); 170 | } else { // Write float 171 | digitalWrite(PIN_RF_TX_DATA, HIGH); 172 | delayMicroseconds(fpulse * 1); 173 | digitalWrite(PIN_RF_TX_DATA, LOW); 174 | delayMicroseconds(fpulse * 3); 175 | digitalWrite(PIN_RF_TX_DATA, HIGH); 176 | delayMicroseconds(fpulse * 3); 177 | digitalWrite(PIN_RF_TX_DATA, LOW); 178 | delayMicroseconds(fpulse * 1); 179 | } 180 | 181 | // Send sync bit 182 | digitalWrite(PIN_RF_TX_DATA, HIGH); 183 | delayMicroseconds(fpulse * 1); 184 | digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal 185 | delayMicroseconds(fpulse * 31); 186 | } 187 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 188 | digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off 189 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on 190 | RFLinkHW(); 191 | } 192 | #endif // PLUGIN_TX_074 193 | -------------------------------------------------------------------------------- /Doc/Supported Device List.txt: -------------------------------------------------------------------------------- 1 | ============================================================================ 2 | Nodo - RFLink supported devices list 3 | ============================================================================ 4 | Remote Controls and Electrical Switches / Dimmers etc.: 5 | ------------------------------------------------------- 6 | ARC Protocol: (Send + Receive) 7 | - Klik Aan Klik Uit (Code Wheel) 8 | - Princeton PT2262 9 | - MOSDESIGN M3EB 10 | - Domia Lite 11 | - Intertechno 12 | - CoCo Technologies 13 | - Cogex 14 | - D-IO (Chacon) 15 | - Nexa 16 | - Düwi Terminal 17 | - Promax RSL366T 18 | - Conrad 640472, 640473, 640475, 640476 19 | - ME FLS 100 20 | - Profile PR-44N, PR-47N 21 | - Sartano 2606 22 | - Impuls 23 | - Elro AB400 24 | - Waveman 25 | - Elro Home Comfort AB600 26 | - (Elro) Home Control 27 | - Smarthome YC-4000B 28 | - Phenix YC-4000S 29 | - Pollin Funk-Dimmer HouseLight FD-UP001 30 | - Pollin Funk-Steckdosen-Set 2605 31 | - Conrad 646443 outlet sockets / RSL366R 32 | - Proteam HO1853 33 | - Velleman WRS3B 34 | - "Emil Lux"/LUX-Tools (Obi.de Art.Nr. 2087971) 35 | - Znane-01 switch set sold at Biedronka (Impuls clone) 36 | - Renkforce 37 | 38 | Automatic Code Learning Protocols: (Send + Receive) 39 | - Klik Aan Klik Uit 40 | (All products, among others: AWMR210, AWMT230, AWMD250, AWST8800) 41 | - CoCo Technologies 42 | - Trust SmartHome 43 | - Nexa Jula Anslut 44 | (among others: 408-063, 408-064) 45 | - Home Easy EU (among others HE100, HE200, HE300, AB600/HE600, HE800) 46 | - Smartwares (SH5-TDR-K 10.037.17) 47 | 48 | Others: (Send + Receive) 49 | - Home Easy (Code Wheel) 50 | - Unitec 48110 EIM 826 / 48111 EIM 821 51 | - Quigg GT-1000 RC / Quigg GT-FSI-08 52 | - Intertek Eurodomest 972080 (Protocol revision 1 & 2 - full autodetection) 53 | - Intertek Eurodomest 972086 (Protocol revision 1 & 2 - full autodetection) 54 | - Blyss 55 | - Conrad RSL2, Conrad RSL88R/B 56 | - Kambrook RF3399/RF3405/RF3672/RF3689/RF4471R 57 | - X10 RF switches 58 | - Home Confort Smart Home - Among others: TEL-010, PRF-100 59 | - Quigg GT-7008BS, Quigg GT-FSI-04 60 | - DMV-7008S 61 | - Mandolyn RC-710 62 | - Powerfix RCB-I 3600 63 | - Quigg GT-8000 64 | - Chacon (TR-502MSV, NR.RC402) 65 | - Rev Ritter REV 8342L 66 | - Ikea Koppla 67 | - TRC02 RGB Controller 68 | - Aster / GEMINI EMC/99/STI/037 69 | - Silvercrest l36-001 70 | - Brennenstuhl RCS 1000 N Comfort 71 | - Lidl / Libra TR502MSV 72 | 73 | - Flamingo FA500R/S/DSS/WD 74 | - SilverCrest 91210/60494 RCS AAA3680 75 | - Mumbi M-FS300 76 | - Toom 1919384 77 | ============================================================================ 78 | Weather Sensors: 79 | ---------------- 80 | - Alecto V1: 81 | Alecto WS3500, SilverCrest, Otio SH-10, Otio SH-20 82 | Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160 83 | Alecto WS4500, Ventus W044, Balance RF-WS105 84 | - Alecto V2: (868 Mhz!) 85 | ACH2010, DKW2012 86 | - Alecto V3: 87 | WS1100, WS1200 88 | - Alecto V4: 89 | Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor 90 | - Cresta/Hideki: 91 | Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W, 92 | WXR810, DV928, Ventus W906, HomeWizard Rain meter 93 | - Mebus: 94 | Mebus Outdoor Sensor 95 | Stacja Pogody WS-9941-M 96 | - UPM/Esic: 97 | UPM, Esic, Emos, DVM, Clas Ohlson, Dickson 98 | WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700 99 | - LaCrosse: 100 | Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4 101 | WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, 102 | WS7000-20: Thermo/Humidity/Barometer, TFA 30.3125 (temperature + humidity), TFA 30.3120.90 (temperature) 103 | - LaCrosseV2: 104 | WS2300 (Temperature/Humidity/Wind/Rain), WS2310, WS2355, WS3600 105 | - Auriol: 106 | Z31743, Rubicson 107 | - Auriol V2: 108 | Z31055A-TX, Xiron, Watshome YT6018-2, Technoline 109 | - Auriol V3: 110 | Z32171A 111 | - FineOffset: 112 | Fine Offset Electronics WH2, Agimex Rosenborg 66796, ClimeMET CM9088 113 | - Eurochron: 114 | EAS 301Z / EAS 302 115 | - Prologue: 116 | Clas Ohlson 36-4741, Clas Ohlson 36-5087 117 | - Oregon V1/2/3: 118 | THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X, 119 | THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500, 120 | THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122, 121 | THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave, RGR928, 122 | UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, BTHG968, OWL CM180, BTHGN129 123 | ============================================================================ 124 | Pool/Water Thermometer 125 | Conrad 9771 Pool Thermometer 126 | ============================================================================ 127 | Soil : Temperature & Moisture/Humidity Sensors 128 | Imagintronix XH300 sensor 129 | TH12 Opus TX300 130 | ============================================================================ 131 | Dusk Sensors (Light On/Off detection): 132 | ----------------------------------- 133 | KAKU ABST-604 134 | Home Easy HE863 135 | Intertechno ITDS-5 136 | ============================================================================ 137 | Window blinds/shutters/sun screens: 138 | ----------------------------------- 139 | Kaku ASUN650 140 | Intertechno CMR-500, ITL-500, ITL-1000 141 | ============================================================================ 142 | Motion Detectors: 143 | -------------------------------- 144 | Low Budget Chinese PIR (only signals motion detection) 145 | Aritech PIR (only signals motion detection) 146 | Ajax Chub Varel PIR (only signals motion detection) 147 | Chuango: among others PIR-900 PIR sensor 148 | Oregon Scientific NR868 PIR/night light 149 | Oregon Scientific MSR939 PIR 150 | ============================================================================ 151 | Door/Window sensors: 152 | -------------------------------- 153 | Low Budget Chinese Door/Window detectors 154 | Intertechno ITM-100 155 | KAKU AMST-606 door/window sensor (separate signals for open and close) 156 | Home Easy HE852 (separate signals for open and close) 157 | CHACON DIO 54781 (separate signals for open and close) 158 | COCO (separate signals for open and close) 159 | Evology door/window contact sensor 160 | ELMES CTX3H, CTX4H 161 | Chuango: among others DWC-100 Door sensor, DWC-102 Door sensor 162 | ============================================================================ 163 | Fireplace: 164 | ---------- 165 | Mertik G6R H4T1 / Dru 166 | ============================================================================ 167 | Smoke Detectors: 168 | ---------------- 169 | KD101 (Send + Receive) 170 | Diamant Smoke alarm (Send + Receive) 171 | Flamingo FA20RF (Send + Receive) 172 | Chacon 34126 (Send + Receive) 173 | ============================================================================ 174 | Doorbells: 175 | ---------- 176 | SelectPlus (200689103 - Black - Date code:0614), 1 by One, Delta (O00 QH-0031) (Send + Receive) 177 | SelectPlus (200689101 - White - Date code:0914) (Send + Receive) 178 | KAKU ACDB 6500BC (Send + Receive) 179 | Deltronic Wireless Doorbell (Send + Receive) 180 | RL-02 Wireless Doorbell (Send + Receive) 181 | Byron SX (Send + Receive) 182 | SilverCrest Z31370-TX (Receive) 183 | Forrinx (Receive) 184 | Heidemann HX Silverline 70290 (Receive) 185 | L^Home model 32311T (Receive) 186 | Plieger York (Receive) 187 | Note that when the Plieger button is detected as Conrad RSL2, you need to use the button 188 | on the inside of the Plieger doorbell to change the address code of the Plieger. 189 | ============================================================================ 190 | Nodo Slave Sensors: 191 | ------------------- 192 | Various Nodo sensor types are supported. 193 | Make sure you use Nodo Slave ID 1,2, 4 till 9 to make the sensor a separate sensor. 194 | If you want to have combined sensors (eg temperature + humidity in one device) make sure 195 | you use Nodo Slave ID 10 till 16 196 | 197 | The following variable / sensor types are currently supported 198 | 199 | Variabele 5 : Temperature 200 | Variabele 6 : Humidity 201 | Variabele 7 : Rain 202 | Variabele 8 : Wind speed 203 | Variabele 9 : Wind direction 204 | Variabele 10 : Wind gust 205 | Variable 11, 12 en 13 : Temperature 206 | Variable 14 : Humidity 207 | Variable 15 : UV 208 | Variable 16 : Barometric pressure 209 | 210 | 211 | Electricity/Water/Gas pulse meters are supported when using the following Nodo variable numbers: 212 | 213 | Make sure the slave devices are using Nodo Slave ID 3 !!! 214 | 215 | Variabele 1 : Pulse value 1 216 | Variabele 2 : Pulse value 2 217 | Variabele 3 : Pulse value 3 218 | Variabele 4 : Pulse value 4 219 | Variabele 5 : Pulse value 5 220 | Variabele 6 : Pulse value 6 221 | 222 | If you require support for other sensors just let us know. 223 | ============================================================================ 224 | 225 | Chuango 226 | * G5 GSM/SMS/RFID Touch Alarm System 227 | * DWC-100 Door sensor 228 | * DWC-102 Door sensor 229 | * KP-700 Wireless Keypad 230 | * PIR-900 PIR sensor 231 | * RC-80 Remote Control 232 | * SMK-500 Smoke sensor 233 | -------------------------------------------------------------------------------- /Plugins/Plugin_005.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-03: Intertek Eurodomest 972080 ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of sending and receiving the Intertek Eurodomest 972080 protocol. 7 | * 8 | * Author : StuntTeam 9 | * Support : http://sourceforge.net/projects/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 | * Technical information: 14 | * 15 | * 0111 00011011 00011111 000 0 16 | * AAAA AAAAAAAA AAAAAAAA BBB C 17 | * 0000 00000011 10101010 101 1 18 | * 0000 00000011 10101010 111 0 19 | * 20 | * 0011 01101001 01101011 000 0 Eurodomest 1 on 21 | * 0011 01101001 01101011 000 1 Eurodomest 1 off 22 | * 0011 01101001 01101011 001 0 ED 2 on 23 | * 0011 01101001 01101011 001 1 ED 2 off 24 | * 0011 01101001 01101011 010 0 3 on 25 | * 0011 01101001 01101011 010 1 3 off 26 | * 0011 01101001 01101011 100 0 4 on 27 | * 0011 01101001 01101011 100 1 4 off 28 | * 0011 01101001 01101011 110 1 all on 29 | * 0011 01101001 01101011 111 0 all off 30 | * 31 | * 32 | * A = ID (20 bits) 33 | * B = UnitCode (3 bits) 34 | * C = switch code (ON/OFF) (1 bit) 35 | * 36 | * 20;2A;DEBUG;Pulses=50;Pulses(uSec)= 900,200,825,200,225,825,200,825,800,200,200,825,200,825,825,200,225,825,800,200,800,225,225,825,800,225,200,825,225,825,800,225,225,825,800,225,200,825,200,825,225,825,225,825,225,825,800,200,200; 37 | * 20;9D;DEBUG;Pulses=50;Pulses(uSec)=1250,200,750,175,200,750,200,750,750,200,200,750,200,750,750,200,200,750,750,200,750,200,200,750,750,200,200,750,200,750,750,200,200,750,750,200,200,750,200,750,750,200,750,200,750,200,750,200,200; 38 | \*********************************************************************************************/ 39 | #define EURODOMEST_PulseLength 50 40 | 41 | #define EURODOMEST_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE 42 | #define EURODOMEST_PULSEMIN 100/RAWSIGNAL_SAMPLE_RATE 43 | #define EURODOMEST_PULSEMAX 900/RAWSIGNAL_SAMPLE_RATE 44 | 45 | #ifdef PLUGIN_005 46 | boolean Plugin_005(byte function, char *string) { 47 | if (RawSignal.Number != EURODOMEST_PulseLength) return false; 48 | if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63 49 | unsigned long bitstream=0; 50 | byte unitcode=0; 51 | byte command=0; 52 | unsigned long address=0; 53 | // ========================================================================== 54 | if(RawSignal.Pulses[49] > EURODOMEST_PULSEMID) return false; // last pulse needs to be short, otherwise no Eurodomest protocol 55 | // get all 24 bits 56 | for(int x=2;x < EURODOMEST_PulseLength;x+=2) { 57 | if(RawSignal.Pulses[x] > EURODOMEST_PULSEMID) { // long pulse 58 | if (RawSignal.Pulses[x-1] > EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission 59 | if(RawSignal.Pulses[x] > EURODOMEST_PULSEMAX) return false; // make sure the long pulse is within range 60 | bitstream = (bitstream << 1) | 0x1; 61 | } else { // short pulse 62 | if (RawSignal.Pulses[x] < EURODOMEST_PULSEMIN) return false; // pulse too short to be Eurodomest 63 | if (RawSignal.Pulses[x-1] < EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission 64 | bitstream = (bitstream << 1); 65 | } 66 | } 67 | //================================================================================== 68 | // Prevent repeating signals from showing up 69 | //================================================================================== 70 | if(SignalHash!=SignalHashPrevious || RepeatingTimer> 4) &0xfffff; 82 | if (address==0) return false; // Address would never be 0 83 | if (address==0xfffff) return false; // Address would never be FFFFF 84 | // ---------------------------------- 85 | unitcode=(( bitstream >> 1)& 0x7); 86 | command=((bitstream) & 0x01); 87 | if (unitcode == 3) return false; // invalid button code? 88 | if (unitcode == 4) unitcode--; 89 | // if (unitcode == 5) return false; // Note: unitcode 5 is present on the PCB and working but not used on any remotes. 90 | if (unitcode > 7) return false; // invalid button code? 91 | //================================================================================== 92 | // Output 93 | // ---------------------------------- 94 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 95 | Serial.print( pbuffer ); 96 | // ---------------------------------- 97 | Serial.print(F("Eurodomest;")); // Label 98 | sprintf(pbuffer, "ID=%06lx;",(address)&0xffffff) ; // ID 99 | Serial.print( pbuffer ); 100 | sprintf(pbuffer, "SWITCH=%02x;", unitcode); // ID 101 | Serial.print( pbuffer ); 102 | Serial.print(F("CMD=")); 103 | if ( unitcode > 4) { 104 | Serial.print(F("ALL")); 105 | if ( command == 0) { 106 | Serial.print(F("OFF;")); 107 | } else { 108 | Serial.print(F("ON;")); 109 | } 110 | } else { 111 | if ( command == 1) { 112 | Serial.print(F("OFF;")); 113 | } else { 114 | Serial.print(F("ON;")); 115 | } 116 | } 117 | Serial.println(); 118 | // ---------------------------------- 119 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 120 | RawSignal.Number=0; 121 | return true; 122 | } 123 | #endif //PLUGIN_005 124 | 125 | #ifdef PLUGIN_TX_005 126 | void Eurodomest_Send(unsigned long address); 127 | 128 | boolean PluginTX_005(byte function, char *string) { 129 | //10;EURODOMEST;03696b;0;ON; 130 | //012345678901234567890123456 131 | boolean success=false; 132 | if (strncasecmp(InputBuffer_Serial+3,"EURODOMEST;",11) == 0) { // KAKU Command eg. 133 | unsigned long bitstream=0L; 134 | if (InputBuffer_Serial[20] != ';') return success; 135 | if (InputBuffer_Serial[22] != ';') return success; 136 | 137 | InputBuffer_Serial[12]=0x30; 138 | InputBuffer_Serial[13]=0x78; 139 | InputBuffer_Serial[20]=0x00; 140 | bitstream=str2int(InputBuffer_Serial+12);// Address 141 | InputBuffer_Serial[22]=0x00; 142 | byte temp=str2int(InputBuffer_Serial+21);// Button number 143 | bitstream=(bitstream) << 4; 144 | if (temp == 1) bitstream=bitstream+0x02; // 0010 145 | if (temp == 2) bitstream=bitstream+0x04; // 0100 146 | if (temp == 3) bitstream=bitstream+0x08; // 1000 147 | if (temp == 6) bitstream=bitstream+0x0d; // 1101 148 | if (temp == 7) bitstream=bitstream+0x0f; // 1111 149 | if (temp > 7) { 150 | return success; 151 | } 152 | byte command=0; 153 | command = str2cmd(InputBuffer_Serial+23); 154 | if (command == VALUE_OFF) { 155 | bitstream=bitstream|1; 156 | } 157 | Eurodomest_Send(bitstream); // the full bitstream to send 158 | success=true; 159 | } 160 | return success; 161 | } 162 | 163 | void Eurodomest_Send(unsigned long address) { 164 | int fpulse = 296; // Pulse witdh in microseconds 165 | int fretrans = 7; // Number of code retransmissions 166 | uint32_t fdatabit; 167 | uint32_t fdatamask = 0x800000; 168 | uint32_t fsendbuff; 169 | 170 | digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver 171 | digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter 172 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 173 | 174 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { 175 | fsendbuff=address; 176 | // Send command 177 | for (int i = 0; i < 24; i++) { // Eurodomest packet is 24 bits 178 | // read data bit 179 | fdatabit = fsendbuff & fdatamask; // Get most left bit 180 | fsendbuff = (fsendbuff << 1); // Shift left 181 | 182 | if (fdatabit != fdatamask) { // Write 0 183 | digitalWrite(PIN_RF_TX_DATA, HIGH); 184 | delayMicroseconds(fpulse * 3); 185 | digitalWrite(PIN_RF_TX_DATA, LOW); 186 | delayMicroseconds(fpulse * 1); 187 | } else { // Write 1 188 | digitalWrite(PIN_RF_TX_DATA, HIGH); 189 | delayMicroseconds(fpulse * 1); 190 | digitalWrite(PIN_RF_TX_DATA, LOW); 191 | delayMicroseconds(fpulse * 3); 192 | } 193 | } 194 | digitalWrite(PIN_RF_TX_DATA, HIGH); 195 | delayMicroseconds(fpulse * 1); 196 | digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal 197 | delayMicroseconds(fpulse * 32); 198 | } 199 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 200 | digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off 201 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on 202 | RFLinkHW(); 203 | } 204 | #endif //PLUGIN_TX_005 205 | -------------------------------------------------------------------------------- /Plugins/Plugin_072.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-072 Byron Wireless Doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception And sending of the Byron SX doorbell 7 | * 8 | * Author : Maurice Ruiter (Dodge) 9 | * Support : http://sourceforge.net/projects/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 | * Changelog: v1.0 initial release 14 | ********************************************************************************************* 15 | * Technical information: 16 | * 26 pulses, manchester code, 12 bits 17 | * 18 | * 111111110001 19 | * AAAAAAAABBBB 20 | * 21 | * A = 8 bit Address 22 | * B = chime number 23 | * Valid chime numbers: 1,2,6,9,a,c,d,e ? 24 | * --------------------------------------------------------- 25 | * 20;25;DEBUG;Pulses=26;Pulses(uSec)=275,250,250,525,250,225,250,525,250,225,250,525,525,225,250,525,525,225,250,225,250,225,250,525,525; 26 | * 20;F0;DEBUG;Pulses=511;Pulses(uSec)=450,225,575,200,575,225,575,200,575,200,575,200,575,225,575,550,250,200,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,225,575,200,575,200,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,200,575,225,575,200,575,200,575,200,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,200,575,225,575,200,575,550,250,2850,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,550,250,2850,225,225,575,200,575,225,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,525,250,2825,250,225,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,200,575,200,575,225,575,525,250,2825,250,225,575,225,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,225,575,225,575,200,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,225,575,200,575,550,250,2850,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,225,575,200,575,550,250,2850,250,200,575,200,575,225,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,200,575,225,575,200,575,200,575,550,250,200,575,200,575,225,575,550,250,2825,250,200,575,225,575,200,575,200,575,200,575,225,575,200,575,525,250,200,575,200,575,200,575,550,250,2825,250,200,575,225,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,225,575,200,575,200,575,200,575,225,575,550,250,200,575,225,575,225,575,525,250,2825,250,200,575,200,575,200,575,200,575,225,575,200,575,225,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,225,575,525,250,225,575,200,575,225,575,550,250,2850,225,225,575,200,575,225,575,200,575,200,575,200,575,200,575,525; 27 | * 20;31;DEBUG;Pulses=511;Pulses(uSec)=450,550,250,550,250,550,250,550,250,525,250,525,250,550,250,550,250,225,575,200,575,200,575,550,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,225,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,525,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,550,250,225,575,200,575,200,575,525,250,2825,250,550,250,525,250,525,250,525,250,525,250,550,250,550,250,550,250,200,575,200,575,225,575,550,250,2825,225,550,250,525,250,525,250,550,250,550,250,525,250,525,250,525,250,225,575,200,575,225,575,550,250,2850,250,550,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,225,575,200,575,225,575,550,250,2850,225,550,250,550,250,550,250,550,250,525,250,525,250,525,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,550,250,2825,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,550,250,525,250,550,250,550,250,550,250,550,250,200,575,200,575,225,575,525,250,2825,250,550,250,550,250,525,250,525,250,550,250,550,250,525,250,525,250,200,575,225,575,225,575,550,250,2850,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,200,575,225,575,200,575,550,250,2850,250,550,250,550,250,550,250,550,250,525,250,525,250,550,250,550,250,225,575,225,575,200,575,550,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,550; 28 | * 20;25;DEBUG;Pulses=26;Pulses(uSec)=250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,225,575,200,575,550,250; 29 | \*********************************************************************************************/ 30 | #define PLUGIN_ID 72 31 | #define BYRON_PULSECOUNT 26 32 | 33 | #define BYRONSTART 3000 34 | #define BYRONSPACE 250 35 | #define BYRONLOW 350 36 | #define BYRONHIGH 675 37 | 38 | #ifdef PLUGIN_072 39 | boolean Plugin_072(byte function, char *string){ 40 | if (RawSignal.Number !=BYRON_PULSECOUNT) return false; 41 | if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets 42 | if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 425) return false; // first pulse is start bit and must be short 43 | unsigned long bitstream=0L; 44 | //================================================================================== 45 | for(byte x=2;x < BYRON_PULSECOUNT-1;x=x+2) { 46 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 350) { // 200-275 (150-350 is accepted) 47 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 150) return false; // pulse too short 48 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 350) return false; // bad manchester code 49 | bitstream = (bitstream << 1); 50 | } else { // 500-575 (450-650 is accepted) 51 | if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 450) return false; // bad manchester code 52 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 450) return false; // pulse too short 53 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 650) return false; // pulse too long 54 | bitstream = (bitstream << 1) | 0x1; 55 | } 56 | } 57 | //================================================================================== 58 | // Prevent repeating signals from showing up 59 | //================================================================================== 60 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000>4)&0xff);// ID 75 | Serial.print( pbuffer ); 76 | Serial.print(F("SWITCH=1;CMD=ON;")); 77 | sprintf(pbuffer, "CHIME=%02x;", (bitstream)&0xf); // chime number 78 | Serial.print( pbuffer ); 79 | Serial.println(); 80 | //================================================================================== 81 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 82 | RawSignal.Number=0; 83 | return true; 84 | } 85 | #endif // PLUGIN_072 86 | 87 | #ifdef PLUGIN_TX_072 88 | boolean PluginTX_072(byte function, char *string) { 89 | boolean success=false; 90 | //10;BYRON;112233;01;OFF; 91 | //01234567890123456789012 92 | if (strncasecmp(InputBuffer_Serial+3,"BYRON;",5) == 0) { // KAKU Command eg. 93 | if (InputBuffer_Serial[15] != ';') return false; 94 | 95 | InputBuffer_Serial[9]='0'; 96 | InputBuffer_Serial[10]='x'; 97 | InputBuffer_Serial[15]=0; 98 | unsigned int tempbyte1=0; 99 | tempbyte1=str2int(InputBuffer_Serial+9); // get parameter 1 100 | 101 | int tempbyte2=0; 102 | InputBuffer_Serial[14]='0'; 103 | InputBuffer_Serial[15]='x'; 104 | InputBuffer_Serial[18]=0; 105 | tempbyte2=str2int(InputBuffer_Serial+14); // get parameter 2 106 | //----------------------------------------------- 107 | unsigned long bitstream1=tempbyte1; // address 108 | unsigned long bitstream=tempbyte2; // ringtone 109 | 110 | RawSignal.Multiply=50; 111 | RawSignal.Repeats=20; 112 | RawSignal.Delay=3; // 1 = 900 3=2825 5= 6= x 113 | RawSignal.Pulses[1]=BYRONLOW/RawSignal.Multiply; 114 | //RawSignal.Pulses[1]=BYRONSTART/RawSignal.Multiply; 115 | for (byte x=17;x>=2;x=x-1) { 116 | if ((bitstream1 & 1) == 1) 117 | RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply; 118 | else 119 | RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply; 120 | bitstream1 = bitstream1 >> 1; 121 | } 122 | for (byte x=25;x>=18;x=x-1) { 123 | if ((bitstream & 1) == 1) 124 | RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply; 125 | else 126 | RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply; 127 | bitstream = bitstream >> 1; 128 | } 129 | //RawSignal.Pulses[26]=BYRONSTART/RawSignal.Multiply; 130 | RawSignal.Pulses[26]=BYRONSPACE/RawSignal.Multiply; 131 | RawSignal.Number=26; 132 | RawSendRF(); 133 | RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; 134 | success=true; 135 | //----------------------------------------------- 136 | } 137 | return success; 138 | } 139 | #endif // PLUGIN_TX_072 140 | --------------------------------------------------------------------------------