├── Base.ino ├── Config └── Config_01.c ├── Doc ├── RFLink Protocol Reference.txt ├── RFLink Schematic.jpg ├── Readme_Loader.txt ├── Readme_RFLink.txt └── Supported Device List.txt ├── License.txt ├── Misc.ino ├── Plugin.ino ├── Plugins ├── Plugin_001.c ├── Plugin_002.c ├── Plugin_003.c ├── Plugin_004.c ├── Plugin_005.c ├── Plugin_006.c ├── Plugin_007.c ├── Plugin_008.c ├── Plugin_009.c ├── Plugin_010.c ├── Plugin_011.c ├── Plugin_012.c ├── Plugin_013.c ├── Plugin_015.c ├── Plugin_030.c ├── Plugin_031.c ├── Plugin_032.c ├── Plugin_034.c ├── Plugin_040.c ├── Plugin_041.c ├── Plugin_042.c ├── Plugin_043.c ├── Plugin_044.c ├── Plugin_045.c ├── Plugin_046.c ├── Plugin_048.c ├── Plugin_060.c ├── Plugin_061.c ├── Plugin_070.c ├── Plugin_071.c ├── Plugin_072.c ├── Plugin_073.c ├── Plugin_074.c ├── Plugin_080.c ├── Plugin_082.c ├── Plugin_090.c ├── Plugin_100.c ├── Plugin_101.c └── Plugin_254.c ├── README ├── RFLink.ino ├── RawSignal.ino └── Readme_RFLink.txt /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: 38 RX: 17 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 // RGB Switch 24 | #define PLUGIN_011 // Home Confort 25 | #define PLUGIN_012 // Flamingo FA500R 26 | #define PLUGIN_013 // Powerfix/Quigg 27 | #define PLUGIN_015 // Home Easy EU 28 | // ------------------- 29 | // Weather sensors 30 | // ------------------- 31 | #define PLUGIN_030 // Alecto V1 (WS3500) 434 MHz. 32 | #define PLUGIN_031 // Alecto V3 (WS1100/WS1200/WSD-19) 433.9 MHz. 33 | #define PLUGIN_032 // Alecto V4 34 | #define PLUGIN_034 // Cresta 35 | #define PLUGIN_040 // Mebus 36 | #define PLUGIN_041 // LaCrosse v3 ws7000 37 | #define PLUGIN_042 // UPM/Esic 38 | #define PLUGIN_043 // LaCrosse v1 39 | #define PLUGIN_044 // Auriol v3 40 | #define PLUGIN_045 // Auriol 41 | #define PLUGIN_046 // Auriol v2 / Xiron 42 | #define PLUGIN_048 // Oregon V1/2/3 43 | // ------------------- 44 | // Motion Sensors, include when needed 45 | // ------------------- 46 | #define PLUGIN_060 // Ajax Chubb Varel 433 MHz. motion sensors 47 | #define PLUGIN_061 // Chinese PIR motion door and window sensors 48 | // ------------------- 49 | // Doorbells 50 | // ------------------- 51 | #define PLUGIN_070 // Select Plus (Action - Quhwa) 52 | #define PLUGIN_071 // Plieger York 53 | #define PLUGIN_072 // Byron SX doorbell 54 | #define PLUGIN_073 // Deltronic doorbell 55 | #define PLUGIN_074 // RL02 56 | // ------------------- 57 | // Smoke detectors / Fire Places 58 | // ------------------- 59 | #define PLUGIN_080 // Flamingo FA20 / KD101 smoke detector 60 | #define PLUGIN_082 // Mertik Maxitrol / Dru fireplace 61 | // ------------------- 62 | // 868 MHZ 63 | // ------------------- 64 | #define PLUGIN_100 // Alecto V2 (DKW2012/ACH2010) 868 MHz. => PLANNED 65 | // ------------------- 66 | // Housekeeping 67 | // ------------------- 68 | #define PLUGIN_090 // Nodo Slave conversion plugin 69 | #define PLUGIN_254 // Debug to show unsupported packets 70 | // **************************************************************************************************************************************** 71 | // RFLink List of Plugins that have TRANSMIT functionality 72 | // **************************************************************************************************************************************** 73 | // Here are all plugins listed that are supported and used after compilation. 74 | // When needed additional plugins can be added or selected plugins can be enabled/disabled. 75 | // **************************************************************************************************************************************** 76 | // ------------------------------------------------------------------------ 77 | // -- Any of the following protocols can be excluded whenever not needed -- 78 | // ------------------------------------------------------------------------ 79 | #define PLUGIN_TX_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC 80 | #define PLUGIN_TX_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno. 81 | #define PLUGIN_TX_005 // Eurodomest 82 | #define PLUGIN_TX_006 // Blyss 83 | #define PLUGIN_TX_007 // Conrad RSL2 84 | #define PLUGIN_TX_008 // Kambrook 85 | #define PLUGIN_TX_009 // X10 RF 86 | #define PLUGIN_TX_011 // Home Confort 87 | #define PLUGIN_TX_012 // Flamingo FA500R 88 | #define PLUGIN_TX_013 // Powerfix/Quigg 89 | #define PLUGIN_TX_015 // Home Easy EU 90 | // ------------------- 91 | // Doorbells 92 | // ------------------- 93 | #define PLUGIN_TX_070 // Select Plus (Action - Quhwa) 94 | #define PLUGIN_TX_072 // Byron SX doorbell 95 | #define PLUGIN_TX_073 // Deltronic doorbell 96 | #define PLUGIN_TX_074 // RL02 97 | // ------------------- 98 | // Smoke detectors 99 | // ------------------- 100 | #define PLUGIN_TX_080 // Flamingo FA20 / KD101 smoke detector 101 | #define PLUGIN_TX_082 // Mertik Maxitrol / Dru fireplace 102 | // ------------------- 103 | // -=#=- 104 | // ------------------- 105 | -------------------------------------------------------------------------------- /Doc/RFLink Protocol Reference.txt: -------------------------------------------------------------------------------- 1 | Nodo - RFLink 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 RFLink to the master, 10 means from the master to RFLink 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 | Packet structure - Send data via RF: 20 | ------------------------------------ 21 | 10;Name;device;action; 22 | 23 | 10;Kaku;A1;ON; => protocol;address;action (ON/OFF) 24 | 10;NewKaku;00c142;1;ON; => protocol;address;button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level) 25 | 10;HomeEasy;7900b100;3;ON; => protocol;address;action (ON/OFF/ALLON/ALLOFF) 26 | 10;SmokeAlert;123456;ON; => protocol;address;action 27 | 10;FA500;12345678;ON; => protocol;address;action (ON/OFF) 28 | 10;Eurodomest;123456;01;ON; => protocol;address;button number;action (ON/OFF/ALLON/ALLOFF) 29 | 10;Selectplus;1234; => protocol;address 30 | 10;Byron;1234;01 => protocol;address;ringtone; 31 | 10;Blyss;ff98;A1;OFF; => protocol;address;button;action (ON/OFF/ALLON/ALLOFF) 32 | 33 | 34 | Control Commands - Send: 35 | -------------------------- 36 | 10;REBOOT; => Reboot RFLink hardware 37 | 10;PING; => Is replied with: 20;99;PONG; 38 | 10;VERSION; => Is replied with: 20;99;"RFLink software version"; 39 | 10;RFDEBUG=ON; => ON/OFF to Enable/Disable showing of RF packets. Is replied with: 20;99;RFDEBUG="state"; 40 | 10;RFUDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;RFUDEBUG="state"; 41 | 10;QRFDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;QRFDEBUG="state"; 42 | QRFDEBUG is a faster version of RFUDEBUG but all pulse times are shown in hexadecimal and need to be multiplied by 25 43 | 44 | 45 | Data Fields: (LABEL=data) 46 | ------------ 47 | ID=9999 => device ID (often a rolling code and/or device channel number) 48 | SWITCH=A16 => House/Unit code like A1, P2, B16 or a button number etc. 49 | CMD=ON => Command (ON/OFF/ALLON/ALLOFF) 50 | TEMP=9999 => Temperature (hexadecimal), high bit contains negative sign, needs devision by 10 51 | HUM=99 => Humidity (hexadecimal) 52 | BARO=9999 => Barometric pressure (hexadecimal) 53 | HSTATUS=99 => 0=Normal, 1=Comfortable, 2=Dry, 3=Wet 54 | BFORECAST=99 => 0=No Info/Unknown, 1=Sunny, 2=Partly Cloudy, 3=Cloudy, 4=Rain 55 | UV=9999 => UV intensity (hexadecimal) 56 | LUX=9999 => Light intensity (hexadecimal) 57 | BAT=OK => Battery status indicator (OK/LOW) 58 | RAIN=1234 => rain rate in mm. (hexadecimal) 59 | RAINTOT=1234 => total rain in mm. (hexadecimal) 60 | WINSP=9999 => Wind speed in km. p/h (hexadecimal) needs devision by 10 61 | AWINSP=9999 => Average Wind speed in km. p/h (hexadecimal) needs devision by 10 62 | WINGS=9999 => Wind Gust in km. p/h (hexadecimal) 63 | WINDIR=123 => Wind direction 0-15 reflecting 0-360 degrees in 22.5 degree steps (decimal) 64 | WINCHL => wind chill (hexadecimal) 65 | WINTMP=1234 => Wind meter temperature reading (hexadecimal) 66 | CHIME=123 => Chime/Doorbell melody number 67 | SMOKEALERT=ON => ON/OFF 68 | PIR=ON => ON/OFF 69 | CO2=1234 => CO2 air quality 70 | SOUND=1234 => Noise level 71 | KWATT=1234 => KWatt 72 | WATT=1234 => Watt 73 | DIST=1234 => Distance 74 | METER=1234 => Water flow meter 75 | VOLT=1234 => Voltage 76 | CURRENT=1234 => Current 77 | 78 | Sample data: 79 | ------------ 80 | 20;2D;UPM/Esic;ID=0001;TEMP=00cf;HUM=16;BAT=OK; 81 | 20;6A;UPM/Esic;ID=1002;WINSP=0041;WINDIR=5A;BAT=OK; 82 | 20;08;UPM/Esic;ID=1003;RAIN=0010;BAT=OK; 83 | 20;31;Mebus;ID=c201;TEMP=00cf; 84 | 20;32;Auriol;ID=008f;TEMP=00d3;BAT=OK; 85 | 20;A2;Auriol V2;ID=008f;TEMP=00a3;BAT=LOW; 86 | 20;33;Cresta;ID=3001;TEMP=00b0;HUM=50; 87 | 20;0C;Cresta;ID=8001;RAIN=001c; 88 | 20;47;Cresta;ID=8001;WINDIR=0002;WINSP=0060;WINGS=0088;WINCHL=b0; 89 | 20;47;Cresta;ID=8001;TEMP=00b0;UV=00d0; 90 | 20;36;Alecto V1;ID=ec02;TEMP=00d1;HUM=14; 91 | 20;07;Mebus;ID=ea01;TEMP=0017; 92 | 20;3D;Alecto V1;ID=2000;TEMP=0011;HUM=61; 93 | 20;26;Alecto V1;ID=0086;RAIN=02ac; 94 | 20;30;Alecto V1;ID=0020;WINSP=0068; 95 | 20;16;Alecto V1;ID=0020;WINSP=0020; 96 | 20;17;Alecto V1;ID=0020;WINDIR=0002;WINGS=0088; 97 | 20;36;Alecto V1;ID=0020;WINDIR=0002;WINGS=0040; 98 | 20;74;Oregon TempHygro;ID=0ACC;TEMP=00be;HUM=40;BAT=OK; 99 | 20;b3;Oregon TempHygro;ID=1a2d;TEMP=00dd;HUM=43;BAT=OK; 100 | 20;e5;Oregon BTHR;ID=5a6d;TEMP=00be;HUM=40;BARO=03d7;BAT=OK; 101 | 20;46;Oregon Rain;ID=2a1d;RAIN=0012;RAINTOT=0012;BAT=OK; 102 | 20;83;Oregon Rain2;ID=2a19;RAIN=002a;RAINTOT=0054;BAT=OK; 103 | 20;32;Oregon Wind;ID=1a89;WDIR=0045;WINSP=0068;AWINSP=0050;BAT=OK; 104 | 20;4a;Oregon Wind2;ID=3a0d;WDIR=0021;WINSP=0040;AWINSP=005a;BAT=OK; 105 | 20;ba;Oregon UVN128/138;ID=ea7c;UV=0030;BAT=OK; 106 | 20;AF;SelectPlus;ID=1bb4;CHIME=01; 107 | 20;FC;Plieger York;ID=dd01;CHIME=02; 108 | 20;47;Byron SX;ID=a66a;CHIME=A9; 109 | 20;12;Pir;ID=aa66;PIR=ON; 110 | 20;63;SmokeAlert;ID=123456;SMOKEALERT=ON; 111 | 20;06;Kaku;ID=41;SWITCH=1;CMD=ON; 112 | 20;0C;Kaku;ID=41;SWITCH=2;CMD=OFF; 113 | 20;0D;Kaku;ID=41;SWITCH=2;CMD=ON; 114 | 20;46;Kaku;ID=44;SWITCH=4;CMD=OFF; 115 | 20;E0;NewKaku;ID=cac142;SWITCH=1;CMD=ALLOFF; 116 | 20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF; 117 | 20;0B;NewKaku;ID=000005;SWITCH=2;CMD=ON; 118 | 20;0E;NewKaku;ID=000005;SWITCH=2;CMD=OFF; 119 | 20;12;NewKaku;ID=000002;SWITCH=2;CMD=OFF; 120 | 20;1E;NewKaku;ID=00000a;SWITCH=2;CMD=OFF; 121 | 20;1F;NewKaku;ID=00000a;SWITCH=2;CMD=ON; 122 | 20;01;NewKaku;ID=000007;SWITCH=2;CMD=OFF; 123 | 20;04;NewKaku;ID=000007;SWITCH=2;CMD=ON; 124 | 20;04;NewKaku;ID=000007;SWITCH=2;CMD=SET_LEVEL=14; 125 | 20;0C;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLON; 126 | 20;AD;FA500;ID=0d00b900;SWITCH=0001;CMD=UNKOWN; 127 | 20;AE;FA500;ID=0a01;SWITCH=0a01;CMD=OFF; 128 | 20;03;Eurodomest;ID=03696b;SWITCH=00;CMD=OFF; 129 | 20;04;Eurodomest;ID=03696b;SWITCH=07;CMD=ALLOFF; 130 | 20;41;Conrad RSL2;ID=010002;SWITCH=03;CMD=ON; 131 | 20;47;Blyss;ID=ff98;SWITCH=A1;CMD=ON; 132 | 20;73;Kambrook;ID=010203;SWITCH=A1;CMD=OFF; 133 | -------------------------------------------------------------------------------- /Doc/RFLink Schematic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClearlyClaire/RFLink/1b04044c6a0b262e9bba02ed8fe8781031a9ab1c/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 | -------------------------------------------------------------------------------- /Doc/Readme_RFLink.txt: -------------------------------------------------------------------------------- 1 | R29: 2 | - Fixed: AC/NewKaku high unit numbers were incorrect. 3 | If you already have devices with high unit numbers in Domoticz, just throw them away and let them be recognized again 4 | === 5 | R28: 6 | - Fixed: FA20RF smoke detector transmit from Domoticz 7 | === 8 | R27: 9 | - Added: OSV1 battery status 10 | - Fixed: OSV1 boundaries and removed some debug info 11 | - Fixed: Some plugins set an incorrect sampling rate divider value 12 | - Changed: AlectoV1 false positives filter was too agressive 13 | === 14 | R26: 15 | - Added: QRFDEBUG command to do faster logging of undecoded data 16 | - Added: VERSION command 17 | - Added: Powerfix/Quigg switches 18 | - Added: proper Lacrosse V3 WS7000 sensor support 19 | - Changed: config file and plugin integration 20 | - Changed: timeout and divider value 21 | - Changed: Lacrosse V2 WS2300/WS3600 plugin number to get faster processing, changed various other parts as well 22 | - Changed: Lacrosse V1 pulse duration checks 23 | - Changed: various parts to improve speed 24 | - Changed: Flamingo Smoke detector signal re-transmits from 8 to 10 times 25 | - Added: Additional tests on Alecto V1 and Alecto V4 to filter out false positives 26 | - Fixed: AC (NewKaku) protocol send for some device numbers 27 | - Fixed: little bug in UPM code 28 | - Fixed: Oregon wind speed reporting 29 | - Fixed: Wind speed calculations 30 | - Fixed: Wind direction reporting in all plugins 31 | - Fixed: AlectoV3 humidity value displaying out of range values 32 | - Fixed: OregonV1 decoding 33 | === 34 | R25: 35 | - Fixed: Eurodomest address range check 36 | - Fixed: Alecto V1 and V3 humidity handling 37 | - Fixed: Lacrosse WS2300/WS3600 and labelled as LacrosseV2 38 | === 39 | R24: 40 | - Fixed: Flamingo Smoke Detector timings and device address usage 41 | - Fixed: Timing for Nexa/Jula Anslut 42 | === 43 | R23: 44 | - Changed: Alecto V1 temperature data filtering 45 | - Added: Alecto V1 battery status now shown for temperature sensors 46 | === 47 | R22: 48 | - Various additional tests and fixes after intensive tests 49 | - Added: Home Confort send and recognition by Domoticz 50 | === 51 | R21: 52 | - Re-Activated PIR & Door/Window sensors (plugin 60/61) 53 | === 54 | R20: 55 | - Switched to Arduino 1.6.5 56 | === 57 | R19: 58 | - Complete rewrite 59 | - Added: Home Confort Smart Home - TEL-010 60 | - Added: RGB LED Controller 61 | - Added: RL-02 Digital Doorbell 62 | - Added: Deltronic Doorbell 63 | - Added: Sartano 2606 remote & switch 64 | === 65 | r18: 66 | - Added Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor 67 | - Tested Okay: Promax RSL366T, Profile PR-44N & PR-47N 68 | - Fixed: LaCrosse humidity values are correctly displayed 69 | - Fixed: Humidity values that originate from slave Nodos are correctly displayed 70 | - Fixed: UPM/Esic insane temperature values are skipped 71 | - Removed Xiron & Auriol debug data 72 | - Tightened pulse range on various protocols to prevent false positives 73 | === 74 | r17: 75 | - Modified Oregon THGR228N code, 76 | - Modified Newkaku(AC) dim values, 77 | - Corrected support for KAKU door switches, 78 | - Fixed Nodo Slave sensors, 79 | - Improved speed and priorities so that group commands are properly transmitting 80 | === 81 | r16: 82 | - Fixed Aleco V1 temperature ID to match wind sensors 83 | - Fixed HomeEasy transmit 84 | - Added AC(NewKaku) dimmer support 85 | === 86 | r15: 87 | - Improved large packet translation 88 | === 89 | r14: 90 | - Changed Motion sensors (60/61) 91 | === 92 | r13: 93 | - Flamingo Smoke detector fix 94 | - Added Xiron sensor support 95 | === 96 | r11/12: 97 | - Mertik / Dru Send added 98 | === 99 | r10: 100 | - Added Auriol Z32171A 101 | === 102 | r9: 103 | - Fixed Kaku send with high device id's (P1 M1 etc) 104 | === 105 | r8: 106 | - Improved descriptions 107 | === 108 | r7: 109 | - Fixed Oregon RTGR328N ID and humidity format 110 | - Fixed UPM/Esic humidity format 111 | - Fixed Alecto humidity format 112 | === 113 | r6: 114 | - Fixed Auriol V2 plugin 115 | - Updated Auriol plugin 116 | - Fixed Lacrosse Humidity 117 | === 118 | r1/2/3/4/5: 119 | - Added X10 receive/transmit plugin 120 | - Minor changes & improvements 121 | === 122 | 123 | Special thanks to: 124 | Alex, Benoit, Bert, Christophe, Deennoo, Jelle, John, Jonas, Gerrit, Goran, Mark, Martinus, Maurice, Paul, Pim, Remco, Richard, Rob, Sebastien, Thibaut, William 125 | and everyone who contributed with feedback, suggestions, debug data, tests etc. 126 | -------------------------------------------------------------------------------- /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 | - ME FLS 100 19 | - Profile PR-44N, PR-47N 20 | - Sartano 2606 21 | - Impuls 22 | - Elro AB400 23 | - Waveman 24 | - Elro Home Comfort AB600 25 | - (Elro) Home Control 26 | - Smarthome YC-4000B 27 | - Phenix YC-4000S 28 | - Pollin Funk-Dimmer HouseLight FD-UP001 29 | - Pollin Funk-Steckdosen-Set 2605 30 | - Conrad 646443 outlet sockets / RSL366R 31 | - Proteam HO1853 32 | - Velleman WRS3B 33 | 34 | Automatic Code Learning Protocols: (Send + Receive) 35 | - Klik Aan Klik Uit 36 | (among others: AWMR210, AWMT230, AWMD250, AWST8800) 37 | - Nexa Jula Anslut 38 | - Home Easy EU 39 | 40 | Others: (Send + Receive) 41 | - Home Easy (Code Wheel) 42 | - Unitec 48110 EIM 826 / 48111 EIM 821 43 | - Quigg GT-1000 RC / Quigg GT-FSI-08 44 | - Intertek Eurodomest 972080 45 | - Blyss 46 | - Conrad RSL2, Conrad RSL88R/B 47 | - Kambrook RF3399/RF3405/RF3672/RF3689/RF4471R 48 | - X10 RF switches 49 | - Home Confort Smart Home - TEL-010 50 | - Quigg GT-7008BS, Quigg GT-FSI-04 51 | - DMV-7008S 52 | - Powerfix RCB-I 3600 53 | - Rev Ritter REV 8342L 54 | 55 | - Flamingo FA500R/S/DSS/WD 56 | - SilverCrest 91210/60494 RCS AAA3680 57 | - Mumbi M-FS300 58 | - Toom 1919384 59 | ============================================================================ 60 | Weather Sensors: 61 | ---------------- 62 | Alecto V1: 63 | Alecto WS3500, SilverCrest, Otio SH-10, Otio SH-20 64 | Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160 65 | Alecto WS4500, Ventus W044, Balance RF-WS105 66 | Alecto V2: (868 Mhz!) 67 | ACH2010, DKW2012 68 | Alecto V3: 69 | WS1100, WS1200 70 | Alecto V4: 71 | Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor 72 | Cresta/Hideki: 73 | Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W, 74 | WXR810, DV928, Ventus W906, HomeWizard Rain meter 75 | Mebus: 76 | Mebus Outdoor Sensor 77 | Stacja Pogody WS-9941-M 78 | UPM/Esic: 79 | UPM, Esic, Emos, DVM, Clas Ohlson, Dickson 80 | WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700 81 | LaCrosse: 82 | Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4 83 | WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, 84 | WS7000-20: Thermo/Humidity/Barometer, TFA 30.3125 (temperature + humidity), TFA 30.3120.90 (temperature) 85 | LaCrosseV2: 86 | WS2300 (Temperature/Humidity/Wind/Rain), WS3600 87 | Auriol: 88 | Z31743, Rubicson 89 | Auriol V2: 90 | Z31055A-TX, Xiron, Watshome YT6018-2, Technoline 91 | Auriol V3: 92 | Z32171A 93 | Oregon V1/2/3: 94 | THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X, 95 | THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500, 96 | THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122, 97 | THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave , RGR928, 98 | UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, BTHG968 99 | ============================================================================ 100 | Window blinds/shutters/sun screens: 101 | ----------------------------------- 102 | Kaku ASUN650 103 | 104 | ============================================================================ 105 | Motion Detectors & Door/Window sensors: 106 | -------------------------------- 107 | Low Budget Chinese PIR (only signals motion detection) 108 | Low Budget Chinese Door/Window detectors 109 | Ajax Chub Varel PIR (only signals motion detection) 110 | KAKU AMST-606 door/window sensor (separate signals for open and close) 111 | CHACON DIO 54781 (separate signals for open and close) 112 | ============================================================================ 113 | Fireplace: 114 | ---------- 115 | Mertik G6R H4T1 / Dru 116 | ============================================================================ 117 | Smoke Detectors: 118 | ---------------- 119 | KD101 (Send + Receive) 120 | Flamingo FA20RF (Send + Receive) 121 | ============================================================================ 122 | Doorbells: 123 | ---------- 124 | SelectPlus (200689103 - Black - Date code:0614), 1 by One, Delta (O00 QH-0031) (Send + Receive) 125 | SelectPlus (200689101 - White - Date code:0914) (Send + Receive) 126 | Deltronic Wireless Doorbell (Send + Receive) 127 | RL-02 Wireless Doorbell (Send + Receive) 128 | Byron SX (Send + Receive) 129 | Plieger York (Receive) 130 | Note that when the Plieger button is detected as Conrad RSL2, you need to use the button 131 | on the inside of the Plieger doorbell to change the address code of the Plieger. 132 | ============================================================================ 133 | Nodo Slave Sensors: 134 | ------------------- 135 | Temperature, Humidity, UV, barometric Pressure sensors are supported when using 136 | the following Nodo variable numbers: 137 | Variable 11, 12 en 13 : Temperature 138 | Variable 14 : Humidity 139 | Variable 15 : UV 140 | Variable 16 : Barometric pressure 141 | If you require support for other sensors just let us know. 142 | ============================================================================ 143 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClearlyClaire/RFLink/1b04044c6a0b262e9bba02ed8fe8781031a9ab1c/License.txt -------------------------------------------------------------------------------- /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 | return false; 16 | } 17 | /********************************************************************************************\ 18 | * Convert unsigned long to float long through memory 19 | \*********************************************************************************************/ 20 | float ul2float(unsigned long ul) { 21 | float f; 22 | memcpy(&f, &ul,4); 23 | return f; 24 | } 25 | /*********************************************************************************************/ 26 | void PrintHex8(uint8_t *data, uint8_t length) { // prints 8-bit data in hex (lowercase) 27 | char tmp[length*2+1]; 28 | byte first ; 29 | int j=0; 30 | for (uint8_t i=0; i> 4) | 48; 32 | if (first > 57) tmp[j] = first + (byte)39; 33 | else tmp[j] = first ; 34 | j++; 35 | 36 | first = (data[i] & 0x0F) | 48; 37 | if (first > 57) tmp[j] = first + (byte)39; 38 | else tmp[j] = first; 39 | j++; 40 | } 41 | tmp[length*2] = 0; 42 | Serial.print(tmp); 43 | } 44 | /*********************************************************************************************/ 45 | // todo: make uppercase? 3a = 3 or 48 (0x30) = 0x33 >57 (0x39) a>3a >39 > +27 46 | void PrintHexByte(uint8_t data) { // prints 8-bit value in hex (single byte) 47 | char tmp[3]; 48 | byte first ; 49 | first = (data >> 4) | 48; // or with 0x30 50 | if (first > 57) tmp[0] = first + (byte)7; // 39; // if > 0x39 add 0x27 51 | else tmp[0] = first ; 52 | 53 | first = (data & 0x0F) | 48; 54 | if (first > 57) tmp[1] = first + (byte)7; // 39; 55 | else tmp[1] = first; 56 | tmp[2] = 0; 57 | Serial.print(tmp); 58 | } 59 | /*********************************************************************************************/ 60 | 61 | -------------------------------------------------------------------------------- /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 | * Incoming event: "Eurodomest ,, 14 | * Send : "EurodomestSend ,, 15 | * 16 | * Address = hexadecimal address 17 | *********************************************************************************************** 18 | * Technical information: 19 | * 20 | * 0111 00011011 00011111 000 0 21 | * AAAA AAAAAAAA AAAAAAAA BBB C 22 | * 23 | * A = ID (20 bits) 24 | * B = UnitCode (3 bits) 25 | * C = switch code (ON/OFF) (1 bit) 26 | * 27 | * 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; 28 | * 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; 29 | \*********************************************************************************************/ 30 | #define EURODOMEST_PulseLength 50 31 | 32 | #define EURODOMEST_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE 33 | #define EURODOMEST_PULSEMIN 100/RAWSIGNAL_SAMPLE_RATE 34 | #define EURODOMEST_PULSEMAX 900/RAWSIGNAL_SAMPLE_RATE 35 | 36 | #ifdef PLUGIN_005 37 | boolean Plugin_005(byte function, char *string) { 38 | if (RawSignal.Number != EURODOMEST_PulseLength) return false; 39 | unsigned long bitstream=0; 40 | byte unitcode=0; 41 | byte command=0; 42 | unsigned long address=0; 43 | // ========================================================================== 44 | if(RawSignal.Pulses[49] > EURODOMEST_PULSEMID) return false; // last pulse (stop bit) needs to be short, otherwise no Eurodomest protocol 45 | // get all 24 bits 46 | for(int x=2;x < EURODOMEST_PulseLength;x+=2) { 47 | if(RawSignal.Pulses[x] > EURODOMEST_PULSEMID) { // long pulse 48 | if (RawSignal.Pulses[x-1] > EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission 49 | if(RawSignal.Pulses[x] > EURODOMEST_PULSEMAX) return false; // make sure the long pulse is within range 50 | bitstream = (bitstream << 1) | 0x1; 51 | } else { // short pulse 52 | if (RawSignal.Pulses[x] < EURODOMEST_PULSEMIN) return false; // pulse too short to be Eurodomest 53 | if (RawSignal.Pulses[x-1] < EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission 54 | bitstream = (bitstream << 1); 55 | } 56 | } 57 | //================================================================================== 58 | // Prevent repeating signals from showing up 59 | //================================================================================== 60 | if(SignalHash!=SignalHashPrevious || RepeatingTimer> 4) &0xfffff; 72 | if (address==0) return false; // Address would never be 0 73 | if (address==0xfffff) return false; // Address would never be FFFFF 74 | // ---------------------------------- 75 | unitcode=(( bitstream >> 1)& 0x7); 76 | command=((bitstream) & 0x01); 77 | if (unitcode == 3) return false; // invalid button code? 78 | if (unitcode == 4) unitcode--; 79 | // if (unitcode == 5) return false; // Note: unitcode 5 is present on the PCB and working but not used on any remotes. 80 | if (unitcode > 7) return false; // invalid button code? 81 | //================================================================================== 82 | // Output 83 | // ---------------------------------- 84 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 85 | Serial.print( pbuffer ); 86 | // ---------------------------------- 87 | Serial.print(F("Eurodomest;")); // Label 88 | sprintf(pbuffer, "ID=%06lx;",(address)&0xffffff) ; // ID 89 | Serial.print( pbuffer ); 90 | sprintf(pbuffer, "SWITCH=%02x;", unitcode); // ID 91 | Serial.print( pbuffer ); 92 | Serial.print(F("CMD=")); 93 | if ( unitcode > 4) { 94 | Serial.print(F("ALL")); 95 | if ( command == 0) { 96 | Serial.print(F("OFF;")); 97 | } else { 98 | Serial.print(F("ON;")); 99 | } 100 | } else { 101 | if ( command == 1) { 102 | Serial.print(F("OFF;")); 103 | } else { 104 | Serial.print(F("ON;")); 105 | } 106 | } 107 | Serial.println(); 108 | // ---------------------------------- 109 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 110 | RawSignal.Number=0; 111 | return true; 112 | } 113 | #endif //PLUGIN_005 114 | 115 | #ifdef PLUGIN_TX_005 116 | void Eurodomest_Send(unsigned long address); 117 | 118 | boolean PluginTX_005(byte function, char *string) { 119 | //10;EURODOMEST;03696b;0;ON; 120 | //012345678901234567890123456 121 | boolean success=false; 122 | if (strncasecmp(InputBuffer_Serial+3,"EURODOMEST;",11) == 0) { // KAKU Command eg. 123 | unsigned long bitstream=0L; 124 | if (InputBuffer_Serial[20] != ';') return success; 125 | if (InputBuffer_Serial[22] != ';') return success; 126 | 127 | InputBuffer_Serial[12]=0x30; 128 | InputBuffer_Serial[13]=0x78; 129 | InputBuffer_Serial[20]=0x00; 130 | bitstream=str2int(InputBuffer_Serial+12);// Address 131 | InputBuffer_Serial[22]=0x00; 132 | byte temp=str2int(InputBuffer_Serial+21);// Button number 133 | bitstream=(bitstream) << 4; 134 | if (temp == 1) bitstream=bitstream+0x02; // 0010 135 | if (temp == 2) bitstream=bitstream+0x04; // 0100 136 | if (temp == 3) bitstream=bitstream+0x08; // 1000 137 | if (temp == 6) bitstream=bitstream+0x0d; // 1101 138 | if (temp == 7) bitstream=bitstream+0x0f; // 1111 139 | if (temp > 7) { 140 | return success; 141 | } 142 | byte command=0; 143 | command = str2cmd(InputBuffer_Serial+23); 144 | if (command == VALUE_OFF) { 145 | bitstream=bitstream|1; 146 | } 147 | Eurodomest_Send(bitstream); // the full bitstream to send 148 | success=true; 149 | } 150 | return success; 151 | } 152 | 153 | void Eurodomest_Send(unsigned long address) { 154 | int fpulse = 296; // Pulse witdh in microseconds 155 | int fretrans = 7; // Number of code retransmissions 156 | uint32_t fdatabit; 157 | uint32_t fdatamask = 0x800000; 158 | uint32_t fsendbuff; 159 | 160 | digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver 161 | digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter 162 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 163 | 164 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { 165 | fsendbuff=address; 166 | // Send command 167 | for (int i = 0; i < 24; i++) { // Eurodomest packet is 24 bits 168 | // read data bit 169 | fdatabit = fsendbuff & fdatamask; // Get most left bit 170 | fsendbuff = (fsendbuff << 1); // Shift left 171 | 172 | if (fdatabit != fdatamask) { // Write 0 173 | digitalWrite(PIN_RF_TX_DATA, HIGH); 174 | delayMicroseconds(fpulse * 3); 175 | digitalWrite(PIN_RF_TX_DATA, LOW); 176 | delayMicroseconds(fpulse * 1); 177 | } else { // Write 1 178 | digitalWrite(PIN_RF_TX_DATA, HIGH); 179 | delayMicroseconds(fpulse * 1); 180 | digitalWrite(PIN_RF_TX_DATA, LOW); 181 | delayMicroseconds(fpulse * 3); 182 | } 183 | } 184 | digitalWrite(PIN_RF_TX_DATA, HIGH); 185 | delayMicroseconds(fpulse * 1); 186 | digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal 187 | delayMicroseconds(fpulse * 32); 188 | } 189 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 190 | digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off 191 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on 192 | RFLinkHW(); 193 | } 194 | #endif //PLUGIN_TX_005 195 | -------------------------------------------------------------------------------- /Plugins/Plugin_008.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-008 Kambrook ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of receiving of the Kambrook protocol 7 | * Device models: RF3399/RF3405/RF3672/RF3689/RF4471R 8 | * Made by Ningbo Comen Electronics Technology Co. Ltd. 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 | * RF packets contain 96 pulses, 48 bits 19 | * 20 | * Kambrook Message Format: 21 | * AAAAAAAA BBBBBBBB BBBBBBBB BBBBBBBB CCCCCCCC DDDDDDDD 22 | * 23 | * A = Preamble, always 0x55 24 | * B = Address 25 | * C = Channel/Command 26 | * D = Trailing, always 0xFF 27 | * 28 | * Details http://wiki.beyondlogic.org/index.php?title=Reverse_engineering_the_RF_protocol_on_a_Kambrook_Power_Point_Controller 29 | \*********************************************************************************************/ 30 | #define KAMBROOK_PULSECOUNT 96 31 | #define KAMBROOK_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE 32 | 33 | #ifdef PLUGIN_008 34 | boolean Plugin_008(byte function, char *string) { 35 | if (RawSignal.Number != KAMBROOK_PULSECOUNT) return false; 36 | unsigned long address=0L; 37 | byte sync=0; 38 | byte command=0; 39 | byte trailing=0; 40 | 41 | byte bitcounter=0; 42 | byte status=0; 43 | byte channel=0; 44 | byte subchan=0; 45 | //================================================================================== 46 | // get bits 47 | for(byte x=1;x KAMBROOK_PULSEMID) { 49 | if (bitcounter < 8) { 50 | sync = (sync << 1) | 0x1; 51 | } else 52 | if (bitcounter < 32) { 53 | address = (address << 1) | 0x1; 54 | } else 55 | if (bitcounter < 40) { 56 | command = (command << 1) | 0x1; 57 | } else { 58 | trailing = (trailing << 1) | 0x1; 59 | } 60 | bitcounter++; 61 | } else { 62 | if (bitcounter < 8) { 63 | sync = (sync << 1); 64 | } else 65 | if (bitcounter < 32) { 66 | address = (address << 1); 67 | } else 68 | if (bitcounter < 40) { 69 | command = (command << 1); 70 | } else { 71 | trailing = (trailing << 1); 72 | } 73 | bitcounter++; 74 | } 75 | } 76 | //================================================================================== 77 | // all bits received, make sure checksum/sanity check is okay 78 | //================================================================================== 79 | if (sync != 0x55) return false; 80 | if (trailing != 0xff) return false; 81 | //================================================================================== 82 | // Prevent repeating signals from showing up 83 | //================================================================================== 84 | if(SignalHash!=SignalHashPrevious || RepeatingTimer> 1)&7) + 1; // button code 95 | if (status == 0) subchan--; 96 | 97 | byte temp=(command) >> 4; // channel code 98 | channel=0x41+temp; 99 | //================================================================================== 100 | // Output 101 | // ---------------------------------- 102 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number 103 | Serial.print( pbuffer ); 104 | // ---------------------------------- 105 | Serial.print(F("Kambrook;")); // Label 106 | sprintf(pbuffer, "ID=%06lx;",((address)&0xffffff) ); // ID 107 | Serial.print( pbuffer ); 108 | sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan); 109 | Serial.print( pbuffer ); 110 | Serial.print(F("CMD=")); // command 111 | if (status==0) Serial.print(F("OFF;")); 112 | if (status==1) Serial.print(F("ON;")); 113 | Serial.println(); 114 | //================================================================================== 115 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 116 | RawSignal.Number=0; 117 | return true; 118 | } 119 | #endif // PLUGIN_008 120 | 121 | #ifdef PLUGIN_TX_008 122 | void Kambrook_Send(unsigned long address); 123 | 124 | boolean PluginTX_008(byte function, char *string) { 125 | boolean success=false; 126 | //10;kambrook;050325;a1;ON; 127 | //012345678901234567890123 128 | if (strncasecmp(InputBuffer_Serial+3,"KAMBROOK;",9) == 0) { // KAKU Command eg. 129 | if (InputBuffer_Serial[18] != ';') return false; 130 | 131 | InputBuffer_Serial[10]=0x30; 132 | InputBuffer_Serial[11]=0x78; // Get address from hexadecimal value 133 | InputBuffer_Serial[18]=0x00; // Get address from hexadecimal value 134 | 135 | unsigned long bitstream=0L; // Main placeholder 136 | byte Home=0; // channel A..D 137 | byte Address=0; // subchannel 1..5 138 | byte c; 139 | byte x=19; // teller die wijst naar het te behandelen teken 140 | 141 | bitstream=str2int(InputBuffer_Serial+10); // Address 142 | 143 | while((c=tolower(InputBuffer_Serial[x++]))!=';') { 144 | if(c>='0' && c<='9'){Address=Address+c-'0';} // Home 0..9 145 | if(c>='a' && c<='d'){Home=c-'a';} // Address a..d 146 | } 147 | 148 | Address=Address << 1; // shift left 1 bit 149 | c=0; 150 | c = str2cmd(InputBuffer_Serial+x); // ON/OFF command 151 | if (c == VALUE_ON) { 152 | Address--; 153 | } 154 | Address=Address & 0x0f; 155 | // ------------------------------- 156 | Home = Home << 4; // move home to bits 4-7 157 | bitstream=(bitstream) << 8; // shift main value 8 bits left 158 | bitstream=bitstream + Home; // add to main value 159 | bitstream=bitstream + Address; // add address bits to bits 0-3 160 | // ------------------------------- 161 | Kambrook_Send(bitstream); // bitstream to send 162 | success=true; 163 | } 164 | return success; 165 | } 166 | 167 | void Kambrook_Send(unsigned long address) { 168 | int fpulse = 300; // Pulse witdh in microseconds 169 | int fretrans = 5; // Number of code retransmissions 170 | uint32_t fdatabit; 171 | uint32_t fdatamask = 0x800000; 172 | uint32_t fsendbuff; 173 | 174 | digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen. 175 | digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan 176 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 177 | for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { 178 | // -------------- 179 | // Send preamble (0x55) - 8 bits 180 | fsendbuff=0x55; 181 | fdatamask=0x80; 182 | for (int i = 0; i < 8; i++) { // Preamble 183 | // read data bit 184 | fdatabit = fsendbuff & fdatamask; // Get most left bit 185 | fsendbuff = (fsendbuff << 1); // Shift left 186 | if (fdatabit != fdatamask) { // Write 0 187 | digitalWrite(PIN_RF_TX_DATA, HIGH); 188 | delayMicroseconds(fpulse * 1); 189 | digitalWrite(PIN_RF_TX_DATA, LOW); 190 | delayMicroseconds(fpulse * 1); 191 | } else { // Write 1 192 | digitalWrite(PIN_RF_TX_DATA, HIGH); 193 | delayMicroseconds(fpulse * 2); 194 | digitalWrite(PIN_RF_TX_DATA, LOW); 195 | delayMicroseconds(fpulse * 1); 196 | } 197 | } 198 | // -------------- 199 | fsendbuff=address; 200 | fdatamask=0x80000000; 201 | // Send command (channel/address/status) - 32 bits 202 | for (int i = 0; i < 32;i++){ //28;i++){ 203 | // read data bit 204 | fdatabit = fsendbuff & fdatamask; // Get most left bit 205 | fsendbuff = (fsendbuff << 1); // Shift left 206 | if (fdatabit != fdatamask) { // Write 0 207 | digitalWrite(PIN_RF_TX_DATA, HIGH); 208 | delayMicroseconds(fpulse * 1); 209 | digitalWrite(PIN_RF_TX_DATA, LOW); 210 | delayMicroseconds(fpulse * 1); 211 | } else { // Write 1 212 | digitalWrite(PIN_RF_TX_DATA, HIGH); 213 | delayMicroseconds(fpulse * 2); 214 | digitalWrite(PIN_RF_TX_DATA, LOW); 215 | delayMicroseconds(fpulse * 1); 216 | } 217 | } 218 | // -------------- 219 | // Send trailing bits - 8 bits 220 | fsendbuff=0xFF; 221 | fdatamask=0x80; 222 | for (int i = 0; i < 8; i++) { 223 | // read data bit 224 | fdatabit = fsendbuff & fdatamask; // Get most left bit 225 | fsendbuff = (fsendbuff << 1); // Shift left 226 | if (fdatabit != fdatamask) { // Write 0 227 | digitalWrite(PIN_RF_TX_DATA, HIGH); 228 | delayMicroseconds(fpulse * 1); 229 | digitalWrite(PIN_RF_TX_DATA, LOW); 230 | delayMicroseconds(fpulse * 1); 231 | } else { // Write 1 232 | digitalWrite(PIN_RF_TX_DATA, HIGH); 233 | delayMicroseconds(fpulse * 2); 234 | digitalWrite(PIN_RF_TX_DATA, LOW); 235 | delayMicroseconds(fpulse * 1); 236 | } 237 | } 238 | // -------------- 239 | digitalWrite(PIN_RF_TX_DATA, LOW); 240 | delayMicroseconds(fpulse * 20); //14 241 | } 242 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 243 | digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit 244 | digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan. 245 | RFLinkHW(); 246 | } 247 | #endif // PLUGIN_008 248 | -------------------------------------------------------------------------------- /Plugins/Plugin_010.c: -------------------------------------------------------------------------------- 1 | 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-10 RGB Controller ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * Decodes signals from a wireless RGB controller remote control 7 | * 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 | * Decodes signals from a wireless RGB controller remote control 18 | * -------------------------------------------------------------------------------------------- 19 | * _Byte 0_ _Byte 1_ _Byte 2_ _Byte 3_ _Bit_ 20 | * 76543210 76543210 76543210 76543210 0 21 | * AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD E 22 | * 23 | * A = Rolling Code 24 | * B = Rolling Code 25 | * C = Constant, always 0xFF 26 | * D = Command 27 | * E = Checksum. bit is XOR of all bits in the RF message 28 | * 29 | * Commands: 30 | * 00 ON 31 | * 01 OFF 32 | * 02 Dim Down 33 | * 03 DIM UP 34 | * 06 Color Mix UP 35 | * 07 Color Mix Down 36 | * 19 Color Wheel Red 37 | * 29 Color Wheel Blue 38 | * 4D Color Wheel Yellow 39 | * 74 Color Wheel Green 40 | 41 | 10011011 9b YELLOW 42 | 00111000 38 RED 43 | 00111000 BLUE 44 | 11010011 D3 green 45 | 46 | RGB Control:10001101110000101111111100000000 1 20;1B;RGB SWITCH;ID=8dc2;SWITCH=00;CMD=ON; 47 | RGB Control:10001101110000101111111100000000 1 20;1D;RGB SWITCH;ID=8dc2;SWITCH=00;CMD=ON; 48 | RGB Control:10001101110000101111111100010101 0 20;1F;RGB SWITCH;ID=8dc2;SWITCH=15;CMD= 49 | RGB Control:10001101110000101111111111001000 0 20;21;RGB SWITCH;ID=8dc2;SWITCH=c8;CMD= 50 | RGB Control:10001101110000101111111111000000 1 20;23;RGB SWITCH;ID=8dc2;SWITCH=c0;CMD= 51 | RGB Control:10001101110000101111111101000001 1 20;25;RGB SWITCH;ID=8dc2;SWITCH=41;CMD= 52 | \*********************************************************************************************/ 53 | #define RGB_MIN_PULSECOUNT 134 54 | #define RGB_MAX_PULSECOUNT 164 55 | 56 | #define RGB_PULSE_STHI 1500/RAWSIGNAL_SAMPLE_RATE 57 | #define RGB_PULSE_STLO 1200/RAWSIGNAL_SAMPLE_RATE 58 | #define RGB_PULSE_HIHI 1000/RAWSIGNAL_SAMPLE_RATE 59 | #define RGB_PULSE_HILO 750/RAWSIGNAL_SAMPLE_RATE 60 | #define RGB_PULSE_LOHI 625/RAWSIGNAL_SAMPLE_RATE 61 | #define RGB_PULSE_LOLO 250/RAWSIGNAL_SAMPLE_RATE 62 | 63 | 64 | #ifdef PLUGIN_010 65 | boolean Plugin_010(byte function, char *string) { 66 | if (RawSignal.Number < RGB_MIN_PULSECOUNT || RawSignal.Number > RGB_MAX_PULSECOUNT) return false; 67 | unsigned long bitstream=0L; // holds first 32 bits 68 | 69 | byte checksum=0; // holds the checksum calculation 70 | byte crc=0; // holds the crc bit from the signal 71 | byte bitcounter=0; // counts number of received bits (converted from pulses) 72 | byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses 73 | int command=0; 74 | byte start_stop=0; 75 | byte x=1; 76 | //================================================================================== 77 | for(x=1;x 1200 && RawSignal.Pulses[x]*RawSignal.Multiply < 1500) { 80 | if (RawSignal.Pulses[x] > RGB_PULSE_STLO && RawSignal.Pulses[x] < RGB_PULSE_STHI) { 81 | start_stop=0x01; 82 | continue; 83 | } else { 84 | if (x > 100) return false; // bad packet 85 | continue; 86 | } 87 | } 88 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 750 && RawSignal.Pulses[x]*RawSignal.Multiply < 1000) { 89 | if (halfbit==1) { // cant receive a 1 bit after a single low value 90 | return false; // pulse error, must not be a UPM packet or reception error 91 | } 92 | if (bitcounter < 32) { 93 | bitstream = (bitstream << 1) | 0x1; 94 | bitcounter++; // only need to count the first 10 bits 95 | } else { 96 | crc =1; 97 | break; 98 | } 99 | halfbit=0; // wait for next first low or high pulse 100 | } else { 101 | if (RawSignal.Pulses[x]*RawSignal.Multiply > 625 && RawSignal.Pulses[x]*RawSignal.Multiply < 250) return false; // Not a valid UPM pulse length 102 | if (halfbit == 0) { // 2 times a low value = 0 bit 103 | halfbit=1; // first half received 104 | } else { 105 | if (bitcounter < 32) { 106 | bitstream = (bitstream << 1); 107 | checksum=checksum^1; 108 | bitcounter++; // only need to count the first 10 bits 109 | } else { 110 | crc=0; 111 | break; 112 | } 113 | halfbit=0; // wait for next first low or high pulse 114 | } 115 | } 116 | } 117 | //================================================================================== 118 | // Validity checks 119 | if (RawSignal.Pulses[x+2]*RawSignal.Multiply < 1200 || RawSignal.Pulses[x+2]*RawSignal.Multiply > 1500) return false; 120 | //================================================================================== 121 | // perform a checksum check to make sure the packet is a valid RGB control packet 122 | // Checksum1: 3rd byte must be 0xFF 123 | // Checksum2: xor all odd and all even bits should match the last bit 124 | // ---------------------------------- 125 | if ( (bitstream & 0xff00) != 0xff00 ) { 126 | //Serial.println("crc1 error"); 127 | return false; 128 | } 129 | // ---------------------------------- 130 | if (checksum != crc) { 131 | //Serial.println("crc2 error"); 132 | return false; 133 | } 134 | 135 | //Serial.print("RGB Control:"); 136 | //Serial.print(bitstream, BIN); 137 | //Serial.print(" "); 138 | //Serial.print(checksum,BIN); 139 | //Serial.println(); 140 | //================================================================================== 141 | // now process the command 142 | //================================================================================== 143 | command = (bitstream) &0xff; // command 144 | bitstream = (bitstream >> 16) &0xffff; // rolling code 145 | //================================================================================== 146 | // Output 147 | // ---------------------------------- 148 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 149 | Serial.print( pbuffer ); 150 | Serial.print(F("RGB;")); // Label 151 | sprintf(pbuffer, "ID=%04x;", bitstream); // ID 152 | Serial.print( pbuffer ); 153 | sprintf(pbuffer, "SWITCH=%02x;", command); 154 | Serial.print( pbuffer ); 155 | Serial.print(F("CMD=")); 156 | if (command==0x00) Serial.print("ON;"); 157 | else if (command==0x01) Serial.print(F("OFF;")); 158 | else if (command==0x02) Serial.print(F("DIM DOWN;")); 159 | else if (command==0x03) Serial.print(F("DIM UP;")); 160 | else if (command==0x06) Serial.print(F("COLORMIX UP;")); 161 | else if (command==0x07) Serial.print(F("COLORMIX DOWN;")); 162 | else if (command==0x19) Serial.print(F("COLOR RED;")); 163 | else if (command==0x29) Serial.print(F("COLOR BLUE;")); 164 | else if (command==0x4D) Serial.print(F("COLOR YELLOW;")); 165 | else if (command==0x74) Serial.print(F("COLOR GREEN;")); 166 | else { 167 | sprintf(pbuffer, "SET_LEVEL=%d;", command ); 168 | Serial.print( pbuffer ); 169 | } 170 | Serial.println(); 171 | //================================================================================== 172 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 173 | RawSignal.Number=0; 174 | return true; 175 | } 176 | #endif // PLUGIN_010 177 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Plugins/Plugin_045.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-45 Auriol ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol (Z31743) and other devices following the same protocol (Rubicson?) 7 | * 8 | * Author : 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, (32/36 bits, 433 MHz). 17 | * Auriol Message Format: 18 | * 1101 0110 1000 0000 1101 1111 1111 0000 19 | * AAAA AAAA BCCC DDDD DDDD DDDD EEEE FFFG 20 | * 21 | * A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number) 22 | * B = Battery status, 1=OK, 0=LOW 23 | * C = Always 000 24 | * D = Temperature (21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 25 | * E = Unknown 26 | * F = Unknown 27 | * G = sum of all bits xored together 28 | * 29 | * Sample: 30 | * 20;34;DEBUG;Pulses=66;Pulses(uSec)=325,3725,325,1825,325,1825,325,1825,325,3700,325,3700,325,3700,325,3700,325,3700,325,1850,300,1825,325,1850,325,1825,325,1850,325,1825,300,1825,325,3725,300,3725,325,1825,325,1825,300,3725,300,1850,325,3725,300,1850,325,3725,300,3700,300,3725,300,1825,325,3700,325,3700,300,3700,325,1825,325; 31 | * 20;0A;DEBUG;Pulses=66;Pulses(uSec)=325,1850,300,1850,300,3700,300,1850,300,1850,300,1850,325,1850,300,1850,325,3700,325,1850,300,1850,300,1825,325,1850,300,1850,325,1825,300,1850,325,3725,300,3700,325,1825,300,1850,325,3700,300,3725,300,3725,300,1850,300,1850,300,3725,325,3700,300,1850,300,1825,325,1850,300,3700,300,1850,325; 32 | \*********************************************************************************************/ 33 | #define AURIOL_PULSECOUNT 66 34 | 35 | #ifdef PLUGIN_045 36 | boolean Plugin_045(byte function, char *string) { 37 | if (RawSignal.Number != AURIOL_PULSECOUNT) return false; 38 | unsigned long bitstream=0L; 39 | unsigned int temperature=0; 40 | byte rc=0; 41 | byte bat=0; 42 | byte checksumcalc=0; 43 | //================================================================================== 44 | if (RawSignal.Number == AURIOL_PULSECOUNT) { 45 | for(int x=2;x < AURIOL_PULSECOUNT;x+=2) { 46 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 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_046.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-46 Auriol / Xiron ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This plugin takes care of decoding the Auriol protocol for sensor type Z31055A-TX and Xiron 7 | * Watshome YT6018-2 (From Fujian Youtong) 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 | * Decodes signals from a Auriol and Xiron Weatherstation outdoor unit, (36 bits, 433 MHz). 18 | * 19 | * Auriol Message Format: 20 | * 10100100 10 00 000011100110 1111 00000000 Temp = 23.60 21 | * AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF 22 | * A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number) 23 | * B = Battery status indicator on highest bit, 1=OK 0=LOW 24 | * C = Always 00 (Most likely channel number) 25 | * D = Temperature (12 bit, 21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 26 | * E = Always 1111 ? 27 | * F = Always 0000 0000 ? 28 | * 29 | * Xiron Message Format: 30 | * 01101110 10 00 000011101101 1111 00110011 31 | * AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF 32 | * ID ?? Ch Temperature ? Humidity 33 | * 34 | * A = ID (Rolling Code, changes after battery replacement) 35 | * B = Battery status indicator on highest bit, 1=OK 0=LOW 36 | * C = Channel (1,2,3) 37 | * D = Temperature (12 bit, 21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096) 38 | * E = Always 1111 ? 39 | * F = Humidity 40 | * 41 | * 42 | * Sample: 43 | * 20;1F;DEBUG;Pulses=74;Pulses(uSec)=550,1575,525,675,525,1625,500,700,475,725,500,1675,500,700,500,725,475,1675,475,750,450,750,475,725,450,750,450,750,475,750,450,750,475,1675,450,1700,425,1700,450,750,450,750,450,1700,450,1700,450,775,450,1700,450,1700,450,1700,425,1700,425,775,450,775,450,775,425,775,425,775,425,775,450,775,425,775,425, 44 | \*********************************************************************************************/ 45 | #define PLUGIN_ID 46 46 | #define AURIOLV2_PULSECOUNT 74 47 | 48 | #ifdef PLUGIN_046 49 | boolean Plugin_046(byte function, char *string) { 50 | if (RawSignal.Number != AURIOLV2_PULSECOUNT) return false; 51 | unsigned long bitstream1=0L; 52 | unsigned long bitstream2=0L; 53 | byte rc=0; 54 | byte bat=0; 55 | int temperature=0; 56 | int humidity=0; 57 | byte channel=0; 58 | byte bitcounter=0; 59 | byte type=0; 60 | //================================================================================== 61 | // get all the bits we need (36 bits) 62 | for(int x=2;x < AURIOLV2_PULSECOUNT;x+=2) { 63 | if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 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_060.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-060 AlarmSensor ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This protocol provides support for some Alarm sensors that are part of a Varel/Chubb/Ajax alarm 7 | * 8 | * Author : 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 data: 16 | * Devices send 25 pulses, first pulse is part of the start bit. Remaining bits are Manchester encoded, 24 bits 17 | * 18 | * The PCB contains a Holtec HT12E Encoder chip 19 | * The PCB has two switch blocks: SW1 with switches 1-8 (Device code?) 20 | * SW2 with switches 1-4 (House code?) 21 | * 22 | * Sample: 23 | * 20;74;DEBUG;Pulses=26;Pulses(uSec)=425,425,800,875,350,875,350,875,350,875,350,875,350,875,350,875,350,400,800,875,350,400,825,875,350; 24 | * 1001101010101010 01100110 25 | * 10000000 1010 26 | \*********************************************************************************************/ 27 | #define ALARMPIRV2_PULSECOUNT 26 28 | 29 | #define ALARMPIRV2_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE 30 | #define ALARMPIRV2_PULSEMAX 1000/RAWSIGNAL_SAMPLE_RATE 31 | #define ALARMPIRV2_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE 32 | #define ALARMPIRV2_PULSEMIN 250/RAWSIGNAL_SAMPLE_RATE 33 | 34 | #ifdef PLUGIN_060 35 | boolean Plugin_060(byte function, char *string) { 36 | if (RawSignal.Number != ALARMPIRV2_PULSECOUNT) return false; 37 | unsigned long bitstream=0L; 38 | byte data[3]; 39 | if (RawSignal.Pulses[1] > 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) { 45 | if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long 46 | if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 47 | bitstream = (bitstream << 1) | 0x1; 48 | } else { 49 | if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short 50 | if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01 51 | bitstream = bitstream << 1; 52 | } 53 | } 54 | //================================================================================== 55 | // Prevent repeating signals from showing up 56 | //================================================================================== 57 | if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000>16; 66 | if ( (bitstream2)==0xff) { 67 | if ( (bitstream)&0xffff==0xff) return false; 68 | } 69 | //================================================================================== 70 | // Output 71 | // ---------------------------------- 72 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 73 | Serial.print( pbuffer ); 74 | // ---------------------------------- 75 | Serial.print(F("X10;")); // Label 76 | sprintf(pbuffer, "ID=%04x;", (bitstream)&0xffff); // ID 77 | Serial.print( pbuffer ); 78 | sprintf(pbuffer, "SWITCH=%02x;", (bitstream2)&0xff); // ID 79 | Serial.print( pbuffer ); 80 | Serial.print(F("CMD=ON;")); // this device reports movement only 81 | Serial.println(); 82 | //================================================================================== 83 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 84 | RawSignal.Number=0; 85 | return true; 86 | } 87 | #endif // Plugin_061 88 | -------------------------------------------------------------------------------- /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_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 York;")); // 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_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 | -------------------------------------------------------------------------------- /Plugins/Plugin_073.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with the RFLink software package ## 3 | //## Plugin-073 Deltronic Doorbell ## 4 | //####################################################################################################### 5 | /*********************************************************************************************\ 6 | * This Plugin takes care of reception And sending of the Deltronic doorbell 7 | * 8 | * Author : Stuntteam / 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 doorbell uses the UM3750 circuit which sends out a 12 bit signal: 16 | * 17 | * AAAAAAAA BBBB 18 | * 19 | * A = Always 1 20 | * B = Address (Can be either 1, 5 or 9) 21 | * 22 | * Address 1 23 | * 20;0D;DEBUG;Pulses=26;Pulses(uSec)=600,1150,525,1175,500,1175,475,1200,500,1175,500,1200,475,1175,475,1200,475,575,1075,575,1075,575,1075,1225,450; 24 | * 000000001110 25 | * Address 5 26 | * 20;17;DEBUG;Pulses=26;Pulses(uSec)=550,1075,425,1100,400,1125,425,1100,400,1125,400,1150,375,1125,400,1125,375,550,900,1125,375,550,900,1150,375; 27 | * 000000001010 28 | * Address 9 29 | * 20;1B;DEBUG;Pulses=26;Pulses(uSec)=600,1150,500,1175,525,1175,500,1175,500,1175,500,1175,500,1175,475,1200,500,1200,475,575,1075,600,1075,1200,475; 30 | * 000000000110 31 | \*********************************************************************************************/ 32 | #define DELTRONIC_PULSECOUNT 26 33 | #define LENGTH_DEVIATION 300 34 | 35 | #ifdef PLUGIN_073 36 | boolean Plugin_073(byte function, char *string) { 37 | if (RawSignal.Number != DELTRONIC_PULSECOUNT) return false; 38 | //================================================================================== 39 | unsigned long bitstream = 0L; 40 | unsigned long checksum = 0L; 41 | //================================================================================== 42 | if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 eachother. 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 | #define FA20RFSTART 3000 // 8000 33 | #define FA20RFSPACE 675 // 800 34 | #define FA20RFLOW 1250 // 1300 35 | #define FA20RFHIGH 2550 // 2600 36 | #define FA20_PULSECOUNT 52 37 | 38 | #ifdef PLUGIN_080 39 | boolean Plugin_080(byte function, char *string) { 40 | if (RawSignal.Number != FA20_PULSECOUNT) return false; 41 | unsigned long bitstream=0L; 42 | for(byte x=4;x<=FA20_PULSECOUNT-2;x=x+2) { 43 | if (RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE > 1000) return false; // every preceding puls must be < 1000! 44 | if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1800) bitstream = (bitstream << 1) | 0x1; 45 | else bitstream = bitstream << 1; 46 | } 47 | if (bitstream == 0) return false; 48 | if (bitstream == 0xFFFFFF) return false; 49 | if (((bitstream)&0xffff) == 0xffff) return false; 50 | //================================================================================== 51 | // Output 52 | // ---------------------------------- 53 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number 54 | Serial.print( pbuffer ); 55 | // ---------------------------------- 56 | Serial.print(F("FA20RF;")); // Label 57 | sprintf(pbuffer, "ID=%06lx;", bitstream ); // ID 58 | Serial.print( pbuffer ); 59 | Serial.print(F("SMOKEALERT=ON;")); 60 | Serial.println(); 61 | //================================================================================== 62 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 63 | RawSignal.Number=0; // do not process the packet any further 64 | return true; 65 | } 66 | #endif // PLUGIN_080 67 | 68 | #ifdef PLUGIN_TX_080 69 | boolean PluginTX_080(byte function, char *string) { 70 | boolean success=false; 71 | //10;FA20RF;67f570;1;ON; 72 | //012345678901234567890 73 | unsigned long bitstream=0; 74 | if (strncasecmp(InputBuffer_Serial+3,"FA20RF;",7) == 0) { // KAKU Command eg. 75 | if (InputBuffer_Serial[18] != ';') return false; 76 | InputBuffer_Serial[8]=0x30; 77 | InputBuffer_Serial[9]=0x78; 78 | InputBuffer_Serial[16]=0; 79 | bitstream=str2int(InputBuffer_Serial+8); 80 | byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF 81 | if (cmd!=VALUE_ON) return true; // pretend command was ok but we dont have to send anything.. 82 | // ---------- SMOKEALERT SEND ----------- 83 | RawSignal.Multiply=50; 84 | RawSignal.Repeats=10; 85 | RawSignal.Delay=20; 86 | RawSignal.Pulses[1]=FA20RFSTART/RawSignal.Multiply; 87 | //RawSignal.Pulses[2]=FA20RFSPACE/RawSignal.Multiply; 88 | //RawSignal.Pulses[3]=FA20RFSPACE/RawSignal.Multiply; 89 | RawSignal.Pulses[2]=(FA20RFSPACE+125)/RawSignal.Multiply; 90 | RawSignal.Pulses[3]=(FA20RFSPACE+25)/RawSignal.Multiply; 91 | for(byte x=49;x>=3;x=x-2) { 92 | RawSignal.Pulses[x]=FA20RFSPACE/RawSignal.Multiply; 93 | if ((bitstream & 1) == 1) 94 | RawSignal.Pulses[x+1] = FA20RFHIGH/RawSignal.Multiply; 95 | else 96 | RawSignal.Pulses[x+1] = FA20RFLOW/RawSignal.Multiply; 97 | bitstream = bitstream >> 1; 98 | } 99 | RawSignal.Pulses[51]=FA20RFSPACE/RawSignal.Multiply; 100 | RawSignal.Pulses[52]=0; 101 | RawSignal.Number=52; 102 | RawSendRF(); 103 | RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // restore setting 104 | success=true; 105 | } 106 | return success; 107 | } 108 | #endif // PLUGIN_080 109 | -------------------------------------------------------------------------------- /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_090.c: -------------------------------------------------------------------------------- 1 | //####################################################################################################### 2 | //## This Plugin is only for use with Nodo 3.7 Slaves (variablesend support) ## 3 | //## Plugin-090 Nodo Slave ## 4 | //####################################################################################################### 5 | // ********************************************************************************************* 6 | // * This Plugin takes care of reception of Nodo Slave 3.7 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 | // ---------------------------------- 16 | // Variabele 5 : Temperatuur 17 | // Variabele 6 : Luchtvochtigheid 0 - 100 18 | // Variabele 7 : Rain 19 | // Variabele 8 : Wind speed 20 | // Variabele 9 : Wind direction 0 - 15 21 | // Variabele 10 : Wind gust 22 | // Variabele 11, 12 en 13 : Temperatuur 23 | // Variabele 14 : Luchtvochtigheid 0 - 100 24 | // Variabele 15 : Lichtsterkte 0 - 1024 dus mappen naar 1-100 25 | // Variabele 16 : Barometric pressure 26 | // ---------------------------------- 27 | // * Sample: 28 | // * 20;9E;DEBUG;Pulses=194;Pulses(uSec)=3100,900,500,350,1475,375,525,300,1475,375,500,350,450,375,575,250,525,300,1475,375,1450,400,1450,400,425,425,425,425,1425,425,425,425,425,400,425,400,425,400,425,400,425,400,450,400,425,400,450,400,450,400,450,400,425,400,425,425,425,425,425,425,400,425,425,425,400,425,1425,425,400,425,400,425,400,425,400,425,400,425,425,425,400,425,425,425,425,425,1450,425,425,425,425,425,425,425,425,425,400,425,1425,425,1425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,425,425,425,425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,450,400,450,400,450,400,450,400,450,400,450,1400,450,400,450,400,450,400,425,400,450,400,425,1425,425,400,425,1425,425,1425,450,400,450,400,450,375,450,375,450,400,450,1425,450,400,450,1425,425,1425,450,400,450,400,425,400,450,400,450,400,450,400; 29 | // * 20;9F;Slave;ID=0307;DEBUG=0014; 30 | // * slave nodo 7, var 3 value 14 31 | 32 | // 3100,900, 33 | /*( 194-2=192/2 = 96 34 | 500,350,1475,375,525,300,1475,375,500,350,450,375,575,250,525,300,1475,375,1450,400,1450,400,425,425,425,425,1425,425,425,425,425,400,425,400,425,400,425,400,425,400,450,400, 35 | 425,400,450,400,450,400,450,400,425,400,425,425,425,425,425,425,400,425,425,425,400,425,1425,425,400,425,400,425,400,425,400,425,400,425,425,425,400,425,425,425,425,425,1450, 36 | 425,425,425,425,425,425,425,425,425,400,425,1425,425,1425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,425,425,425,425,425,400,425,400,425,400,425,400,425,400,425, 37 | 400,425,400,450,400,450,400,450,400,450,400,450,400,450,1400,450,400,450,400,450,400,425,400,450,400,425,1425,425,400,425,1425,425,1425,450,400,450,400,450,375,450,375,450, 38 | 400,450,1425,450,400,450,1425,425,1425,450,400,450,400,425,400,450,400,450,400,450,400; 39 | 40 | 010100001110010000000 41 | 0000000000010000000001 42 | 000001100000000000000 43 | 000000010000010110000 44 | 01011000000 45 | 46 | 01010000 11100100 00000000 00000000 10000000 00100000 11000000 00000000 00000001 00000101 10000010 11000000 47 | 00001010 00100111 00000000 00000000 00000001 00000100 00000011 00000000 10000000 10100000 01000001 00000011 48 | 50E400008020C0010582C0 49 | A270000104030080A04103 50 | A2^70^00^01^04^03^00^80^A0^41^03 51 | A2^70^00^01^04^03^00^80^A0^41= 52 | */ 53 | // ********************************************************************************************* 54 | #define NODO_PULSE_MID 1000/RAWSIGNAL_SAMPLE_RATE // PWM: Pulsen langer zijn '1' 55 | #define NodoSlave_PULSECOUNT 194 56 | 57 | #ifdef PLUGIN_090 58 | 59 | struct DataBlockStruct { // 16*sizeof(struct DataBlockStruct)+2 = 194 eg. 16*12+2 60 | byte Version; 61 | byte SourceUnit; // event->SourceUnit=DataBlock.SourceUnit&0x1F; // Maskeer de bits van het Home adres. 62 | byte DestinationUnit; // event->DestinationUnit=DataBlock.DestinationUnit; // destination nodo 63 | byte Flags; 64 | byte Type; // event->Type=DataBlock.Type; 65 | byte Command; // event->Command=DataBlock.Command; 66 | byte Par1; // event->Par1=DataBlock.Par1; 67 | unsigned long Par2; // event->Par2=DataBlock.Par2; 68 | byte Checksum; 69 | }; 70 | 71 | boolean Plugin_090(byte function, char *string) { 72 | if (RawSignal.Number!=NodoSlave_PULSECOUNT ) return false; // Per byte twee posities + startbit. 73 | byte b,x,y,z; 74 | 75 | struct DataBlockStruct DataBlock; 76 | byte *B=(byte*)&DataBlock; // B wijst naar de eerste byte van de struct 77 | z=3; // RawSignal pulse teller: 0=niet gebruiktaantal, 1=startpuls, 2=space na startpuls, 3=1e pulslengte. Dus start loop met drie. 78 | 79 | for(x=0;x NODO_PULSE_MID) 83 | b|=1<command = DataBlock.Command = 4 = EVENT_VARIABLE 96 | // ---------------------------------- 97 | // Output 98 | // ---------------------------------- 99 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 100 | Serial.print( pbuffer ); 101 | // ---------------------------------- 102 | Serial.print(F("Slave;")); // Label 103 | sprintf(pbuffer, "ID=%02x%02x;", DataBlock.Par1, DataBlock.SourceUnit); // ID 104 | Serial.print( pbuffer ); 105 | //================================================================================== 106 | if ((DataBlock.Par1 < 5) || (DataBlock.Par1 > 16)) { // Unsupported (for now) variable, just show the contents 107 | int varvalue = ul2float(DataBlock.Par2); // convert 108 | sprintf(pbuffer, "DEBUG=%04x;", varvalue); // value 109 | } else 110 | if ( DataBlock.Par1 < 14) { // Variable 11 12 or 13 : emulate temperature sensor 111 | int temperature = 10 * ul2float(DataBlock.Par2); // convert 112 | if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures 113 | sprintf(pbuffer, "TEMP=%04x;", temperature); // value 114 | } else 115 | if (DataBlock.Par1 == 14){ // Variable 14 : emulate humidity sensor 116 | int humidity = ul2float(DataBlock.Par2) + 0.5; // add 0.5 to make sure it's rounded the way it should and assign as integer to remove decimal value 117 | sprintf(pbuffer, "HUM=%02d;", humidity); // value 118 | } else 119 | if (DataBlock.Par1 == 15){ // Variable 15 : UV sensor 120 | int light = ul2float(DataBlock.Par2); // supplied is value between 0 and 1024 121 | light = map(light, 0,1024,1,100); // Map value to 1 - 100 122 | sprintf(pbuffer, "UV=%04x;", light); // value 123 | } else 124 | if (DataBlock.Par1 == 16){ // Variable 16 : Barometric pressure sensor 125 | int baro = ul2float(DataBlock.Par2); // convert 126 | sprintf(pbuffer, "BARO=%04x;", baro); // value 127 | } else 128 | if (DataBlock.Par1 == 5){ // Variable 5 : temperature 129 | int temperature = 10 * ul2float(DataBlock.Par2); // convert 130 | if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures 131 | sprintf(pbuffer, "TEMP=%04x;", temperature); // value 132 | } else 133 | if (DataBlock.Par1 == 6){ // Variable 6 : humidity 134 | int humidity = ul2float(DataBlock.Par2) + 0.5; // add 0.5 to make sure it's rounded the way it should and assign as integer to remove decimal value 135 | sprintf(pbuffer, "HUM=%02d;", humidity); // value 136 | } else 137 | if (DataBlock.Par1 == 7){ // Variable 7 : Rain in mm. 138 | int rain = ul2float(DataBlock.Par2); // convert 139 | sprintf(pbuffer, "RAIN=%04x;", rain); // value 140 | } else 141 | if (DataBlock.Par1 == 8){ // Variable 8 : Wind speed 142 | int winsp = ul2float(DataBlock.Par2); // convert 143 | sprintf(pbuffer, "WINSP=%04x;", winsp); // value 144 | } else 145 | if (DataBlock.Par1 == 9){ // Variable 9 : Wind Direction 146 | int windir = ul2float(DataBlock.Par2); // convert 147 | sprintf(pbuffer, "WINDIR=%04d;", windir); // value 148 | } else 149 | if (DataBlock.Par1 == 10){ // Variable 10: Wind Gust 150 | int wings = ul2float(DataBlock.Par2); // convert 151 | sprintf(pbuffer, "WINGS=%04x;", wings); // value 152 | } 153 | Serial.print( pbuffer ); 154 | Serial.println(); 155 | //================================================================================== 156 | } else { 157 | if ((DataBlock.Command == 0) && (DataBlock.Type==0)) return false; 158 | // ---------------------------------- 159 | // Output 160 | // ---------------------------------- 161 | sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number 162 | Serial.print( pbuffer ); 163 | // ---------------------------------- 164 | Serial.print(F("Slave;DEBUG=")); // Label 165 | sprintf(pbuffer, "%02x %02x %02x %02x ", DataBlock.Command, DataBlock.Type, DataBlock.SourceUnit, DataBlock.Par1); 166 | Serial.print( pbuffer ); 167 | sprintf(pbuffer, "%d;", DataBlock.Par2); // ID 168 | Serial.print( pbuffer ); 169 | Serial.println(); 170 | } 171 | //================================================================================== 172 | RawSignal.Repeats=true; // suppress repeats of the same RF packet 173 | RawSignal.Number=0; 174 | return true; 175 | } 176 | 177 | #endif // PLUGIN_090 178 | -------------------------------------------------------------------------------- /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_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;xmillis() || 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 | unsigned long LastPulse; 38 | uint8_t Fbit = digitalPinToBitMask(DataPin); 39 | uint8_t Fport = digitalPinToPort(DataPin); 40 | uint8_t FstateMask = (StateSignal ? Fbit : 0); 41 | 42 | if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is 43 | // Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze 44 | // routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit 45 | // geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte 46 | // rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht. 47 | if (RawSignal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel... 48 | if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer! 49 | PulseLength=micros()+SIGNAL_TIMEOUT*1000; // delay 50 | while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros()) 51 | if ((*portInputRegister(Fport) & Fbit) == FstateMask) 52 | PulseLength=micros()+SIGNAL_TIMEOUT*1000; 53 | while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && (*portInputRegister(Fport) & Fbit) != FstateMask); 54 | } 55 | } 56 | RawCodeLength=1; // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc. 57 | Ftoggle=false; 58 | maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli); 59 | do{ // read the pulses in microseconds and place them in temporary buffer RawSignal 60 | numloops = 0; 61 | LastPulse = micros(); 62 | while (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) // while() loop *A* 63 | if (numloops++ == maxloops) break; // timeout 64 | PulseLength = micros() - LastPulse; // Contains pulslength in microseconds 65 | if (PulseLength=MIN_RAW_PULSES) { 70 | RawSignal.Repeats=0; // no repeats 71 | RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // sample size. 72 | RawSignal.Number=RawCodeLength-1; // Number of received pulse times (pulsen *2) 73 | RawSignal.Pulses[RawSignal.Number+1]=0; // Last element contains the timeout. 74 | RawSignal.Time=millis(); // Time the RF packet was received (to keep track of retransmits 75 | return true; 76 | } else { 77 | RawSignal.Number=0; 78 | } 79 | } 80 | return false; 81 | } 82 | /*********************************************************************************************/ 83 | // RFLink Board specific: Generate a short pulse to switch the Aurel Transceiver from TX to RX mode. 84 | void RFLinkHW( void ) { 85 | delayMicroseconds(36); 86 | digitalWrite(PIN_BSF_0,LOW); 87 | delayMicroseconds(16); 88 | digitalWrite(PIN_BSF_0,HIGH); 89 | return; 90 | } 91 | /*********************************************************************************************\ 92 | * Send rawsignal buffer to RF 93 | \*********************************************************************************************/ 94 | void RawSendRF(void) { 95 | int x; 96 | digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen. 97 | digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan 98 | delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) 99 | 100 | // LET OP: In de Arduino versie 1.0.1 zit een bug in de funktie delayMicroSeconds(). Als deze wordt aangeroepen met een nul dan zal er 101 | // een pause optreden van 16 milliseconden. Omdat het laatste element van RawSignal af sluit met een nul (omdat de space van de stopbit 102 | // feitelijk niet bestaat) zal deze bug optreden. Daarom wordt deze op 1 gezet om de bug te omzeilen. 103 | RawSignal.Pulses[RawSignal.Number]=1; 104 | 105 | for(byte y=0; y