1
0
mirror of https://github.com/seahu/rflink.git synced 2025-12-10 16:07:23 +01:00

first commit

This commit is contained in:
Ondrej Lycka
2017-04-29 03:27:02 +02:00
commit 406093e31d
85 changed files with 25806 additions and 0 deletions

620
Plugins/Plugin_001.c Normal file
View File

@@ -0,0 +1,620 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-01: Long Packet Translation and debugging ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of long packets that actually contain multiple RF packets
* Usually caused by a very short delay between RF packets
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical information:
*
* The first part of this plugin outputs all the received pulses from RF packets, use this plugin to
* find signals from new devices. Even if you do not know what to do with the data yourself you might
* want to share your data so others can analyse it and add support for missong protocols.
*
* The second part of this plugin takes care of oversized RF packets that might need to be cut into
* smaller RF packets. Usually the oversized packets are due to a very short delay between re-transmits
* so that multiple packets are seen as one long packet
*
* ELRO HOMEEASY HE842
* The HE842 remote control sends 3 different protocols.
* 8 x Protocol method 1 - 28 bit code (58 pulses)
* 20 x Protocol method 2 - 24 bit code (50 pulses)
* 6 x Protocol method 3 - HE compatible (116 pulses) See Plugin 15
* Method 1 is detected as a 460+ pulse RF packet which we reject.
* 20;19;DEBUG;Pulses=464;Pulses(uSec)=275,950,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,950,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,950,225,950,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,975,200;
* -------------------
* ELRO FLAMINGO FA500
* The FA500R remote control sends 4 different protocols.
* 4 x Protocol method 1 - 28 bit code (58 pulses) - Same as HE842 Method 1
* 3 x Protocol method 2 - AC compatible (132 pulses)
* 3 x Protocol method 3 - HE compatible (116 pulses)
* 5 x Protocol method 4 - 24/12 bit code (24 pulses)
* It appears that the FA500S power switch is only capable to react to the first method!
* RFLink can only distinguish the 3rd method properly. Method 1 and 2 have to be pulled apart first.
* This plugin will split the received signal so that method 1 or 2 can be used.
* In this case we force method 1 so that the remote control can be used with the FA500 switches.
* Method 3: 20;60;DEBUG;Pulses=24;Pulses(uSec)=325,800,275,800,825,225,275,800,275,825,275,800,825,225,275,800,825,225,275,800,275,800,275;
* Method 1&2: 20;1F;DEBUG;Pulses=364;Pulses(uSec)=225,4650,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,825,250,825,250,200,875,825,250,200,875,200,875,825,250,800,250,200,875,200,875,200,875,800,250,800,225,200,875,200,875,825,250,825,250,200,875,800,250,200,875,200,4650,200,875,200,875,825,250,200,875,200,875,800,250,200,875,200,875,825,250,800,250,200,875,800,250,200,875,200,875,825,225,825,250,200,875,200,875,200,875,825,250,800,250,200,875,200,875,825,250,800,225,200,875,800,250,200,875,200,4650,200,875,200,875,800,250,200,875,200,875,825,250,200,875,200,875,800,250,825,250,200,875,800,250,200,875,200,875,800,225,825,250,200,875,200,875,200,875,800,250,800,250,200,875,200,875,800,250,825,225,200,875,800,250,200,875,200,4650,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,825,250,800,250,200,875,825,250,200,875,200,875,800,225,800,250,200,875,200,875,200,875,800,250,825,250,200,875,200,875,800,250,800,250,200,875,825,250,200,875,150,2550,150,175,150,1200,125,175,150,1200,125,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1200,150,1175,150,200,150,175,150,1200,150,175,150,1175,150,175,150,1200,150,1175,150,200,150,1175,150,200,150,175,150,1175,150,1175,150,200,150,1175,150,200,125,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,125,1200,150,175,125,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,1175,150,175,150;
* 20;55;DEBUG;Pulses=58;Pulses(uSec)=275,900,200,900,850,250,200,925,200,925,850,275,875,250,225,950,875,275,875,275,225,950,875,275,225,950,875,275,225,950,225,950,875,275,200,950,875,275,875,275,875,250,875,275,875,275,875,275,875,250,225,950,875,275,200,950,225;
* 20;57;DEBUG;Pulses=130;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1300,150,225,150,200,150,1300,150,1300,150,200,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
* 20;59;DEBUG;Pulses=124;Pulses(uSec)=225,1250,150,175,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
* -------------------
* Auriol
* 20;03;DEBUG;Pulses=511;Pulses(uSec)=425,750,425,775,425,1700,450,1700,450,1675,450,1700,450,750,425,1725,425,1725,425,775,425,800,400,800,400,800,425,800,400,800,425,800,400,1725,400,1750,425,800,400,1750,400,800,400,1750,400,825,400,1750,400,1750,400,1750,400,1750,400,1750,400,800,400,825,400,800,400,825,400,825,400,825,375,825,400,825,400,3725,300,825,400,825,400,1750,400,1750,400,1750,400,1750,400,825,400,1750,400,1750,375,825,400,825,400,825,400,825,400,825,375,825,400,825,375,1750,400,1775,400,825,375,1775,400,825,375,1750,400,825,400,1750,375,1775,400,1750,375,1775,400,1750,400,825,400,825,400,825,400,825,400,825,400,825,400,825,400,825,400,3725,300,825,400,825,400,1750,400,1750,400,1775,400,1750,400,825,400,1750,400,1750,375,825,400,825,400,825,400,825,400,825,400,825,400,825,400,1750,400,1750,400,825,400,1775,400,825,375,1775,400,825,375,1750,375,1750,400,1775,400,1750,400,1775,400,825,375,825,400,825,375,825,400,825,375,825,375,825,400,825,400,3725,275,825,375,825,400,1775,400,1775,375,1750,400,1775,375,825,375,1750,400,1775,400,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1750,400,1775,400,825,375,1775,400,825,375,1750,400,825,375,1775,375,1775,400,1750,375,1775,400,1750,400,825,375,825,400,825,375,825,400,825,375,825,375,825,400,825,375,3750,300,825,375,825,400,1750,400,1775,375,1775,400,1750,375,825,375,1775,400,1775,375,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1775,400,1750,375,825,400,1750,400,825,375,1775,400,825,375,1775,375,1750,400,1775,375,1750,400,1775,400,825,375,825,400,825,375,825,400,825,375,825,400,850,400,825,375,3750,275,825,375,825,400,1775,375,1775,375,1750,400,1775,375,825,400,1775,400,1750,400,825,375,825,375,825,375,850,400,825,375,825,400,825,375,1750,375,1775,375,825,375,1775,375,825,400,1750,400,825,375,1750,375,1775,375,1750,375,1775,400,1775,400,825,375,825,375,825,375,825,400,825,375,825,400,825,400,825,375,3750,275,825,375,825,400,1775,400,1750,375,1775,400,1775,375,825,400,1750,400,1775,400,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1750,400,1775,375,825,375,1775,400,825,375,1750,400,825,375,1775,375,1775,400,1750,375,1775,375,1750,400,825,375,850,375,825,375,825,375,825;
* -------------------
* Xiron
* 20;03;DEBUG;Pulses=511;Pulses(uSec)=600,3425,575,625,550,1600,525,1625,525,700,500,1650,500,1650,475,1675,475,725,475,1650,475,750,475,725,475,750,450,750,475,750,450,750,450,750,450,1700,450,1700,450,750,450,1700,450,750,450,1700,450,1700,450,1700,450,1700,450,1700,450,1700,450,1700,450,775,450,775,450,1700,425,1725,425,775,450,1700,425,775,450,800,425,3575,425,775,450,1700,425,1725,425,775,425,1700,450,1725,450,1700,425,775,425,1725,450,775,425,775,425,775,425,775,425,775,425,775,450,775,425,1700,425,1725,425,775,425,1725,425,775,425,1725,425,1700,450,1700,425,1725,450,1700,450,1725,425,1700,425,775,450,775,425,1725,425,1700,425,775,425,1725,450,775,425,775,425,3600,425,775,450,1725,425,1700,425,775,450,1725,425,1700,425,1725,450,775,450,1700,450,775,425,775,425,775,450,775,425,775,425,775,425,775,425,1725,425,1700,425,775,425,1725,425,775,425,1725,425,1700,425,1725,425,1700,425,1725,450,1700,425,1725,425,775,450,775,425,1700,425,1725,425,775,425,1725,450,775,425,775,425,3575,450,775,425,1700,425,1725,425,775,425,1700,425,1725,425,1700,450,775,450,1700,450,775,450,775,425,775,425,775,450,775,425,775,425,775,425,1700,425,1725,425,775,425,1700,450,775,425,1700,450,1700,425,1700,450,1700,425,1700,425,1700,450,1700,425,775,450,775,450,1700,425,1700,450,775,425,1700,450,775,425,775,425,3600,450,775,425,1725,450,1700,450,775,450,1700,450,1700,450,1700,450,775,450,1725,450,750,450,775,425,775,450,775,425,775,425,775,450,775,425,1725,450,1700,425,800,450,1700,425,775,425,1725,425,1700,425,1725,425,1700,450,1725,425,1700,450,1725,425,775,425,775,425,1700,450,1700,450,775,425,1725,425,775,450,775,425,3575,450,775,425,1700,425,1700,450,775,425,1700,450,1700,450,1700,450,775,450,1700,425,775,450,775,425,775,450,775,425,775,425,775,425,775,425,1700,450,1950,425,800,425,1700,425,775,425,1725,450,1700,425,1725,450,1700,450,1725,425,1700,450,1725,425,775,450,775,425,1700,450,1700,450,775,425,1725,450,775,425,775,425,3575,450,775,425,1700,425,1700,450,775,425,1700,450,1700,425,1700,450,775,450,1700,425,775,450,775,425,775,450,775,425,775,425,800,425,775,425,1700,450,1725,425,775,425,1725,425,775,425,1700,425,1725,425,1700,425,1725,450,1700,425,1725,450,1700,450,775,425,775,450,1700,425,1700;
* 20;06;DEBUG;Pulses=511;Pulses(uSec)=525,3475,525,700,475,1650,475,1675,475,750,450,1700,475,1675,450,1700,450,750,450,1700,425,775,425,775,400,825,400,800,425,800,425,800,400,1750,400,800,400,800,400,825,400,800,400,800,375,1750,400,825,375,825,400,1775,375,1750,400,1750,400,1750,400,825,400,825,400,1750,400,825,400,1750,400,1750,400,1775,375,1775,400,3625,400,825,400,1775,375,1775,400,825,375,1775,400,1750,400,1750,400,825,400,1750,375,825,400,825,400,825,375,825,400,825,375,825,375,1775,375,825,375,850,375,825,375,825,400,825,375,1775,375,825,375,850,350,1775,375,1775,375,1750,400,1775,350,825,375,825,375,1750,375,825,400,1750,375,1775,375,1775,375,1775,375,3650,375,850,375,1775,375,1775,400,825,375,1775,375,1750,400,1775,375,825,375,1775,375,825,375,825,400,850,375,825,400,825,375,825,400,1750,375,825,375,825,375,825,375,825,375,825,350,1775,375,825,375,850,350,1775,375,1775,375,1775,375,1775,375,825,375,825,375,1775,375,825,375,1775,375,1775,375,1775,375,1775,375,3625,400,825,375,1775,375,1750,400,825,375,1775,375,1750,400,1775,375,825,375,1775,375,825,375,825,375,825,375,850,375,825,375,825,375,1750,375,825,375,825,375,850,375,825,375,825,375,1775,375,850,375,825,350,1775,375,1750,375,1800,350,1775,375,825,375,825,375,1775,375,825,375,1775,375,1775,350,1775,375,1750,375,3650,375,825,375,1775,375,1750,400,825,400,1750,375,1775,375,1775,375,850,375,1775,375,825,375,825,400,825,375,825,375,825,375,825,375,1750,375,825,375,825,375,825,350,825,375,825,375,1775,375,825,375,825,350,1775,375,1775,375,1775,375,1775,375,850,350,825,375,1775,375,825,375,1775,375,1775,350,1775,375,1775,375,3650,375,825,375,1775,375,1775,375,825,375,1750,375,1775,375,1775,375,825,375,1775,375,850,350,825,375,825,375,825,375,850,375,850,375,1775,375,825,375,825,375,850,350,825,375,825,375,1775,375,825,375,1075,375,1775,375,1775,375,1775,375,1750,375,825,375,825,375,1775,375,825,375,1775,375,1775,375,1750,400,1775,375,3650,375,825,400,1775,375,1775,375,825,375,1775,375,1775,400,1750,375,825,400,1750,375,825,375,825,375,825,375,825,400,825,375,825,375,1775,375,825,350,825,375,825,375,825,375,850,350,1775,375,850,375,825,375,1775,375,1800,350,1775,375,1750,375,825,375,825,375,1775,375,825;
* 20;0F;DEBUG;Pulses=511;Pulses(uSec)=475,3525,450,775,450,1700,425,1725,425,775,425,1725,425,1725,400,1775,400,825,400,1750,400,825,400,825,375,825,375,825,375,825,375,825,375,1775,375,850,375,850,350,850,350,850,375,1775,375,1775,375,850,375,850,350,1800,375,1775,375,1775,375,1775,350,850,375,850,350,1800,375,1775,375,1775,350,850,350,875,350,1800,350,3675,350,850,350,1775,375,1775,350,850,375,1775,350,1800,350,1775,375,850,350,1800,350,850,350,875,350,850,350,850,325,875,350,875,350,1800,350,875,350,875,325,875,350,850,350,1800,350,1800,350,875,350,875,350,1825,325,1800,350,1800,350,1800,350,875,350,875,325,1800,350,1800,350,1800,350,875,350,875,350,1800,350,3675,350,875,350,1800,350,1800,350,875,325,1800,350,1800,350,1800,350,875,350,1800,350,850,350,850,350,875,350,875,325,875,350,875,350,1800,350,875,350,875,325,875,350,875,350,1800,350,1800,350,875,350,850,350,1800,325,1825,350,1800,350,1800,350,850,350,875,325,1825,325,1800,350,1800,350,875,350,875,350,1825,325,3675,350,875,350,1800,350,1800,350,850,325,1800,350,1800,350,1800,350,875,350,1800,350,850,350,875,350,850,350,850,350,875,350,875,350,1800,350,875,350,875,325,875,350,875,350,1800,350,1800,350,875,325,875,350,1825,325,1825,325,1825,350,1800,350,875,350,875,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,3675,350,875,325,1800,350,1800,375,850,325,1800,350,1800,350,1800,350,850,350,1800,325,875,350,875,350,875,350,875,350,875,350,850,350,1800,350,875,350,875,350,875,350,875,350,1800,325,1825,350,875,325,875,350,1800,350,1800,325,1800,350,1800,350,875,350,875,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,3675,350,875,325,1800,350,1800,350,875,350,1800,350,1800,350,1800,350,850,350,1800,350,850,350,875,350,875,350,875,350,875,350,875,350,1825,350,875,350,875,350,875,350,875,350,1825,325,1800,350,1325,350,875,350,1800,350,1800,350,1800,350,1800,350,875,350,875,350,1800,350,1800,325,1800,350,875,350,875,350,1800,350,3675,350,850,350,1800,350,1800,350,875,350,1800,350,1800,350,1800,350,875,325,1800,350,850,350,850,350,875,350,850,350,850,350,875,325,1800,350,875,350,875,350,875,350,875,325,1800,350,1800,350,875,350,875,350,1800,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,1800; * -------------------
* 20;0B;DEBUG;Pulses=511;Pulses(uSec)=75,125,625,3375,525,675,525,1625,475,725,475,750,475,750,450,775,450,1700,450,1700,450,1700,450,750,450,775,450,1725,425,800,425,800,425,800,425,1725,400,825,400,800,400,1725,425,800,425,775,425,800,400,800,400,800,400,1750,400,1750,400,1750,400,1750,400,825,400,1750,400,800,400,800,400,800,400,1750,400,1750,400,825,400,3625,400,800,400,1750,400,800,400,825,400,825,400,825,375,1775,375,1750,400,1750,375,800,400,800,400,1750,400,825,400,800,400,825,375,1775,375,825,375,825,375,1775,375,825,375,825,375,825,400,825,400,825,400,1750,400,1750,400,1750,375,1775,375,850,375,1775,375,825,375,825,375,825,375,1750,400,1750,400,825,400,3625,400,825,375,1775,375,825,400,825,400,825,400,825,400,1750,375,1775,375,1775,375,825,375,825,375,1775,375,825,375,825,375,825,400,1750,400,825,400,825,400,1750,375,825,375,825,375,825,375,825,375,825,375,1775,375,1775,375,1750,400,1750,400,825,400,1750,400,825,375,850,375,825,375,1775,375,1775,375,825,375,3650,375,825,375,1775,375,825,375,825,375,825,375,825,375,1750,400,1750,400,1750,375,825,400,825,375,1775,375,825,375,825,375,825,375,1775,375,825,375,825,375,1775,400,825,400,825,400,825,400,825,375,850,375,1775,375,1775,375,1775,375,1775,375,825,375,1775,375,825,400,825,400,825,400,1750,400,1750,375,850,375,3650,400,825,400,1750,400,825,400,825,375,825,375,825,375,1775,375,1775,375,1775,375,825,375,850,375,1750,400,825,400,825,400,825,400,1750,375,825,375,825,375,1775,375,825,375,825,375,825,375,825,375,825,400,1750,400,1775,400,1750,400,1750,375,825,375,1775,375,850,375,825,375,825,375,1775,375,1775,375,825,400,3625,400,825,375,1775,400,825,375,825,375,825,400,825,400,1750,400,1750,400,1750,375,825,375,825,375,1775,375,825,375,825,375,825,375,1775,375,825,400,825,400,1750,400,825,400,825,375,850,375,825,375,825,375,1775,375,1775,375,1775,375,1775,375,800,400,1750,400,1300,375,825,400,825,400,1750,400,1750,400,825,375,3650,375,825,400,1750,400,825,400,825,400,825,375,825,375,1775,375,1775,375,1775,375,850,375,850,375,1775,375,825,400,825,375,825,400,1750,400,825,400,825,375,1775,375,825,375,825,375,850,375,825,375,825,375,1775,375,1750,400,1750,400,1750,400,825,400,1750,375,825;
* 20;17;DEBUG;Pulses=511;Pulses(uSec)=550,675,475,1650,525,700,500,700,450,750,450,750,450,1700,450,1700,450,1725,400,775,425,775,425,1725,400,800,425,800,400,775,425,1725,400,800,400,825,400,1750,400,800,425,800,400,825,400,1775,400,825,400,1750,400,1750,400,1750,400,1750,400,800,400,825,400,1775,375,825,400,1750,375,825,375,825,400,825,375,3625,400,825,400,1750,375,825,400,825,375,825,375,825,375,1775,350,1775,375,1775,375,825,400,825,375,1775,375,850,375,825,400,825,400,1775,375,850,375,850,375,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1775,375,1750,400,1775,400,825,375,850,375,1775,375,825,400,1775,375,850,375,850,375,825,375,3650,375,825,375,1775,375,850,375,850,375,825,400,825,375,1750,375,1775,375,1775,375,825,400,825,375,1775,375,850,375,825,375,825,375,1775,375,850,375,850,375,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1800,375,1775,400,1775,375,850,375,850,375,1775,375,825,375,1775,375,850,375,850,375,825,375,3650,375,825,375,1775,375,850,375,850,375,825,400,825,375,1775,375,1775,375,1775,375,825,400,825,350,1775,375,850,375,825,375,825,375,1775,350,850,375,850,350,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1775,375,1775,375,1775,375,825,375,850,375,1775,375,825,375,1775,375,850,375,850,375,850,375,3650,375,825,375,1775,375,825,375,850,375,850,375,825,375,1775,375,1775,375,1800,375,825,375,825,375,1775,375,850,375,825,375,825,375,1775,350,850,375,850,350,1775,375,825,375,850,350,850,375,1800,375,825,375,1775,350,1800,350,1800,375,1775,375,825,375,850,350,1800,375,825,375,1775,350,850,375,850,375,850,375,3650,375,825,375,1775,375,850,375,850,350,850,375,850,375,1775,375,1775,350,1800,375,825,375,825,375,1775,375,850,375,850,375,825,375,1775,350,850,375,850,375,1775,375,825,375,825,375,850,375,1800,375,825,375,1775,375,1800,350,1775,375,1775,375,825,375,850,375,2025,375,850,375,1775,400,825,375,850,375,850,375,3650,375,850,375,1775,400,825,350,850,375,850,375,850,375,1775,375,1775,375,1775,375,850,350,825,375,1775,375,850,375,850,375,825,375,1775,375,825,375,850,375,1800,375,825,375,825,375,825,350,1800,375,850,375,1775,375,1775,375,1775,375,1775,375,825,375,825,375,1775,375,850,375,1775;
auriol..
* BYRON & LIDL doorbells
* The doorbells send the same packet a number of times shortly after each other.
* We just grab one packet out of the lot and kill the remaining ones.
* -------------------
* Home Confort Smart Home - TEL-010
* The Home Confort remote sends the same RF packet at least 6 times over the air. The delay in between the re-transmits is too short to detect individual packets
* So we break, filter and convert the Home Confort RF packets in this plugin
\*********************************************************************************************/
#define OVERSIZED_LIMIT 291 // longest packet is handled by plugin 48
#define PULSE500 500/RAWSIGNAL_SAMPLE_RATE
#define PULSE1100 1100/RAWSIGNAL_SAMPLE_RATE
#define PULSE1600 1600/RAWSIGNAL_SAMPLE_RATE
#define PULSE2000 2000/RAWSIGNAL_SAMPLE_RATE
#define PULSE4000 4000/RAWSIGNAL_SAMPLE_RATE
#define PULSE4200 4200/RAWSIGNAL_SAMPLE_RATE
#define PULSE3300 3300/RAWSIGNAL_SAMPLE_RATE
#define PULSE2500 2500/RAWSIGNAL_SAMPLE_RATE
#define PULSE3000 3000/RAWSIGNAL_SAMPLE_RATE
#define PULSE5000 5000/RAWSIGNAL_SAMPLE_RATE
#define PULSE6000 6000/RAWSIGNAL_SAMPLE_RATE
#define PULSE6500 6500/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_001
boolean Plugin_001(byte function, char *string) {
//Serial.println("P001");
byte HEconversiontype=1; // 0=No conversion, 1=conversion to Elro 58 pulse protocol (same as FA500R Method 1)
int i,j;
// ==========================================================================
// TEST
// ==========================================================================
//PROGMEM int temp[]={4200,625,150,625,150,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,150,625,125,625,125,650,125,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,600,175,600,175,600,175,575,175,575,175,600,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,575,650,100,175,575,175,575,175,575,175,575,175,575,175,575,650,100,175,100,4625,2375,650,100,650,100,675,100,650,100,675,100,650,100,675,100,675,100,675,100,675,100,650,100,650,100,650,100,650,125,650,100,650,125,650,100,650,100,650,100,175,575,175,575,175,575,175,575,175,575,175,575,175,575,200,575,175,575,175,575,175,575,175,575,200,575,200,575,200,575,200,575,200,575,175,575,200,575,200,575,200,575,675,100,200,575,200,575,200,575,200,575,200,575,175,575,675,100,175,100,4625,2375,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,175,575,200,575,175,575,200,575,200,575,200,575,175,575,175,575,200,575,200,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,200,575,675,100,200,575,200,575,200,575,200,575,200,575,200,575,650,100,200,100,4625,2375,650,100,650,100,650,100,675,100,650,100,675,100,650,100,650,100,650,100,650,100,650,100,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,175,600,175,600,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,600,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,600,650,125,175,575,175,575,175,575,175,575,175,575,175,575,650,125,175,125};
//PROGMEM int temp[]={725,150,600,150,600,150,600,150,600,650,125,150,600,175,600,175,600,175,600,175,600,175,600,650,125,175,125,4650,2375,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,175,600,175,600,650,125,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,575,175,575,175,600,650,125,175,575,175,575,175,575,175,575,175,575,175,600,650,125,175,100,4625,2375,300,325};
//PROGMEM int temp[]={550,300,475,300,475,325,950,800,450,325,925,825,925,325,450,350,425,350,425,350,425,825,425,350,900,850,900,850,900,850,875,850,425,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,350,1325,875,400,375,400,375,400,375,875,875,400,400,875,875,875,400,400,400,400,400,400,400,375,875,400,375,875,875,875,875,875,875,875,875,400,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,350,1325,875,400,375,400,375,400,375,875,875,400,375,875,875,875,400,400,400,400,400,400,400,400,875,400,375,875,875,875,875,875,875,875,875,400,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,0,0,0,0,0,0,0,0,0,0,0,0,0};
//PROGMEM int temp[]={625,300,575,275,550,300,1025,875,500,350,1000,925,1000,400,475,400,450,400,450,375,450,900,475,375,1000,925,975,925,975,925,950,925,450,400,450,400,450,400,450,400,450,400,450,400,450,400,950,425,425,375,1450,950,425,425,425,425,425,425,950,950,425,425,950,975,950,425,425,425,425,425,425,425,425,950,425,425,950,950,950,950,950,950,950,950,425,425,425,425,425,425,425,425,425,425,425,425,425,425,950,425,425,375,1450,950,425,425,425,425,425,425,950,950,425,425,950,975,950,425,425,425,425,425,425,425,425,950,425,425,950,950,950,950,950,950,950,950,450,425,425,425,425,425,425,425,425,425,425,425,425,425,950,425,425};
//PROGMEM int temp[]={325,825,875,225,225,875,850,225,225,875,225,875,225,875,225,850,225,875,225,875,225,850,225,850,225,875,825,250,225,875,850,225,225,875,825,250,200,900,825,275,200,900,200,900,200,900,825,250,200};
//pir PROGMEM int temp[]={475,925,400,950,1150,175,400,950,375,950,1125,200,1100,225,1100,250,1075,250,1075,275,1050,275,1050,275,1050,275,1050,275,275,1050,1050,275,300,1050,1050,275,300,1050,300,1050,1050,275,300,1050,275,1050,1050,275,275};
//homeconfort PROGMEM int temp[]={2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,550,250,550,250,550,750,50,250,50};
//eurodomest //20;03;DEBUG;Pulses=50;Pulses(uSec)= PROGMEM int temp[]={275,800,200,800,200,800,175,800,775,225,175,800,200,800,200,800,200,800,775,225,175,800,175,800,775,225,775,225,200,800,775,225,200,800,775,225,200,800,200,800,775,225,775,225,775,225,775,225,175};
//lacrosse hum PROGMEM int temp[]={1400,1300,1325,1300,1325,1275,1350,1150,225,1300,1325,1275,1325,1275,225,1300,1325,1275,225,1275,1350,1275,225,1300,1325,1275,225,1300,225,1275,1350,1275,1350,1275,250,1275,225,1275,1350,1275,1350,1300,225,1300,1350,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,225,1300,1325,1275,1325,1275,1325,1275,250,1275,1350,1275,1325,1300,1325,1275,250,1275,1350,1275,1325,1275,250,1275,1325,1275,250,1275,225,1275,225,1275,1350,1275,225,1275,250,1275,225,1275,1325,1275,250,1275,1350,1300,1325};
//lacrosse temp
//PROGMEM int temp[]={1400,1275,1350,1275,1350,1275,1325,1150,225,1275,1350,1275,1325,1275,225,1300,1325,1275,225,1300,1325,1275,1325,1275,1350,1275,225,1300,225,1275,1350,1275,1350,1300,225,1300,225,1275,1350,1275,1325,1275,250,1275,1350,1275,250,1275,225,1275,225,1275,225,1275,1325,1275,1350,1275,250,1275,1325,1275,1350,1275,1350,1275,225,1275,225,1275,1350,1275,225,1300,1325,1275,1325,1275,1350,1275,250,1275,1325,1275,250,1275,250,1275,225,1275,1350,1275,1350,1275,225,1275,1350,1275,1350,1275,225,1275,1325};
//lacrosse wind
//PROGMEM int temp[]={1400,1275,1350,1275,1350,1275,1325,1150,250,1275,1350,1275,1325,1275,250,1275,1325,1275,1350,1275,225,1275,225,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,1350,1300,225,1275,225,1275,225,1275,225,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1300,1325,1275,225,1275,225,1275,1350,1275,225,1275,225,1300,225,1275,250,1275,225,1275,225,1275,250,1275,225,1275,225,1275,1350,1275,250,1275,225,1275,1325};
//powerfix 2 off
//PROGMEM int temp[]={600,600,1250,625,1225,625,1225,625,1250,1300,550,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,575,625,1225,625,1225,625,1250,625,1225,650,1225,1300,550,625,1175};
//PROGMEM int temp[]={600,600,1250,600,1250,625,1225,625,1225,1275,575,625,1225,625,1225,625,1250,625,1225,650,1200,625,1225,625,1225,1300,550,1300,575,1300,550,1300,575,650,1225,625,1225,625,1225,625,1175};
//PROGMEM int temp[]={3675,950,250,950,250,950,950,250,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,250,250,950,250,950,250,950,950,250,250,950,950,250,250,950,950,275,250,950,950,275,250};
// mising bit 102 pulses //PROGMEM int temp[]={1400,1275,1325,1275,1325,1275,1325,1175,225,1300,1350,1275,1350,1275,225,1300,1325,1300,1325,1275,1325,1300,225,1300,1325,1275,225,1275,225,1300,1325,1275,1325,1275,250,1275,225,1275,1325,1275,1350,1275,225,1275,1325,1275,225,1225,300,1275,250,1275,225,1275,1325,1275,1325,1300,225,1275,225,1275,1325,1300,1325,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,250,1275,1325,1275,1350,1275,225,1275,225,1300,1325,1275,1350,1275,1325,1300,1325,1275,1350,1275,1325};
//lacrosse v3
//PROGMEM int temp[]={825,275,750,275,750,300,750,300,750,300,750,275,750,275,750,300,750,300,750,300,250,800,725,300,750,300,250,800,725,300,225,800,225,800,250,800,250,800,725,300,250,800,725,300,750,300,725,300,250,800,250,800,225,800,750,300,250,800,725,300,250,800,725,300,250,800,725,300,725,300,250,800,725,300,725,300,250,800,725,300,250,800,725,300,725,300,725,300,725,300,250,800,225,800,225,800,725,300,725,300,225,800,225,800,725,300,725,300,725,300,250,800,250,800,725,300,725,300,725,300,250,800,725,300,725,300,725,300,225,800,225,800,225,800,725,300,225,800,225,800,250,800,725,300,225,800,225,800,225,800,250,800,250,800,225,800,725,300,225,800,225,600};
// oregon v1
//PROGMEM int temp[]={1525,1025,1475,1050,1450,2350,1475,1025,2800,1025,1450,2375,1450,1050,2800,2375,1450,1050,1450,1050,1450,1050,1450,1050,2800,1050,1450,2350,1475,1025,1475,1050,1450,1050,1450,1050,1425,1050,1450,1050,1450,1050,2800,2375,2800,2375,2800,1050,1450,1075,1425};
//PROGMEM int temp[]={1725,1100,1650,1100,1650,1100,1650,1100,1650,1100,1650,1100,1625,1125,1625,1125,1625,1125,1625,1100,1625,1100,1625,4150,5675,225,3100,1125,1625,1125,1625,2600,3100,2600,1625,1125,3100,2600,1625,1125,3075,1125,1625,2600,3100,2600,1625,1125,3075,2600,1625,1125,1625,1125,1625,1125,1625,1125,1600,1125,3075,2600,1600,1125,3075,2600,1625,1125,1600,1150,3075,600};
//20;38;DEBUG;Pulses=66;Pulses(uSec)= v1
//PROGMEM int temp[]={1725,1075,1675,1075,1675,1075,1675,1075,1675,1050,1700,1050,1675,4125,5725,5075,1650,2575,3125,1100,1625,2575,1600,1150,3175,2500,1700,1050,1625,1150,3125,2550,3150,1075,1650,2550,1650,1100,1575,1175,3100,2575,1625,1125,1650,1075,1675,1075,1650,1125,1575,1175,3100,1100,1600,2600,1625,1125,1650,1100,1625,1125,1575,1175,3100,600};
//20;04;DEBUG;Pulses=50;Pulses(uSec)=
//PROGMEM int temp[]={300,1020,240,1020,240,1020,240,1020,240,1020,240,1020,240,1020,990,300,240,1020,240,1020,240,1020,240,1020,240,1020,990,270,240,1020,990,300,240,1020,240,1020,240,1020,990,300,240,1020,990,300,240,1020,990,300,240,6990};
// chuango
//PROGMEM int temp[]={1625,425,1550,450,1575,400,525,1450,1575,425,1550,425,475,1550,1450,525,1450,550,375,1525,475,1475,500,1475,1575,400,525,1450,1550,425,1525,500,1475,575,350,1600,400,1550,475,1500,500,1475,1550,425,1550,425,1550,425,450};
//PROGMEM int temp[]={1975,275,900,250,225,975,250,975,250,975,225,975,900,250,900,250,900,250,250,950,225,975,900,250,225,950,225,975,250,950,225,975,900,250,900,250,900,250,250,950,900,250,250,950,225,950,925,250,250};
//Imagintronix:
//PROGMEM int temp[]={390,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1260,870,420,870,1260,870,420,870,1230,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,1230,870,1260,870,420,870,1260,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,420,870,1260,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1230,870,1260,870,420,870,420,870,420,840,420,840,1260,6990};
//20;10;DEBUG;Pulses=42;Pulses(uSec)=Chacon:
//PROGMEM int temp[]={630,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1200,540,1200,570,1170,1230,540,570,1200,540,1200,540,1170,1230,540,6990};
//PROGMEM int temp[]={660,510,1260,510,1260,510,1260,510,1260,540,1260,510,1260,540,1260,540,1230,540,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,6990};
//PROGMEM int temp[]={120,510,90,510,510,90,510,90,120,510,90,510,510,90,510,90,510,90,90,510,120,510,120,510,510,90,510,90,90,510,510,90,510,90,90,510,90,510,120,510,120,510,120,510,510,90,510,90,120,6240,120};
//PROGMEM int temp[]={90,510,510,90,510,90,120,510,510,90,90,510,90,510,510,90,510,90,510,90,120,510,510,90,120,510,510,90,510,90,90,510,90,510,510,90,510,90,510,90,90,510,90,510,510,90,510,90,90,6300,90};
//PROGMEM int temp[]={330,360,270,360,270,330,270,360,270,360,270,360,270,330,270,360,270,360,270,360,270,360,270,3960,660,360,270,780,690,360,690,360,660,360,270,780,270,780,270,780,690,360,270,780,270,780,690,360,270,780,660,360,270,780,270,780,690,360,270,780,660,360,270,780,660,360,270,780,660,360,270,780,270,780,690,360,690,360,660,360,270,780,660,360,690,360,660,360,660,360,660,360,270,780,690,360,660,360,660,360,270,780,660,360,270,780,270,780,270,780,690,360,270,780,690,360,690,360,270,780,660,360,690,360,690,360,270,780,660,360,660,360,690,360,690,360,270,780,270,780,660,360,660,360,660,360,270,780,690,360,660,390,660,360,270,6990};
// bofu
//PROGMEM int temp[]={1200,2370,1560,180,600,210,600,210,600,210,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,210,600,180,600,180,600,180,210,600,600,180,600,180,210,600,210,600,180,600,180,600,600,180,600,210,180,600,180,600,180,600,180,600,210,600,210,600,600,180,600,210,210,600,600,210,210,600,600,210,600,210,210,600,210,600,600,180,600};
//PROGMEM int temp[]={270,600,210,600,210,600,180,600,180,600,180,630,180,600,180,630,180,600,180,600,180,600,180,600,180,6990};
//Alecto
//PROGMEM int temp[]={1800,2010,1710,2010,3690,3960,1710,2010,1710,2010,1710,2010,1710,3960,1710,3960,1710,3960,1710,2010,1710,3960,1740,2010,1710,2010,1710,3960,1710,2010,1710,2010,1710,3960,1710,2010,1710,2010,1710,3960,1740,3960,1710,2010,1710,2010,1710,2010,1710,2010,1710,3960,1710,2010,1710,3960,1710,2010,1710,2010,1710,2010,1710,1980,1710,3960,1710,2010,1710,3960,1710,3960,1710,3960,1710,3960,1710,2010,1710,2010,1710,2010,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,2010,1710,3960,1710,3960,1710,3960,1710,3960,1740,2010,1710,3960,1740,2010,1710,3960,1710,3960,1710,3960,1710,3960,1710,1980,1740,3960,1710,3960,1740,1980,1740,1980,1710,3960,1710,2010,1710,2010,1740,2010,1710,3960,1710,6990};
//PROGMEM int temp[]={360,150,600,180,600,510,300,510,300,510,300,510,300,510,300,210,600,210,630,510,300,210,600,540,300,510,300,210,600,210,600,510,300,180,600,510,300,510,300,210,600,540,300,210,600,510,300,210,600,210,600,540,300,510,270,210,600,6990};
//PROGMEM int temp[]={1200,2370,1530,180,600,210,600,210,600,210,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,180,600,180,600,180,600,180,210,600,600,180,600,180,210,600,180,600,180,600,180,600,600,210,600,210,180,600,180,600,180,600,210,600,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,210,210,600,210,600,600,180,600,6990};
// perel
//PROGMEM int temp[]={420,900,1080,180,360,900,360,900,360,900,1080,180,360,900,1080,210,330,930,1080,210,330,930,330,930,360,930,330,930,330,930,330,930,330,930,330,930,330,930,1080,210,330,930,1080,210,330,930,1080,210,330,6990};
// Europe
//PROGMEM int temp[]={1290,3240,450,3240,450,3240,1230,3240,1230,3240,450,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,450,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1200,3240,1230,3240,1200,3240,1230,3240,450,6990};
//kaku doorbell
//PROGMEM int temp[]={300,950,250,950,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250};
//rev tristate
//PROGMEM int temp[]={330,960,930,270,240,960,930,270,930,270,930,270,240,960,930,270,930,270,930,270,240,960,930,270,240,960,930,270,240,960,240,960,240,930,240,960,240,960,240,960,240,960,240,960,930,270,930,270,240,6990};
//PROGMEM int temp[]={270,990,930,270,210,960,930,270,930,270,930,270,210,960,900,270,210,960,900,270,900,270,900,270,210,960,900,270,210,960,210,960,210,960,210,960,210,960,210,960,900,270,900,270,210,960,210,960,210,6990};
// lidl 3state
//PROGMEM int temp[]={180,930,900,270,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,870,270,210,930,870,270,210,930,210,930,870,270,900,270,210,6990};
// impuls
//PROGMEM int temp[]={60,330,360,30,60,330,360,30,60,330,360,30,60,330,360,30,360,30,360,30,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,360,30,60,330,60,330,60,6990;};
//biowin
//PROGMEM int temp[]={1200,1860,480,1860,480,3780,480,3780,480,3780,480,3780,480,3780,480,3780,480,3810,480,1890,480,3780,480,1860,450,1860,480,3750,480,3780,480,3780,480,1890,480,1860,480,1860,480,1860,480,1860,480,1860,480,3750,480,1890,480,3780,480,1860,480,1860,480,3750,480,1860,480,1860,480,1860,480,3750,480,1890,450,1860,480,1860,480,3750,480,1860,480,3780,480,3780,480,1860,480,1890,480,6990};
//somfy up 88
//PROGMEM int temp[]={1200,2490,2400,2490,4710,1200,1170,1200,1170,1200,1170,1200,540,570,510,570,1170,570,510,570,510,540,540,1200,1170,1200,540,570,1170,570,540,570,510,540,540,570,510,570,540,1200,1170,1200,1170,570,510,1200,1170,570,540,1200,540,570,1170,1200,1170,1200,510,540,540,570,1170,570,540,570,510,1200,540,540,540,570,1170,570,540,1200,1170,540,540,570,540,1200,1170,570,510,570,540,1200,510,6990};
//somfy down? 84
//PROGMEM int temp[]={3540,1140,1110,1140,1110,1140,1140,1200,1170,1200,1170,570,540,570,540,1200,1170,1200,1170,1200,1170,570,510,570,540,1200,510,570,540,570,1170,570,540,1200,1170,570,510,1200,1170,570,540,1200,510,570,1170,1200,1170,1200,510,540,540,540,1170,570,540,570,540,1200,540,540,510,570,1170,570,510,1200,1170,540,540,570,540,1200,1170,540,540,570,540,1200,510,6990};
// somfy my 80
//PROGMEM int temp[]={1200,2490,2400,2490,4710,1200,1170,1200,1170,1200,510,540,1170,1200,540,540,1170,1200,540,540,1170,1200,1170,540,540,1200,1170,1200,510,540,1170,540,540,570,540,540,540,570,540,1200,510,570,510,540,540,540,1170,1200,1170,1200,1170,540,540,1200,510,570,510,570,1170,1200,1170,570,510,570,540,540,540,1200,1170,1200,1170,570,540,570,540,1200,1170,570,540,570,540,1200,1170,6990};
//PROGMEM int temp[]={270,930,210,930,210,930,870,270,180,930,870,270,180,930,870,270,180,930,840,270,180,930,210,930,210,930,870,270,180,930,870,270,180,930,870,270,180,930,870,270,210,930,180,930,180,930,840,270,180,6990};
//Xiron
//PROGMEM int temp[]={990,870,900,870,870,390,390,390,390,870,390,390,870,390,390,900,390,390,390,390,870,390,390,390,390,870,390,390,870,390,390,870,390,390,390,390,900,870,390,390,870,870,870,870,870,390,390,870,870,870,390,390,870,870,390,390,870,390,390,390,390,870,390,390,870,390,390,390,390,390,390,390,390,390,390,870,870,870,870,870,870,390,390,390,390,870,870,390,390,870,390,390,870,870,390,390,870,900,390,390,390,390,390,390,30,6990};
//if (RawSignal.Number==66){
// for (i=0;i<160;i++) {
// //RawSignal.Pulses[1+i]=temp[i]/25;
// RawSignal.Pulses[1+i]=temp[i]/RawSignal.Multiply;
// }
// RawSignal.Number=106;
//}
// -
//if (RawSignal.Number==66){
//Serial.print("20;01;LaCrosseV2;ID=0606;"); // Label
// ----------------------------------
//int sensordata=0x0e; // 9=203 10=225
//sprintf(pbuffer, "WINDIR=%04d;", sensordata);
//Serial.print( pbuffer );
//sensordata=6;
//sensordata=sensordata*36;
//sprintf(pbuffer, "WINGS=%04x;", sensordata);
//Serial.print( pbuffer );
//sprintf(pbuffer, "WINSP=%04x;", sensordata);
//Serial.println( pbuffer );
//}
// ==========================================================================
// Kill ALL Short RF packets
// ==========================================================================
if (RawSignal.Number < 24) { // Less than 24 pulses?
RawSignal.Number=0; // Kill packet
return true; // abort processing
}
// ==========================================================================
// DEBUG
// ==========================================================================
if (RFDebug==true) {
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("DEBUG;Pulses=")); // debug data
Serial.print(RawSignal.Number);
Serial.print(F(";Pulses(uSec)="));
//for(i=1;i<RawSignal.Number;i++) {
for(i=1;i<RawSignal.Number+1;i++) {
Serial.print(RawSignal.Pulses[i]*RawSignal.Multiply);
//if (i < RawSignal.Number-1) Serial.write(',');
if (i < RawSignal.Number) Serial.write(',');
}
Serial.println(";");
}
// ==========================================================================
// Beginning of Signal translation for Impuls
// ==========================================================================
// 20;D7;DEBUG;Pulses=250;Pulses(uSec)=275,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,350,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,75,325,75,350,375,25,75,4700,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,75,325,75,350,375,25,75;
if ((RawSignal.Number == 250) || (RawSignal.Number == RAW_BUFFER_SIZE-1) ) { // Impuls
if (RawSignal.Pulses[50] > PULSE4200) {
if (RawSignal.Pulses[100] > PULSE4200) {
if (RawSignal.Pulses[150] > PULSE4200) {
RawSignal.Number=50; // New packet length
RawSignal.Pulses[0]=33; // signal the plugin number that should process this packet
return false; // packet detected, conversion done
}
}
}
}
// ==========================================================================
// End of Signal translation
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Home Confort Switches/Remotes
// ==========================================================================
if (RawSignal.Number == 200) {
if (RawSignal.Pulses[1] > PULSE2000) {
if (RawSignal.Pulses[100] > PULSE4000) {
if (RawSignal.Pulses[101] > PULSE2000) {
RawSignal.Number=100; // New packet length
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
return false; // packet detected, conversion done
}
}
}
}
// ==========================================================================
// End of Signal translation
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Intertek Unitec Switches/Remotes
// ==========================================================================
if (RawSignal.Number == 202) {
if (RawSignal.Pulses[2] > PULSE2000) {
if (RawSignal.Pulses[52] > PULSE2000) {
if (RawSignal.Pulses[102] > PULSE2000) {
if (RawSignal.Pulses[1] < PULSE500) {
RawSignal.Number=50; // New packet length
RawSignal.Pulses[0]=19; // signal the plugin number that should process this packet
return false; // packet detected, conversion done
}
}
}
}
}
// ==========================================================================
// End of Signal translation
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for HomeEasy HE844 mode 4 - compatibility mode
// ==========================================================================
//if (RawSignal.Number == 234) {
// if (HEconversiontype==0) { // Reject the entire packet
// if ((RawSignal.Pulses[2] > PULSE4000) && (RawSignal.Pulses[2+58] > PULSE4000) && (RawSignal.Pulses[2+58+58] > PULSE4000) ){
// RawSignal.Pulses[0]=15; // Instruct plugin 3 to skip any packets it might see after this
// RawSignal.Number=0; // Kill packet
// return true; // abort processing
// }
// }
//}
// ==========================================================================
// End of Signal translation HomeEasy HE842
// ==========================================================================
// ==========================================================================
// END plugin 001 if the incoming packet is not oversized and resume normal processing of plugins
// there is no need to do all the checks if there never will be a match
if (RawSignal.Number < OVERSIZED_LIMIT) return false;
// ==========================================================================
// ##########################################################################
// ==========================================================================
// Beginning of Signal translation for oversized packets (more pulses than handled by any plugin)
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Flamingo FA500R
// ==========================================================================
if (RawSignal.Number > 330 && RawSignal.Number < 378) {
int pos1=RawSignal.Number - 130;
int pos2=RawSignal.Number - 130 - 58;
if (RawSignal.Pulses[pos1] > PULSE2000 && RawSignal.Pulses[pos2] > PULSE4000) {
for (i=0;i<58;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[pos2+1+i];
}
RawSignal.Pulses[0]=12; // Data will be processed by plugin 12
RawSignal.Number=58; // New packet length
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
// ==========================================================================
// End of Signal Translation
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Conrad RSL
// ==========================================================================
//Conrad RSL
//20;87;DEBUG;Pulses=462;Pulses(uSec)=1260,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6990;
if (RawSignal.Number == 462) {
if ( (RawSignal.Pulses[66] > PULSE6500) && (RawSignal.Pulses[66+66] > PULSE6500) && (RawSignal.Pulses[66+66+66] > PULSE6500) ) {
RawSignal.Number=66; // New packet length
return false; // Conversion done, terminate plugin 1 and continue with regular plugins
}
}
// ==========================================================================
// End of Signal Translation
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for HomeEasy HE842/HE852/HE863
// ==========================================================================
if (RawSignal.Number > 460) { // && RawSignal.Number < 470) {
if (HEconversiontype==0) { // Reject the entire packet
if ((RawSignal.Pulses[2] > PULSE4000) && (RawSignal.Pulses[2+58] > PULSE4000) && (RawSignal.Pulses[2+58+58] > PULSE4000) ){
RawSignal.Pulses[0]=15; // Instruct plugin 3 to skip any packets it might see after this
RawSignal.Number=0; // Kill packet
return true; // abort processing
}
} else { // Convert to Elro Method 1 (same as FA500 Method 1)
int pos1=RawSignal.Number - 58;
//if (RawSignal.Pulses[pos1]*RawSignal.Multiply > 4000) {
if (RawSignal.Pulses[pos1] > PULSE4000) {
for (i=0;i<58;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[pos1+1+i];
}
RawSignal.Number=58; // New packet length
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
// ==========================================================================
// End of Signal translation HomeEasy HE842
// ==========================================================================
// **************************************************************************
// Full buffer size checks, >>>>>> STATIC checks <<<<<
// **************************************************************************
// ==========================================================================
// Beginning of Signal translation for Forrinx
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
if ((RawSignal.Pulses[2] > PULSE6000) && (RawSignal.Pulses[2+50] > PULSE6000) && (RawSignal.Pulses[2+50+50] > PULSE6000)) {
for (i=0;i<50;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[3+i]; // reorder pulse array
}
RawSignal.Number=51; // New packet length (report 51 and not 50 to avoid handling by other plugins
RawSignal.Pulses[0]=76; // signal the plugin number that should process this packet
return false; // packet detected, conversion done
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for bofu
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
if ( (RawSignal.Pulses[1] > PULSE4200) && (RawSignal.Pulses[2] > PULSE2000) && (RawSignal.Pulses[3] > PULSE1100) ) {
if ( (RawSignal.Pulses[1+86] > PULSE4200) && (RawSignal.Pulses[2+86] > PULSE2000) && (RawSignal.Pulses[3+86] > PULSE1100) ) {
RawSignal.Number=85; // New packet length
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
// ==========================================================================
// **************************************************************************
// Full buffer size checks, >>>> SCANNING checks <<<<< sorted by packet size
// **************************************************************************
// ==========================================================================
// Beginning of Signal translation for Silvercrest Doorbell
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
for (j=2;j<114;j++) { // Only check twice the total RF packet length we are looking for
if (RawSignal.Pulses[j] > PULSE1100) { // input is going to fast skip to where new part is going to start
if (j+114 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
if ( (RawSignal.Pulses[j+114] > PULSE1100) && (RawSignal.Pulses[j+114+114] > PULSE1100) && (RawSignal.Pulses[j+114+114+114] > PULSE1100) ) { // first long delay found, make sure we have another at the right position
for (i=0;i<114;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
}
RawSignal.Number=114; // New packet length
RawSignal.Pulses[0]=75; // signal the plugin number that should process this packet
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Home Confort Switches/Remotes
// ==========================================================================
if (RawSignal.Number > 299) { // Scan for corrupted/chained Home Confort RF packets
if (RawSignal.Pulses[1] > PULSE2000) {
if (RawSignal.Pulses[100] > PULSE4000) {
if (RawSignal.Pulses[101] > PULSE2000) {
RawSignal.Number=100; // New packet length
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
return false; // packet detected, conversion done
}
}
}
for (j=1;j<104;j++) {
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 4000) {
if (RawSignal.Pulses[j] > PULSE4000) {
//if (RawSignal.Pulses[j+1]*RawSignal.Multiply > 2000) {
if (RawSignal.Pulses[j+1] > PULSE2000) {
if ( (j+98) > RawSignal.Number) break; // cant be the packet we are looking for
//if ( (RawSignal.Pulses[j+100]*RawSignal.Multiply > 4000) && (RawSignal.Pulses[j+101]*RawSignal.Multiply > 2000) ) { // This could be a Home Confort packet
if ( (RawSignal.Pulses[j+100] > PULSE4000) && (RawSignal.Pulses[j+101] > PULSE2000) ) { // This could be a Home Confort packet
for (i=0;i<100;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+i]; // relocate/reorder pulse array
}
RawSignal.Number=100; // New packet length
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
}
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Auriol & Xiron
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
for (int offset=0; offset < 74; offset++) {
//if (RawSignal.Pulses[offset]*RawSignal.Multiply > 3300) {
if (RawSignal.Pulses[offset+74] > PULSE3300
&& RawSignal.Pulses[offset+74*2] > PULSE3300
&& ((offset > 0 && RawSignal.Pulses[offset] > PULSE3300)
|| RawSignal.Pulses[offset+74*3] > PULSE3300)) {
for (i=0;i<74;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[offset+i+1]; // reorder pulse array
}
RawSignal.Number=74; // New packet length
RawSignal.Pulses[0]=46; // signal the plugin number that should process this packet
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Oregon
// ==========================================================================
//Serial.println("P001");
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
for (j=50;j<104;j++) { // Only check the total RF packet length we are looking for
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
if (RawSignal.Pulses[j] > PULSE1600) { // input is going to fast skip to where new part is going to start
if (j+52 > RAW_BUFFER_SIZE-1) break; // check for overflow, cant be the packet we look for
byte x=0;
if ( (RawSignal.Pulses[j+52] > PULSE1600) && (RawSignal.Pulses[j+52+52] > PULSE1600) && (RawSignal.Pulses[j+52+52+52] > PULSE1600) ) x=2;
if ( (RawSignal.Pulses[j+50] > PULSE1600) && (RawSignal.Pulses[j+50+50] > PULSE1600) && (RawSignal.Pulses[j+50+50+50] > PULSE1600) ) x=1;
if (x !=0) {
for (i=0;i<52;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
}
RawSignal.Number=52; // New packet length
RawSignal.Pulses[0]=63; // signal the plugin number that should process this packet
//Serial.println("P002");
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for SelectPlus
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
for (j=2;j<37;j++) { // Only check the total RF packet length we are looking for
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
if (RawSignal.Pulses[j] > PULSE5000) { // input is going to fast skip to where new part is going to start
if (j+36 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
//if ( (RawSignal.Pulses[j+26]*RawSignal.Multiply > 2500) && (RawSignal.Pulses[j+26]*RawSignal.Multiply < 3000) && (RawSignal.Pulses[j+26+26]*RawSignal.Multiply > 2500) ) { // first long delay found, make sure we have another at the right position
if ( (RawSignal.Pulses[j+36] > PULSE5000) && (RawSignal.Pulses[j+36+36] > PULSE5000) ) { // first long delay found, make sure we have another at the right position
if (j != 36) {
for (i=0;i<36;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
}
}
RawSignal.Number=36; // New packet length
RawSignal.Pulses[0]=70; // signal the plugin number that should process this packet
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
}
// ==========================================================================
// ==========================================================================
// Beginning of Signal translation for Byron Doorbell
// ==========================================================================
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
for (j=2;j<90 /*RawSignal.Number*/;j++) { // Only check twice the total RF packet length we are looking for
// Byron SX
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
if (RawSignal.Pulses[j] > PULSE2500) { // input is going to fast skip to where new part is going to start
if (j+26 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
//if ( (RawSignal.Pulses[j+26]*RawSignal.Multiply > 2500) && (RawSignal.Pulses[j+26]*RawSignal.Multiply < 3000) && (RawSignal.Pulses[j+26+26]*RawSignal.Multiply > 2500) ) { // first long delay found, make sure we have another at the right position
if ( (RawSignal.Pulses[j+26] > PULSE2500) && (RawSignal.Pulses[j+26] < PULSE3000) && (RawSignal.Pulses[j+26+26] > PULSE2500) ) { // first long delay found, make sure we have another at the right position
for (i=0;i<26;i++){
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
}
RawSignal.Number=26; // New packet length
RawSignal.Pulses[0]=72; // signal the plugin number that should process this packet
return false; // Conversion done, stop plugin 1 and continue with regular plugins
}
}
}
}
// ==========================================================================
// ==========================================================================
// End of Signal translation
// ==========================================================================
if (RawSignal.Number > OVERSIZED_LIMIT) { // unknown and unsupported long packet (290 is the max. pulse length used at the Oregon plugin)
RawSignal.Number=0; // no need to show this to any of the other plugins for processing
return true; // abort processing completely
} // as there is no support for it anyway
return false;
}
#endif //PLUGIN_001
/*********************************************************************************************\
167 5010
77 2310
52 1560
161
77
52
0137
77
52
161
77
52
169
78
52
161
77
52
0137
77
52
161
77
52
20;08;DEBUG;Pulses=511;Pulses(uSec)=
5010,2340,1560,210,270,510,270,510,270,540, 9
270,510,270,510,270,510,270,510,270,510, 20
270,510,270,510,270,510,270,510,270,510, 30
270,510,270,510,270,510,600,210,270,510, 4
270,510,270,510,270,540,270,540,600,210, 5
600,210,600,210,270,510,270,540,270,540, 6
270,510,270,510,270,510,270,510,600,210, 69
600,210,600,210,600,210,600,210,600,210, 79
270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,510,270,510,270,510,270,540,270,540,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,540,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,540,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,540,270,540,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,540,270,510,270,510,270,510,270,510,270,540,270,540,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,540,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,540,600,210,600,210,600,210,270,510,270,510,270,510,270,540,270,540,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,510,270,510,270,510,270,540,270,540,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270;
Plugin Pulselength
------ -----------
002 102-104
003 50
004 132 148
005 50
006 106
007 66
008 96
009 66 68
010 134-164
011 100
012 (26) 58
013 42
014 36-52
015 116
030 74
031 94 & 126
032 74-78
034 124-284
035 96
040 58
041 92/162/122/132
042 48-56
043 88
044 82
045 66
046 74
048 126-290
060 26
061 50
070 36
071 66
072 26
073 26
074 50
080 52
081 46
082 26
090 194
100 160 & 164-176
\*********************************************************************************************/

220
Plugins/Plugin_002.c Normal file
View File

@@ -0,0 +1,220 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-41 LaCrosse ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
* It also works for all non LaCrosse sensors that follow this protocol.
* Lacrosse WS2355, WS3600 and compatibles
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Partially based on http://makin-things.com/articles/decoding-lacrosse-weather-sensor-rf-transmissions/
*
* WS2355
* Each packet is 52 bits long. 4 different packet formats are transmitted. They are composed of:
*
* data 0 1 2 3 4 5 6 7 8 9 10
* 1) 0000 1001 01 00 00100010 01111000 01010011 0011 10101100 0001 0+9+4+2+2+7+8+5+3+3+A+C=41 = 1
* 2) 0000 1001 00 01 00100010 01111000 01010000 1101 10101111 1000 0+9+1+2+2+7+8+5+0+D+A+F=48 = 8
* 3) 0000 1001 00 10 00100010 01111000 00001000 1100 11110111 1000
* 4) 0000 1001 01 11 00100010 01111000 00000000 1100 11111111 1101
* SSSS PPPP QR AA BBBBBBBB CCCCCCCC DDDDDDDD dddd EEEEEEEE FFFF
* 0000 1001 01 01 01100110 01011110 10001000 1001 01110111 0100
* 0000 1001 00 11 01100110 01011110 00000000 1101 11111111 0110
* 0000 1001 01 00 01100110 01011110 01000110 1000 10111001 0010
* 0000 1001 00 01 01100110 01011110 01100111 1001 10011000 000 9+1+6+6+5+E+6+7+9+9+8=50 missing bit is 0
0000 1001 01 11 01100110 01011110 00000000 1001 11111111 011 9+7+6+6+5+E+0+0+9+F+F=56 missing bit is 0
* S = Sync
* P = Preamble (1001 for WS2300, 0110 for WS3600?)
* A = packet type 00=TEMP, 01=HUM, 10=RAIN, 11=WIND
* B = Rolling Code
* C = Flags
* D = 12 bit value depending on the device/packet type
* E = Inverted data
* F = Checksum
* Q = 0/1 1=windpacket reports windgust 0=windpacket reports windspeed
* R = Error checking bit
*
* TEMP Dd = temperature - 30 degrees offset, 12 bits, 0x533 - 0x300 = 0x233 = 23.3 degrees
* HUM D = humidity value, 8 bits, 0x50 = RH of 50
* RAIN D = number of tips * 0.508mm (range=0-4095, Once the count reaches 4095 it wraps back to 0. Powerloss results in a reset of the count)
* WIND d = Wind direction (0-15 in 22.5 degrees steps) D= wind speed
*
* Sample:
* 20;D3;DEBUG;Pulses=104;Pulses(uSec)=1400,1300,1325,1300,1325,1275,1350,1150,225,1300,1325,1275,1325,1275,225,1300,1325,1275,225,1275,1350,1275,225,1300,1325,1275,225,1300,225,1275,1350,1275,1350,1275,250,1275,225,1275,1350,1275,1350,1300,225,1300,1350,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,225,1300,1325,1275,1325,1275,1325,1275,250,1275,1350,1275,1325,1300,1325,1275,250,1275,1350,1275,1325,1275,250,1275,1325,1275,250,1275,225,1275,225,1275,1350,1275,225,1275,250,1275,225,1275,1325,1275,250,1275,1350,1300,1325;
* 20;D4;DEBUG;Pulses=104;Pulses(uSec)=1400,1275,1350,1275,1350,1275,1325,1150,250,1275,1350,1275,1325,1275,250,1275,1325,1275,1350,1275,225,1275,225,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,1350,1300,225,1275,225,1275,225,1275,225,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1300,1325,1275,225,1275,225,1275,1350,1275,225,1275,225,1300,225,1275,250,1275,225,1275,225,1275,250,1275,225,1275,225,1275,1350,1275,250,1275,225,1275,1325;
* 20;D5;DEBUG;Pulses=104;Pulses(uSec)=1400,1275,1350,1275,1350,1275,1325,1150,225,1275,1350,1275,1325,1275,225,1300,1325,1275,225,1300,1325,1275,1325,1275,1350,1275,225,1300,225,1275,1350,1275,1350,1300,225,1300,225,1275,1350,1275,1325,1275,250,1275,1350,1275,250,1275,225,1275,225,1275,225,1275,1325,1275,1350,1275,250,1275,1325,1275,1350,1275,1350,1275,225,1275,225,1275,1350,1275,225,1300,1325,1275,1325,1275,1350,1275,250,1275,1325,1275,250,1275,250,1275,225,1275,1350,1275,1350,1275,225,1275,1350,1275,1350,1275,225,1275,1325;
20;C3;DEBUG;Pulses=102;Pulses(uSec)=1400,1275,1325,1275,1325,1275,1325,1175,225,1300,1350,1275,1350,1275,225,1300,1325,1300,1325,1275,1325,1300,225,1300,1325,1275,225,1275,225,1300,1325,1275,1325,1275,250,1275,225,1275,1325,1275,1350,1275,225,1275,1325,1275,225,1225,300,1275,250,1275,225,1275,1325,1275,1325,1300,225,1275,225,1275,1325,1300,1325,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,250,1275,1325,1275,1350,1275,225,1275,225,1300,1325,1275,1350,1275,1325,1300,1325,1275,1350,1275,1325;
20;E1;DEBUG;Pulses=102;Pulses(uSec)=1425,1275,1325,1275,1325,1275,1350,1150,225,1275,1350,1275,1350,1275,250,1275,1350,1275,225,1275,225,1275,250,1275,1350,1275,225,1300,225,1275,1325,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1300,225,1275,1350,1275,250,1275,225,1275,225,1275,250,1275,1325,1275,1350,1275,1325,1275,1325,1275,1325,1275,1350,1275,1350,1275,1325,1300,1325,1275,250,1275,1325,1275,1325,1275,225,1275,250,1275,225,1275,250,1275,225,1300,225,1275,225,1275,225,1300,225,1275,1350,1275,250,1275,225;
\*********************************************************************************************/
#define LACROSSE_PULSECOUNT 104 // also handles 102 pulses!
#define LACROSSE_PULSEMID 1000/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE_MIDLO 1100/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE_MIDHI 1400/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_002
boolean Plugin_002(byte function, char *string) {
if ((RawSignal.Number != LACROSSE_PULSECOUNT) && (RawSignal.Number != (LACROSSE_PULSECOUNT-2))) return false;
unsigned long bitstream1=0L; // holds first 16 bits
unsigned long bitstream2=0L; // holds last 28 bits
unsigned int sensordata=0;
byte checksum=0;
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte sensortype=0;
byte data[12];
//==================================================================================
// get bytes
for(int x=1;x < RawSignal.Number;x+=2) {
if ((RawSignal.Pulses[x+1] < LACROSSE_MIDLO) || (RawSignal.Pulses[x+1] > LACROSSE_MIDHI)) {
if (x+1 < RawSignal.Number) return false; // in between pulse check
}
if (RawSignal.Pulses[x] > LACROSSE_PULSEMID ){
if (bitcounter < 20) {
bitstream1 = (bitstream1 << 1);
bitcounter++; // only need to count the first 20 bits
} else {
bitstream2 = (bitstream2 << 1);
}
} else {
if (bitcounter < 20) {
bitstream1 = (bitstream1 << 1) | 0x1;
bitcounter++; // only need to count the first 20 bits
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
}
}
}
if (RawSignal.Number == (LACROSSE_PULSECOUNT-2)) bitstream2 = (bitstream2 << 1); // add missing zero bit
//==================================================================================
// all bytes received, sort data, do sanity checks and make sure checksum is okay
//==================================================================================
if (bitstream1 == 0) return false;
//if ((bitstream1 == 0) && (bitstream2 == 0)) return false;
//data[0] = (bitstream1 >> 16) & 0x0f; // prepare nibbles from bit stream
//if (data[0] != 0) return false; // just a quick check to make sure the sync bits are correct. they are not needed for the checksum
data[0] = (bitstream1 >> 12) & 0x0f; // First nibble
if ( (data[0] != 0x09) && (data[0] != 0x06) ) { // type verification
return false; // 1001 for WS2300, 0110 for WS3600
}
data[1] = (bitstream1 >> 8) & 0x0f; // Various other checks are possible
data[2] = (bitstream1 >> 4) & 0x0f; // Like parity checks and bit tests
data[3] = (bitstream1 >> 0) & 0x0f; // but false positives do not seem to be a problem
data[4] = (bitstream2 >> 28) & 0x0f;
data[5] = (bitstream2 >> 24) & 0x0f;
data[6] = (bitstream2 >> 20) & 0x0f;
data[7] = (bitstream2 >> 16) & 0x0f;
data[8] = (bitstream2 >> 12) & 0x0f;
data[9] = (bitstream2 >> 8) & 0x0f;
data[10]= (bitstream2 >> 4) & 0x0f;
//==================================================================================
for (byte i=0;i<11;i++){
checksum=checksum + data[i]; // max. value = A5
}
checksum=checksum & 0x0f;
if (checksum != ((bitstream2)&0x0f)) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
sensortype=(data[1])&0x03; // get sensor type from bitstream
unsigned long tempval=((checksum)<<8)+sensortype; // sensor type + checksum
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
SignalCRC=tempval; // not seen this RF packet recently, save value for later
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
// now process the various sensor types
//==================================================================================
// Output
// ----------------------------------
if (sensortype == 0x00) { // Temperature
sensordata = data[6]*100; // 468
sensordata = sensordata + data[7]*10;
sensordata = sensordata + data[8];
if ( (data[0]) == 0x09) { // WS2300
sensordata = sensordata-300;
} else { // WS3600
sensordata = sensordata-400;
}
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";LaCrosseV2;ID=")); // Label
PrintHex8( data+2,2);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", sensordata);
Serial.println( pbuffer );
} else
if (sensortype == 0x01) { // Humidity
sensordata=((data[6])<<4)+data[7];
if (sensordata==0) return false; // Humidity should not be 0
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";LaCrosseV2;ID=")); // Label
PrintHex8( data+2,2);
// ----------------------------------
sprintf(pbuffer, ";HUM=%02x;", (sensordata)&0xff);
Serial.println( pbuffer );
} else
if (sensortype == 0x02) { // Rain
unsigned long rain=((data[6])<<8)+((data[7])<<4)+(data[8]);
if ( (data[0]) == 0x09) { // WS2300
rain=rain*508; // 0-4095 * 0.508mm
rain=rain/350; // divide by 3.5
} else {
rain=rain*518; // 0-4095 * 0.518mm
rain=rain/100;
}
// ---------------------------------- // 8c = 140 = 140*0,518=72,5mm
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";LaCrosseV2;ID=00")); // Label
PrintHex8( data+2,1);
//PrintHex8( data+2,2);
// ----------------------------------
sprintf(pbuffer, ";RAIN=%04x;", (rain)&0xffff);
Serial.println( pbuffer );
} else
if (sensortype == 0x03) { // Wind
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";LaCrosseV2;ID=")); // Label
PrintHex8( data+2,2);
// ----------------------------------
sensordata=(data[8])&0x0f; // wind direction in 22.5 degree steps
sprintf(pbuffer, ";WINDIR=%04d;", sensordata);
Serial.print( pbuffer );
sensordata=((data[6])<<4)+data[7]; // possibly 9 bits?
sensordata=sensordata * 36; // go from m/s to km/hr 6*36=216 = 21,6 km hr = 6 m/s
if ( (data[0]) == 0x09) { // WS2300
sensordata=sensordata / 10; // divide by 10
}
// 216 * 0,0277778
sprintf(pbuffer, "WINGS=%04x;WINSP=%04x;", sensordata, sensordata);
Serial.println( pbuffer );
} else {
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";LaCrosseV2;DEBUG=")); // Label
PrintHex8( data,11);
Serial.println();
//return false;
}
//==================================================================================
RawSignal.Repeats=false;
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_002

936
Plugins/Plugin_003.c Normal file
View File

@@ -0,0 +1,936 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-03: Kaku (ARC) ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the ARC protocol known from Klik-Aan-Klik-Uit (KAKU)
* transmitter, switch, PIR, door sensor etc.
* Devices following the ARC protocol can often be recognized by their manual switch settings for
* the unit and house code number. Like for example by code wheel, dip switch or mini switch.
*
* This plugin also works with the following devices:
* Princeton PT2262 / MOSDESIGN M3EB / Domia Lite / Klik-Aan-Klik-Uit / Intertechno / Sartano 2606.
*
* Author : StuntTeam & Jonas Jespersen (Sartano)
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Address = A0..P16 according to KAKU adressing/notation
***********************************************************************************************
* Het signaal bestaat drie soorten reeksen van vier pulsen, te weten:
* 0 = T,3T,T,3T, 1 = T,3T,3T,T, short 0 = T,3T,T,T Hierbij is iedere pulse (T) 350us PWDM
*
* KAKU Supports:
* on/off, waarbij de pulsreeks er als volgt uit ziet: 000x en x staat voor Off / On
* all on/off, waarbij de pulsreeks er als volgt uit ziet: 001x en x staat voor All Off / All On
***********************************************************************************************
* Brand Model Chipset Timing L/H
* Intertechno ITK200 MDT10P61S 8/43
* Profile PN-47N SC5262 5/26-27
* Elro Home Comfort AB-600MA PT2262 7/29-30 6/30 6/31
* Eurodomest 972080 HS2303
* Elro Home Control AB-440 (Home Control) HX2262
* Elro Home Control AB-4xx (Home Control) HX2272
* Profile PN-44N SC2262 9/34
* ProMax RSL366T SC5262 11/41 10/54 11/54 ?
* Phenix YC-4000S HX2262
* Flamingo FA500R 8/30
* Select Remote 1728029 HS2262 3/22
***********************************************************************************************
* POSSIBLE BIT VARIATIONS: (Note: Bit order is reversed -compared to order in the RF signal- in the description below and in the processing!!!)
* ------------------------ ( real: 1111 0000 011 1 => reversed: 1 110 0000 1111)
* ARC with 0 & F bits:
* -------------------
* KAKU 1 110 0000 0000
* Intertechno ITK200 D CCC BBBB AAAA
* A bit 0-3 = address 2^4 = 16 addresses
* B bit 4-7 = device 2^4 = 16 devices
* C bit 8-10 = always (110) ! (AND with 0x700 result must be 0x600)
* D bit 11 = on/off command (1=on 0=off)
* Timing: 8-9 /33-34 (low/high)
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 1 110 0000 0000 A1 on
* 0 110 0000 0000 A1 off
* 1 110 0001 0000 A2 on
* 0 110 0001 0000 A2 off
* 1 110 0010 0000 A3 on
* 0 110 0010 0000 A3 off
* 1 110 0011 0000 A4 on
* 0 110 0011 0000 A4 off
* 1 110 0000 0000 itk200 on
* 0 110 0000 0000 itk200 off
* -------------------
* Perel 1 1111 1111 11 1
* A BBBB CCCC DD E
* A bit 0 = on/off command
* B bit 1-4 = system code 1111 each bit corresponds to a button number
* C bit 5-8 = device / Unitcode 1111 each bit corresponds to a button number
* D bit 9-10 = always '11'
* E bit 11 = on/off command (1=on 0=off)
* Timing: 8-9 /33-34
* Analyser: 362 / 1086
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 1 110 100 1110 1 1 on
* 0 110 100 1110 0 1 off
* 1 110 101 1110 1 2 on
* 0 110 101 1110 0 2 off
* 1 110 110 1110 1 3 on
* 0 110 110 1110 0 3 off
* -------------------
* Elro Home Easy 0 1 00001 10001
* Elro Home Control D C BBBBB AAAAA
* Brennenstuhl A bit 0-4 = address 2^5 = 32 addresses
* Comfort B bit 5-9 = device
* C bit 10 = unknown (always 1?)
* D bit 11 = on/off command (1=on 0=off)
* Timing: 7-8-9 /29-30
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 1 1 10101 11000 I12 on
* 0 1 10101 11000 I12 off
* 1 1 10011 00000 A7 on
* 0 1 10011 00000 A7 off
* -------------------
* AB400R 0 1 11111 11111
* D C BBBBB AAAAA
* A bit 0-4 = system code - each bit corresponds to a dip switch number (order 54321)
* B bit 5-9 = device/unit code
* C bit 10 = on/off command (reverse of D)
* D bit 11 = on/off command
* Timing: 8 /30
* Analyser: 330/990
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 10 11110 11110 A ON
* 10 11101 11110 B ON
* 10 11011 11110 C ON
* 10 10111 11110 D ON
* 01 11110 11110 A OFF
* 01 11101 11110 B OFF
* 01 11011 11110 C OFF
* 01 10111 11110 D OFF
* -------------------
* Sartano: 0 1 00001 10001
* Phenix YC-4000B D C BBBBB AAAAA
* A bit 0-4 = address 2^5 = 32 addresses / Housecode
* B bit 5-9 = device / Unitcode each bit corresponds to a button number
* C bit 10 = off command (inverse command)
* D bit 11 = on command
* Timing: 11-12 /31-37
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 01 01000 00000
* -------------------
* ProMAX: 0 111 0000 0001
* D CCC BBBB AAAA
* A bit 0-3 = address 2^5 = 32 addresses / Housecode
* B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number
* C bit 8-10 = Always 111
* D bit 11 = on command
* Timing: 10-11 / 40-41
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 111111101110 1 ON
* 111111011110 2 ON
* 111110111110 3 ON
* 111101111110 4 ON
* 011111101110 1 OFF
* 011111011110 2 OFF
* 011110111110 3 OFF
* 011101111110 4 OFF
* -------------------
* ProFile: 0 110 0001 0001
* D CCC BBBB AAAA
* A bit 0-3 = address 2^4 = 16 addresses / Housecode
* B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number
* C bit 8-10 = Always 110
* D bit 11 = on command
* Timing: 9/34
* Pulses: 0101 and 0110 eg. bit state 0 and f
* 111000000000 1 ON
* 111000010000 2 ON
* 111000100000 3 ON
* 111000110000 4 ON
* 011000000000 1 OFF
* 011000010000 2 OFF
* 011000100000 3 OFF
* 011000110000 4 OFF
* -------------------
* ProFile:
* Everflourish 0 110 0001 0001
* EMW203 D CCC BBBB AAAA
* A bit 0-3 = Button A/B/C/D
* B bit 4-6 = Button 1/2/3
* C bit 7-10 = Always 1111
* D bit 11 = on/off command (on = tri-state)
* Timing: 14/55
* Analyser:
* Pulses: 0101, 1010 and 0110 eg. bit state 0, 1 and f
* 211111101110 A1 on
* 211111011110 A2 on
* 211110111110 A3 on
* 211111101101 B1 on
* 211111011101 B2 on
* 211110111101 B3 on
* 011111101110 A1 off
* 011111011110 A2 off
* 011110111110 A3 off
* 011111101101 B1 off
* 011111011101 B2 off
* 011110111101 B3 off
* -------------------
* -------------------
* 0 111 0000 1 000 reverse: 000 1 0000 111 0 and EF1 = 0?
* A BBB CCCC D EEE
* SelectRemote A/C/E = always 0 0000 000 !
* Blokker: B bit 1-3 = device number
* D bit 8 = on/off command
* Timing: 0-1-2 /33-34
* Analyser: 232 / 692
* Pulses: 0101 and 1010 eg. bit state 0 and 1
* -------------------
* 1111 111111 11
* AAAA BBBBBB CC
* Action: A bit 0-3 = address 2^4 = 16 addresses
* Impuls B bit 4-9 = device
* C bit 10-11= on/off command 10=on 01=off
* -------------------
* 10100 00010 0 0
* AAAAA BBBBB C D
* InterTechno A bit 0-4 = address 2^5 = 32 addresses
* Düwi Terminal B bit 5-9 = device
* Cogex C bit 10 = always 0
* D bit 11 = on/off command
* -------------------
* 20;DB;DEBUG;Pulses=50;Pulses(uSec)=425,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,950,300,250,1050,950,300,250,1025,950,300,250;
*
* KAKU Doorbell 010111101111
* 20;07;DEBUG;Pulses=50;Pulses(uSec)=300,950,250,950,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250;
* 20;09;DEBUG;Pulses=50;Pulses(uSec)=3675,950,250,950,250,950,950,250,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250,950,250,950,250,950,950,250,250,950,950,275,250,950,950,275,250,950,950,275,250;
* HE842
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=270,870,840,240,210,870,840,240,210,870,210,870,210,870,840,240,210,870,210,870,210,870,210,870,210,870,210,870,210,870,840,240,210,870,210,870,210,870,840,240,210,870,840,240,210,870,210,870,210,6990;
* 360/1380 12/46
* 20;54;DEBUG;Pulses=50;Pulses(uSec)=1410,390,1350,360,1350,360,1380,360,1350,360,1380,360,1380,360,1380,360,1350,360,1350,360,1350,360,1380,360,1380,360,1380,360,1350,360,1380,360,1350,360,1350,360,390,1350,390,1350,390,1320,390,1320,420,1320,420,1320,390,6990;
\*********************************************************************************************/
#define KAKU_CodeLength 12 // number of data bits
#define KAKU_R 300/RAWSIGNAL_SAMPLE_RATE //360 // 300 // 370? 350 us
#define KAKU_PULSEMID 510/RAWSIGNAL_SAMPLE_RATE // (17) 510 = KAKU_R*2 not sufficient!
#ifdef PLUGIN_003
boolean Plugin_003(byte function, char *string) {
if (RawSignal.Number!=(KAKU_CodeLength*4)+2) return false; // conventionele KAKU bestaat altijd uit 12 data bits plus stop. Ongelijk, dan geen KAKU!
if (RawSignal.Pulses[0]==15) return true; // Home Easy, skip KAKU
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
if (RawSignal.Pulses[0]==19) return false; // No need to test, packet for plugin 19
// -------------------------------------------
int i,j;
boolean error=false;
unsigned long bitstream=0L; // to store a 12 bit code (ARC type)
unsigned long bitstream2=0L; // to store a 24 bit code (Extended ARC type)
byte tricount=0;
// -------------------------------------------
byte command=0; // ON/OFF/DIM/BRIGHT
byte group=0; // flags group command
byte housecode=0; // 0x40 + 1 to 16? (41-5a?)
byte unitcode=0; // 1 to 16
// -------------------------------------------
int PTLow=22; // Pulse Time - lowest found value (22 = a pulse duration of 550)
int PTHigh=22; // Pulse Time - highest found value
byte signaltype=0; // bit map: bit 0 = 0 bit 1 = f bit 2 = 0/1 (PT2262)
// meaning: byte value 3 = kaku (bit 0/f) 5=PT2262 7=tristate 0/1/f
byte devicetype=0; // 0=Kaku 5=Impuls 7=Perel
// -------------------------------------------
// -------------------------------------------
// ==========================================================================
j=KAKU_PULSEMID; // set MID value
j--;
if (RawSignal.Pulses[0]==33) { // If device is "Impuls"
RawSignal.Pulses[0]=0; // Unset Impuls conversion indicator
j=KAKU_R; // Set new (LOWER!) MID value
devicetype=5; // Indicate Impuls device
}
// -------------------------------------------
if (RawSignal.Pulses[49] > j) return false; // Last pulse has to be low! Otherwise we are not dealing with an ARC signal
// ==========================================================================
// TIMING MEASUREMENT, this will find the shortest and longest pulse within the RF packet
// ==========================================================================
for (i=2;i<RawSignal.Number;i++) { // skip first pulse as it is often affected by the start bit pulse duration
if(RawSignal.Pulses[i] < PTLow) { // shortest pulse?
PTLow=RawSignal.Pulses[i]; // new value
} else
if(RawSignal.Pulses[i] > PTHigh) { // longest pulse?
PTHigh=RawSignal.Pulses[i]; // new value
}
}
// -------------------------------------------
// TIMING MEASUREMENT to devicetype
if (devicetype != 5) { // Dont do the timing check for Impuls, it is already identified at this point
if( ((PTLow==7)||(PTLow==8)) && ((PTHigh ==30) || (PTHigh ==31) ) ) devicetype=4; // ELRO AB400
if( ((PTLow==9)||(PTLow==10)) && ((PTHigh==36)||(PTHigh==37)||((PTHigh >=40)&&(PTHigh <=42))) ) devicetype=1; // ELRO AB600
else
if( ((PTLow==10)||(PTLow == 11)) && ((PTHigh >=40)&&(PTHigh <=42)) ) devicetype=2; // Profile PR44N / Promax rsl366t
else
if( (PTLow==13) && ((PTHigh >=32)&&(PTHigh <=34)) ) devicetype=3; // Profile PR47N
else
if( ((PTLow >=11)&&(PTLow <=12)) && ((PTHigh >=31)&&(PTHigh <=37)) ) devicetype=4; // Sartano
else
if( ((PTLow==12)||(PTLow==13)) && ((PTHigh==45)||(PTHigh==46)) ) devicetype=4; // Philips SBC
else
if( (PTLow <=3) && ((PTHigh==22)||(PTHigh==23)) ) devicetype=5; // Philips SBC
//else
//if( (PTLow == 8 || PTLow == 9) && (PTHigh == 33 || PTHigh == 34) ) devicetype=7; // Perel st=0,dt=7
}
//sprintf(pbuffer, "ST=%d DT=%d %d/%d",signaltype,devicetype,PTLow,PTHigh);
//Serial.println( pbuffer );
// ==========================================================================
// Turn pulses into bits
// -------------------------------------------
for (i=0; i<KAKU_CodeLength; i++) {
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
bitstream=(bitstream >> 1); // bit '0'
bitstream2=(bitstream2 << 2); // bit '0' written as '00'
signaltype=signaltype|1; // bit '0' present in signal '0001'
} else
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
//!! untested !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
tricount++; // tri-state bit counter
if ((i==11) && (tricount==1)) { // only the last bit, "on/off command" is in tristate mode? then it must be EMW200
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10'
// DONT CHANGE signal type to tri-state to keep EMW200 in KAKU mode
} else {
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10'
signaltype=signaltype|2; // bit 'f' present in signal '0010'
}
} else
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) { // 0100
bitstream=(bitstream >> 1); // Short 0, Group command on 2nd bit. (NOT USED?!)
bitstream2=(bitstream2 << 2) | 3; // bit 'short' written as '11'
group=1;
} else
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
bitstream2=(bitstream2 << 2) | 1; // bit '1' written as '01'
signaltype=signaltype|4; // bit '1' present in signal '0100'
if (devicetype==5) { // in case of 'impuls remote' store
bitstream=(bitstream >> 1); // bit 1 (stored as 0) (IMPULS REMOTE)
} else {
if (i==11) { // last bit seems to cause trouble every now and then..?!
bitstream=(bitstream >> 1); // bit 1 (stored as 0) (IMPULS REMOTE)
} else {
devicetype=6;
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
}
}
} else {
// -------------------------------------------
// following are signal patches to fix bad transmission/receptions
// -------------------------------------------
if (i==0) { // are we dealing with a RTK/AB600 device? then the first bit is sometimes mistakenly seen as 1101
bitstream2=(bitstream2 << 2); // bit 0
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
bitstream=(bitstream >> 1); // 0, treat as 0101 eg 0 bit
} else {
error=true;
signaltype=signaltype|8;
}
} else {
error=true;
signaltype=signaltype|8;
}
} // bad signal
}
//==================================================================================
// Sort out devices based on signal type and timing measurements
// -------------------------------------------
//sprintf(pbuffer, "ST=%d DT=%d [%d]",signaltype,devicetype, error);
//Serial.println( pbuffer );
//Serial.println(bitstream,BIN);
//Serial.println(bitstream2,BIN);
// -------------------------------------------
// END OF TIMING MEASUREMENTS
// ==========================================================================
if (error==true) { // Error means that a pattern other than 0101/0110 was found
return false; // This usually means we are dealing with a semi-compatible device
} // that might have more states than used by ARC
if ((signaltype != 0x03) && (signaltype != 0x05) && (signaltype != 0x07)) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
//if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+500)<millis()) ) {
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+500)<millis()) || (((RepeatingTimer+1000)>millis())&&(SignalCRC != bitstream2)) ) {
// not seen the RF packet recently
if (signaltype == 0x07) {
if (((RepeatingTimer+1000)>millis())&&(SignalCRC != bitstream2)) {
return true; // skip tristate after normal arc
}
}
//Serial.print("KAKU PREV:");
//Serial.println(SignalHashPrevious);
if ((SignalHashPrevious==14) && ((RepeatingTimer+2000)>millis()) ) {
SignalHash=14;
return true; // SignalHash 14 = HomeEasy, eg. cant switch KAKU after HE for 2 seconds
}
if ((SignalHashPrevious==11) && ((RepeatingTimer+2000)>millis()) ) {
SignalHash=11;
return true; // SignalHash 11 = FA500, eg. cant switch KAKU after FA500 for 2 seconds
}
SignalCRC=bitstream2; // store RF packet identifier
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Determine signal type to sort out the various houdecode/unitcode/button bits and on/off command bits
//==================================================================================
if (signaltype != 0x07) {
if ((bitstream&0x700)!=0x600) { // valid but not real KAKU
devicetype=4;
}
// -------------------------------------------
if (devicetype == 4) { // Sartano
// ---------------------------------- // Sartano
housecode = ((bitstream) & 0x0000001FL); // .......11111b
unitcode = (((bitstream) & 0x000003E0L) >> 5); // ..1111100000b
housecode = ~housecode; // Sartano housecode is 5 bit ('A' - '`')
housecode &= 0x0000001FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = '`'
housecode += 0x41;
switch(unitcode) { // Translate unit code into button number 1 - 5
case 0x1E: // E=1110
unitcode = 1;
break;
case 0x1D: // D=1101
unitcode = 2;
break;
case 0x1B: // B=1011
unitcode = 3;
break;
case 0x17: // 7=0111
unitcode = 4;
break;
case 0x0F: // f=1111
unitcode = 5;
break;
default:
//Serial.print("Sartano:");
devicetype=3; // invalid for Sartano, fall back
break;
}
if (devicetype == 4) { // Sartano
if ( ((bitstream >> 10) & 0x03) == 2) {
command = 1; // On
} else if ( ((bitstream >> 10) & 0x03) == 1){
command = 0;// Off
}
}
} else
// -------------------------------------------
if (devicetype == 5) { // IMPULS
housecode = ((bitstream) & 0x0000000FL); // ........1111b
unitcode = (((bitstream) & 0x000003F0L) >> 4); // ..1111110000b
housecode = ~housecode; // Impuls housecode is 4 bit ('A' - 'P')
housecode &= 0x0000000FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = 'P'
housecode += 0x41;
unitcode = ~unitcode; // Impuls unitcode is 5 bit
unitcode &= 0x0000001FL; // Translate unitcode so that all jumpers off = '1' and all jumpers on = '64'
if ( ((bitstream >> 10) & 0x03) == 2) {
command = 0; // Off
} else
if ( ((bitstream >> 10) & 0x03) == 1){
command = 1;// On
}
} else
// -------------------------------------------
if (devicetype == 6) { // Blokker/SelectRemote
// ----------------------------------
if ( ((bitstream)&0xef1) != 0) return false; // Not a valid bitstream
housecode = ((bitstream) & 0x0000000EL); // Isolate housecode
housecode = housecode >> 1; // shift right 1 bit
housecode = (~housecode)&0x07; // invert bits
housecode += 0x41; // add 'A'
unitcode = 0;
if ( ((bitstream >> 8) & 0x01) == 1) {
command = 1; // On
} else {
command = 0;// Off
}
// ---------------------------------- // Sartano
} else
// -------------------------------------------
if (devicetype != 4) { // KAKU (and some compatibles for now)
// ----------------------------------
if ((bitstream&0x700)!=0x600) { // valid but not real KAKU
housecode=(((bitstream) &0x0f) +0x41);
unitcode=((((bitstream) &0xf0) >> 4)+1);
devicetype=1;
} else {
if ((bitstream&0x600)!=0x600) {
//Serial.println("Kaku 0/1 error");
return false; // use two static bits as checksum
}
//bitstream=(bitstream)&0xffe; // kill bit to ensure Perel works -> actually kills code wheel letter B
housecode=(((bitstream) &0x0f) +0x41);
unitcode=((((bitstream) &0xf0) >> 4)+1);
// ----------------------------------
}
if ( ((bitstream >> 11) & 0x01) == 1) {
command=1; // ON
} else {
command=0; // OFF
}
}
}
// ==========================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
if (signaltype == 0x03) { // '0011' bits indicate bits 0 and f are used in the signal
if (devicetype < 4) { // KAKU (and some compatibles for now)
Serial.print(F("Kaku;")); // Label
} else {
if (devicetype == 4) { // AB440R and Sartano
Serial.print(F("AB400D;")); // Label
} else
if (devicetype == 5) { // Impuls
Serial.print(F("Impuls;")); // Label
} else {
Serial.print(F("Sartano;")); // Others
}
}
} else
if (signaltype == 0x05) { // '0101' bits indicate bits 0 and 1 are used in the signal
if (devicetype == 5) { // KAKU (and some compatibles for now)
Serial.print(F("Impuls;")); // Label
} else {
Serial.print(F("PT2262;")); // Label
}
} else
if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state)
Serial.print(F("TriState;")); // Label
}
// ----------------------------------
if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state)
sprintf(pbuffer, "ID=%06lx;",((bitstream2)>>4)&0xffffff) ; // ID
Serial.print( pbuffer );
housecode=(bitstream2)&0x03;
unitcode=((((bitstream2)>>2)&0x03)^0x03)^housecode;
//command=((bitstream2)&1)^1; << ^1 reverses lidl light
command=((bitstream2)&3); // 00 01 10 0 1 f
if (command > 1) command=1; // 0 stays 0 (OFF), 1 and f become 1 (ON)
} else {
sprintf(pbuffer, "ID=%02x;", housecode); // ID
Serial.print( pbuffer );
}
sprintf(pbuffer, "SWITCH=%d;", unitcode);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if (group==1) Serial.print(F("ALL"));
if ( command == 1 ) {
Serial.print(F("ON;"));
} else {
Serial.print(F("OFF;"));
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_003
#ifdef PLUGIN_TX_003
void Arc_Send(unsigned long address); // sends 0 and float
void NArc_Send(unsigned long bitstream); // sends 0 and 1
void TriState_Send(unsigned long bitstream); // sends 0, 1 and float
boolean PluginTX_003(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0L;
byte command=0;
uint32_t housecode = 0;
uint32_t unitcode = 0;
byte Home=0; // KAKU home A..P
byte Address=0; // KAKU Address 1..16
byte c=0;
byte x=0;
// ==========================================================================
//10;Kaku;00004d;1;OFF;
//10;Kaku;00004f;e;ON;
//10;Kaku;000050;10;ON;
//10;Kaku;000049;b;ON;
//012345678901234567890
// ==========================================================================
if (strncasecmp(InputBuffer_Serial+3,"KAKU;",5) == 0) { // KAKU Command eg. Kaku;A1;On
if (InputBuffer_Serial[14] != ';') return false;
x=15; // character pointer
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value
InputBuffer_Serial[14]=0x00; // Get home from hexadecimal value
Home=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0
if (Home < 0x51) // take care of upper/lower case
Home=Home - 'A';
else
if (Home < 0x71) // take care of upper/lower case
Home=Home - 'a';
else {
return false; // invalid value
}
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
if(c>='a' && c<='f'){Address=Address+(c-'a'+10);} // 31?
if(c>='A' && c<='F'){Address=Address+(c-'A'+10);} // 51?
}
//if (Address==0) { // group command is given: 0=all
// command=2; // Set 2nd bit for group.
// bitstream=Home;
//} else {
// bitstream= Home | ((Address-1)<<4);
//}
bitstream= Home | ((Address-1)<<4);
command |= str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
bitstream = bitstream | (0x600 | ((command & 1) << 11)); // create the bitstream
//Serial.println(bitstream);
Arc_Send(bitstream);
success=true;
// --------------- END KAKU SEND ------------
} else
// ==========================================================================
//10;AB400D;00004d;1;OFF;
//012345678901234567890
// ==========================================================================
if (strncasecmp(InputBuffer_Serial+3,"AB400D;",7) == 0) { // KAKU Command eg. Kaku;A1;On
if (InputBuffer_Serial[16] != ';') return false;
x=17; // character pointer
InputBuffer_Serial[12]=0x30;
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
if (Home < 0x61) // take care of upper/lower case
Home=Home - 'A';
else
if (Home < 0x81) // take care of upper/lower case
Home=Home - 'a';
else {
return false; // invalid value
}
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
}
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
housecode = ~Home;
housecode &= 0x0000001FL;
unitcode=Address;
if ((unitcode >= 1) && (unitcode <= 5) ) {
bitstream = housecode & 0x0000001FL;
if (unitcode == 1) bitstream |= 0x000003C0L;
else if (unitcode == 2) bitstream |= 0x000003A0L;
else if (unitcode == 3) bitstream |= 0x00000360L;
else if (unitcode == 4) bitstream |= 0x000002E0L;
else if (unitcode == 5) bitstream |= 0x000001E0L;
if (command) bitstream |= 0x00000800L;
else bitstream |= 0x00000400L;
}
//Serial.println(bitstream);
Arc_Send(bitstream);
success=true;
} else
// --------------- END SARTANO SEND ------------
// ==========================================================================
//10;PT2262;000041;1;OFF;
//012345678901234567890
// ==========================================================================
if (strncasecmp(InputBuffer_Serial+3,"PT2262;",7) == 0) { // KAKU Command eg. Kaku;A1;On
if (InputBuffer_Serial[16] != ';') return false;
x=17; // character pointer
InputBuffer_Serial[12]=0x30;
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
if (Home < 0x61) // take care of upper/lower case
Home=Home - 'A';
else
if (Home < 0x81) // take care of upper/lower case
Home=Home - 'a';
else {
return false; // invalid value
}
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
}
// reconstruct bitstream reversed order so that most right bit can be send first
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
housecode = ~Home;
housecode &= 0x00000007L;
housecode=(housecode)<<1;
if (command) bitstream |= 0x00000100L;
NArc_Send(bitstream); // send 24 bits tristate signal (0/1/f)
success=true;
} else
// --------------- END Select Remote SEND ------------
// ==========================================================================
//10;TriState;00004d;1;OFF;
//10;TriState;08000a;2;OFF; 20;1B;TriState;ID=08000a;SWITCH=2;CMD=OFF;
//10;TriState;0a6980;2;OFF;
//01234567890123456789012
// ==========================================================================
if (strncasecmp(InputBuffer_Serial+3,"TriState;",9) == 0) { // KAKU Command eg. Kaku;A1;On
if (InputBuffer_Serial[18] != ';') return false;
x=19; // character pointer
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value
InputBuffer_Serial[18]=0x00; // Get home from hexadecimal value
bitstream=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0
bitstream=(bitstream<<4);
// 11^00^01=10 11^10^11=01 11^11^00=00
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 0/1/2
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
}
Address=(Address)&0x03; // only use 3 bits
command = str2cmd(InputBuffer_Serial+x); // ON/OFF command
if (command==VALUE_ON) { // on
if (Address==0x0) bitstream |= 0x0000000bL; // 0011
if (Address==0x1) bitstream |= 0x0000000cL; // 1011
if (Address==0x2) bitstream |= 0x00000001L; // 0001
} else { // off
if (Address==0x0) bitstream |= 0x0000000cL; // 1100
if (Address==0x1) bitstream |= 0x0000000eL; // 1110
if (Address==0x2) bitstream |= 0x00000004L; // 0100
}
TriState_Send(bitstream);
success=true;
} else
// --------------- END TRISTATE SEND ------------
// ==========================================================================
//10;Impuls;00004d;1;OFF;
//012345678901234567890
// ==========================================================================
if (strncasecmp(InputBuffer_Serial+3,"Impuls;",7) == 0) { // KAKU Command eg. Kaku;A1;On
if (InputBuffer_Serial[16] != ';') return false;
x=17; // character pointer
InputBuffer_Serial[12]=0x30;
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
if (Home < 0x61) // take care of upper/lower case
Home=Home - 'A';
else
if (Home < 0x81) // take care of upper/lower case
Home=Home - 'a';
else {
return false; // invalid value
}
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
}
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
housecode = ~Home;
housecode &= 0x0000001FL;
unitcode=Address;
if ((unitcode >= 1) && (unitcode <= 5) ) {
bitstream = housecode & 0x0000001FL;
if (unitcode == 1) bitstream |= 0x000003C0L;
else if (unitcode == 2) bitstream |= 0x000003A0L;
else if (unitcode == 3) bitstream |= 0x00000360L;
else if (unitcode == 4) bitstream |= 0x000002E0L;
else if (unitcode == 5) bitstream |= 0x000001E0L;
if (command) bitstream |= 0x00000800L;
else bitstream |= 0x00000400L;
}
TriState_Send(bitstream);
success=true;
}
return success;
}
//#define KAKU_T 390 //420 // 370 // 370? 350 us
//#define Sartano_T 300 //360 // 300 // 300 uS
void Arc_Send(unsigned long bitstream) {
int fpulse = 360; // Pulse width in microseconds
int fretrans = 8; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x00000001;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff = bitstream;
// Send command
for (int i = 0; i < 12; i++) { // Arc packet is 12 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most right bit
fsendbuff = (fsendbuff >> 1); // Shift right
// PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
} else { // Write float
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
}
// Send sync bit
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 31);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
void NArc_Send(unsigned long bitstream) {
int fpulse = 190; // Pulse width in microseconds
int fretrans = 7; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x00000001;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff = bitstream;
// Send command
for (int i = 0; i < 12; i++) { // Arc packet is 12 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most right bit
fsendbuff = (fsendbuff >> 1); // Shift right
// PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
}
// Send sync bit
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 31);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
void TriState_Send(unsigned long bitstream) {
int fpulse = 360; // Pulse width in microseconds
int fretrans = 8; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x00000003;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
// reverse data bits (2 by 2)
for (unsigned short i=0; i<12; i++) { // reverse data bits (12 times 2 bits = 24 bits in total)
fsendbuff<<=2;
fsendbuff|=(bitstream & B11);
bitstream>>=2;
}
bitstream=fsendbuff; // store result
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff = bitstream;
// Send command
for (int i = 0; i < 12; i++) { // 12 times 2 bits = 24 bits in total
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most right 2 bits
fsendbuff = (fsendbuff >> 2); // Shift right
// data can be 0, 1 or float.
if (fdatabit == 0) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
} else
if (fdatabit == 1) { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write float
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
}
// Send sync bit
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 31);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
#endif //PLUGIN_TX_003

341
Plugins/Plugin_004.c Normal file
View File

@@ -0,0 +1,341 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-04: NewKAKU ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of receiving from and transmitting to "Klik-Aan-Klik-Uit" devices
* working according to the learning code system. This protocol is also used by the Home Easy devices.
* It includes direct DIM functionality.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Pulse (T) is 275us PDM
* 0 = T,T,T,4T, 1 = T,4T,T,T, dim = T,T,T,T op bit 28
*
* From: Wieltje @ http://www.circuitsonline.net/forum/view/message/1181410#1181410
* _ _
* '0': | |_| |____ (T,T,T,3T)
* _ _
* '1': | |____| |_ (T,3T,T,T)
* _ _
* dim: | |_| |_ (T,T,T,T)
*
* T = korte periode = 275 µs (of 375, werkt ook)
* lange periode = 3 of 4*T (werkt ook allebei)
*
* | 00100011110100100010011010 | 0 | 1 | 0000 |
* | ID# | All | State | unit# |
*
* NewKAKU supports:
* on/off ---- 000x Off/On
* all on/off ---- 001x AllOff/AllOn
* dim absolute xxxx 0110 Dim16 // dim on bit 27 + 4 extra bits for dim level
*
* NewKAKU bitstream= (First sent) AA AAAAAAAA AAAAAAAA AAAAAAAACCUUUU(LLLL) -> A=KAKU_address, C=command, U=KAKU-Unit, L=extra dimlevel bits (optional)
*
* Sample RF packet:
* 20;B8;NewKaku;ID=00c142;SWITCH=1;CMD=OFF;
* 20;B9;DEBUG;Pulses=132;Pulses(uSec)=200,2550,150,200,125,1200,150,200,150,1200,125,1200,150,225,125,1200,125,225,125,200,150,1200,150,200,150,1200,150,1200,125,200,125,200,125,1225,125,1200,125,225,150,200,150,1200,150,1200,150,200,150,1200,150,225,125,200,150,1200,125,200,150,1200,125,200,150,1200,150,200,125,1225,150,200,125,1200,150,1200,125,225,125,200,125,1200,150,1200,125,225,125,200,125,1225,125,200,125,1225,125,200,125,1200,125,200,150,1225,125,1200,150,200,125,200,125,1200,125,200,150,1200,125,200,125,1200,150,200,125,1200,125,200,125,1200,150,200,125,1200,150,200,150,1200,125;
* 20;06;DEBUG;Pulses=132;Pulses(uSec)=175,2575,150,200,150,1200,150,200,150,1200,150,1200,150,200,125,1200,150,200,125,200,150,1200,125,200,150,1200,150,1200,150,200,150,200,150,1225,150,1200,125,225,150,200,125,1200,150,1200,150,200,150,1200,150,200,150,200,125,1225,125,200,150,1200,125,200,150,1200,125,200,150,1200,150,200,150,1200,150,1200,125,200,150,200,125,1200,150,1200,125,225,150,200,125,1200,150,200,150,1200,150,200,150,1200,150,200,150,1225,125,1200,150,200,125,200,150,1200,150,200,125,1200,150,200,150,1200,150,200,150,1200,150,200,125,1225,125,200,125,1200,150,200,150,1200,150
\*********************************************************************************************/
#define NewKAKU_RawSignalLength 132 // regular KAKU packet length
#define NewKAKUdim_RawSignalLength 148 // KAKU packet length including DIM bits
#define NewKAKU_mT 650/RAWSIGNAL_SAMPLE_RATE // us, approx. in between 1T and 4T
#ifdef PLUGIN_004
boolean Plugin_004(byte function, char *string) {
// nieuwe KAKU bestaat altijd uit start bit + 32 bits + evt 4 dim bits. Ongelijk, dan geen NewKAKU
if ( (RawSignal.Number != NewKAKU_RawSignalLength) && (RawSignal.Number != NewKAKUdim_RawSignalLength) ) return false;
if (RawSignal.Pulses[0]==15) return true; // Home Easy, skip KAKU
boolean Bit;
int i;
//int P0,P1,P2,P3;
byte P0,P1,P2,P3;
byte dim=0;
byte dimbitpresent=0;
unsigned long bitstream=0L;
// RawSignal.Pulses[1] startbit with duration of 1T => ignore
// RawSignal.Pulses[2] long space after startbit with duration of 8T => ignore
i=3; // RawSignal.Pulses[3] is first pulse of a T,xT,T,xT combination
do {
P0=RawSignal.Pulses[i] ; // * RawSignal.Multiply;
P1=RawSignal.Pulses[i+1]; // * RawSignal.Multiply;
P2=RawSignal.Pulses[i+2]; // * RawSignal.Multiply;
P3=RawSignal.Pulses[i+3]; // * RawSignal.Multiply;
if (P0<NewKAKU_mT && P1<NewKAKU_mT && P2<NewKAKU_mT && P3>NewKAKU_mT) {
Bit=0; // T,T,T,4T
} else
if (P0<NewKAKU_mT && P1>NewKAKU_mT && P2<NewKAKU_mT && P3<NewKAKU_mT) {
Bit=1; // T,4T,T,T
} else
if (P0<NewKAKU_mT && P1<NewKAKU_mT && P2<NewKAKU_mT && P3<NewKAKU_mT) { // T,T,T,T should be on i=111 (bit 28)
dimbitpresent=1;
if(RawSignal.Number!=NewKAKUdim_RawSignalLength) { // dim set but no dim bits present => invalid signal
return false;
}
//if (i != 111) return false; // not the right location for the dim bit indicator
} else {
//Serial.println("Unknown pattern");
return false; // Other pulse patterns are invalid within the AC KAKU signal.
}
if(i<130) { // all bits that belong to the 32-bit pulse sequence (32bits * 4 positions per bit + pulse/space for startbit)
bitstream=(bitstream<<1) | Bit;
} else { // remaining 4 bits that set the dim level
dim=(dim<<1) | Bit;
}
i+=4; // Next 4 pulses
} while(i<RawSignal.Number-2); //-2 to exclude the stopbit space/pulse
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || ((RepeatingTimer+700)<millis() ) || SignalCRC != bitstream ) { // 1000
// not seen the RF packet recently
//Serial.print("NKAKU PREV:");
//Serial.println(SignalHashPrevious);
//if ((SignalHashPrevious==14) && ((RepeatingTimer+2000)>millis()) ) {
// SignalHash=14;
// return true; // SignalHash 14 = HomeEasy, eg. cant switch KAKU after HE for 2 seconds
//}
if ((SignalHashPrevious==11) && ((RepeatingTimer+2000)>millis()) ) {
SignalHash=11;
return true; // SignalHash 11 = FA500, eg. cant switch KAKU after FA500 for 2 seconds
}
SignalCRC=bitstream;
} else {
// already seen the RF packet recently
//Serial.println("Skip");
return true;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("NewKaku;")); // Label
sprintf(pbuffer, "ID=%08lx;",((bitstream) >> 6) ); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%x;", ((bitstream)&0x0f)+1 );
Serial.print( pbuffer );
Serial.print(F("CMD="));
int command = (bitstream >> 4) & 0x03;
if (command > 1) command ++;
if (i>140 && dimbitpresent==1) { // Command and Dim part
sprintf(pbuffer, "SET_LEVEL=%d;", dim );
Serial.print( pbuffer );
} else {
if ( command == 0 ) Serial.print(F("OFF;"));
if ( command == 1 ) Serial.print(F("ON;"));
if ( command == 3 ) Serial.print(F("ALLOFF;"));
if ( command == 4 ) Serial.print(F("ALLON;"));
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // Plugin_004
#ifdef PLUGIN_TX_004
void AC_Send(unsigned long data, byte cmd);
boolean PluginTX_004(byte function, char *string) {
boolean success=false;
//10;NewKaku;123456;3;ON; // ON, OFF, ALLON, ALLOFF, ALL 99, 99
//10;NewKaku;0cac142;2;ON;
//10;NewKaku;050515;f;OFF;
//10;NewKaku;2100fed;1;ON;
//10;NewKaku;000001;10;ON;
//10;NewKaku;306070b;f;ON;
//10;NewKaku;306070b;10;ON;
//01234567890123456789012
if (strncasecmp(InputBuffer_Serial+3,"NEWKAKU;",8) == 0) {
byte x=18; // pointer to the switch number
if (InputBuffer_Serial[17] != ';') {
if (InputBuffer_Serial[18] != ';') {
return false;
} else {
x=19;
}
}
unsigned long bitstream=0L;
unsigned long tempaddress=0L;
byte cmd=0;
byte c=0;
byte Address=0; // Address 1..16
// -----
InputBuffer_Serial[ 9]=0x30; // Get NEWKAKU/AC main address part from hexadecimal value
InputBuffer_Serial[10]=0x78;
InputBuffer_Serial[x-1]=0x00;
tempaddress=str2int(InputBuffer_Serial+9);
// -----
//while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16
// if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
//}
InputBuffer_Serial[x-2]=0x30; // Get unit number from hexadecimal value
InputBuffer_Serial[x-1]=0x78; // x points to the first character of the unit number
if (InputBuffer_Serial[x+1] == ';') {
InputBuffer_Serial[x+1]=0x00;
cmd=2;
} else {
if (InputBuffer_Serial[x+2] == ';') {
InputBuffer_Serial[x+2]=0x00;
cmd=3;
} else {
return false;
}
}
Address=str2int(InputBuffer_Serial+(x-2)); // NewKAKU unit number
if (Address > 16) return false; // invalid address
Address--; // 1 to 16 -> 0 to 15 (transmitted value is 1 less than shown values)
x=x+cmd; // point to on/off/dim command part
// -----
tempaddress=(tempaddress <<6) + Address; // Complete transmitted address
// -----
cmd=str2cmd(InputBuffer_Serial+x); // Get ON/OFF etc. command
if (cmd == false) { // Not a valid command received? ON/OFF/ALLON/ALLOFF
cmd=str2int(InputBuffer_Serial+x); // get DIM value
}
// --------------- Prepare bitstream ------------
bitstream=tempaddress & 0xFFFFFFCF; // adres geheel over nemen behalve de twee bits 5 en 6 die het schakel commando bevatten.
// Dimming of groups is also possible but not supported yet!
// when level=0 is it better to transmit just the off command ?
if (cmd == VALUE_ON || cmd == VALUE_OFF) {
bitstream|=(cmd == VALUE_ON)<<4; // bit-5 is the on/off command in the KAKU signal
cmd=0xff;
} else
if (cmd == VALUE_ALLON || cmd == VALUE_ALLOFF) {
bitstream|= B1 << 5; // bit 5 is the group indicator
bitstream|=(cmd == VALUE_ALLON)<<4; // bit-4 is the on/off indicator
cmd=0xff;
}
// bitstream now contains the AC/NewKAKU-bits that have to be transmitted
// --------------- NEWKAKU SEND ------------
AC_Send(bitstream, cmd);
success=true;
}
// --------------------------------------
return success;
}
void AC_Send(unsigned long data, byte cmd) {
int fpulse = 260; // Pulse width in microseconds
int fretrans = 10; // Number of code retransmissions
unsigned long bitstream = 0L;
byte command;
// prepare data to send
for (unsigned short i=0; i<32; i++) { // reverse data bits
bitstream<<=1;
bitstream|=(data & B1);
data>>=1;
}
if (cmd !=0xff) { // reverse dim bits
for (unsigned short i=0; i<4; i++) {
command<<=1;
command|=(cmd & B1);
cmd>>=1;
}
}
// Prepare transmit
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
// send bits
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
data=bitstream;
if (cmd !=0xff) cmd=command;
digitalWrite(PIN_RF_TX_DATA, HIGH);
//delayMicroseconds(fpulse); //335
delayMicroseconds(335);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //260*10=2600
for (unsigned short i=0; i<32; i++) {
if (i==27 && cmd !=0xff) { // DIM command, send special DIM sequence TTTT replacing on/off bit
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
} else
switch (data & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*5); // 335*3=1005 260*5=1300 260*4=1040
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*5);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
break;
}
//Next bit
data>>=1;
}
// send dim bits when needed
if (cmd != 0xff) { // need to send DIM command bits
for (unsigned short i=0; i<4; i++) { // 4 bits
switch (cmd & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*5); // 335*3=1005 260*5=1300
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*5);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
break;
}
//Next bit
cmd>>=1;
}
}
//Send termination/synchronisation-signal. Total length: 32 periods
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*40); //31*335=10385 40*260=10400
}
// End transmit
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
#endif // Plugin_TX_004

204
Plugins/Plugin_005.c Normal file
View File

@@ -0,0 +1,204 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-03: Intertek Eurodomest 972080 ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the Intertek Eurodomest 972080 protocol.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical information:
*
* 0111 00011011 00011111 000 0
* AAAA AAAAAAAA AAAAAAAA BBB C
* 0000 00000011 10101010 101 1
* 0000 00000011 10101010 111 0
*
* 0011 01101001 01101011 000 0 Eurodomest 1 on
* 0011 01101001 01101011 000 1 Eurodomest 1 off
* 0011 01101001 01101011 001 0 ED 2 on
* 0011 01101001 01101011 001 1 ED 2 off
* 0011 01101001 01101011 010 0 3 on
* 0011 01101001 01101011 010 1 3 off
* 0011 01101001 01101011 100 0 4 on
* 0011 01101001 01101011 100 1 4 off
* 0011 01101001 01101011 110 1 all on
* 0011 01101001 01101011 111 0 all off
*
*
* A = ID (20 bits)
* B = UnitCode (3 bits)
* C = switch code (ON/OFF) (1 bit)
*
* 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;
* 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;
\*********************************************************************************************/
#define EURODOMEST_PulseLength 50
#define EURODOMEST_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
#define EURODOMEST_PULSEMIN 100/RAWSIGNAL_SAMPLE_RATE
#define EURODOMEST_PULSEMAX 900/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_005
boolean Plugin_005(byte function, char *string) {
if (RawSignal.Number != EURODOMEST_PulseLength) return false;
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
unsigned long bitstream=0;
byte unitcode=0;
byte command=0;
unsigned long address=0;
// ==========================================================================
if(RawSignal.Pulses[49] > EURODOMEST_PULSEMID) return false; // last pulse needs to be short, otherwise no Eurodomest protocol
// get all 24 bits
for(int x=2;x < EURODOMEST_PulseLength;x+=2) {
if(RawSignal.Pulses[x] > EURODOMEST_PULSEMID) { // long pulse
if (RawSignal.Pulses[x-1] > EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission
if(RawSignal.Pulses[x] > EURODOMEST_PULSEMAX) return false; // make sure the long pulse is within range
bitstream = (bitstream << 1) | 0x1;
} else { // short pulse
if (RawSignal.Pulses[x] < EURODOMEST_PULSEMIN) return false; // pulse too short to be Eurodomest
if (RawSignal.Pulses[x-1] < EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission
bitstream = (bitstream << 1);
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
// not seen the RF packet recently
if (bitstream==0) return false; // no bits detected?
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// perform sanity checks to prevent false positives
//==================================================================================
address=bitstream;
address=(address >> 4) &0xfffff;
if (address==0) return false; // Address would never be 0
if (address==0xfffff) return false; // Address would never be FFFFF
// ----------------------------------
unitcode=(( bitstream >> 1)& 0x7);
command=((bitstream) & 0x01);
if (unitcode == 3) return false; // invalid button code?
if (unitcode == 4) unitcode--;
// if (unitcode == 5) return false; // Note: unitcode 5 is present on the PCB and working but not used on any remotes.
if (unitcode > 7) return false; // invalid button code?
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Eurodomest;")); // Label
sprintf(pbuffer, "ID=%06lx;",(address)&0xffffff) ; // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", unitcode); // ID
Serial.print( pbuffer );
Serial.print(F("CMD="));
if ( unitcode > 4) {
Serial.print(F("ALL"));
if ( command == 0) {
Serial.print(F("OFF;"));
} else {
Serial.print(F("ON;"));
}
} else {
if ( command == 1) {
Serial.print(F("OFF;"));
} else {
Serial.print(F("ON;"));
}
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_005
#ifdef PLUGIN_TX_005
void Eurodomest_Send(unsigned long address);
boolean PluginTX_005(byte function, char *string) {
//10;EURODOMEST;03696b;0;ON;
//012345678901234567890123456
boolean success=false;
if (strncasecmp(InputBuffer_Serial+3,"EURODOMEST;",11) == 0) { // KAKU Command eg.
unsigned long bitstream=0L;
if (InputBuffer_Serial[20] != ';') return success;
if (InputBuffer_Serial[22] != ';') return success;
InputBuffer_Serial[12]=0x30;
InputBuffer_Serial[13]=0x78;
InputBuffer_Serial[20]=0x00;
bitstream=str2int(InputBuffer_Serial+12);// Address
InputBuffer_Serial[22]=0x00;
byte temp=str2int(InputBuffer_Serial+21);// Button number
bitstream=(bitstream) << 4;
if (temp == 1) bitstream=bitstream+0x02; // 0010
if (temp == 2) bitstream=bitstream+0x04; // 0100
if (temp == 3) bitstream=bitstream+0x08; // 1000
if (temp == 6) bitstream=bitstream+0x0d; // 1101
if (temp == 7) bitstream=bitstream+0x0f; // 1111
if (temp > 7) {
return success;
}
byte command=0;
command = str2cmd(InputBuffer_Serial+23);
if (command == VALUE_OFF) {
bitstream=bitstream|1;
}
Eurodomest_Send(bitstream); // the full bitstream to send
success=true;
}
return success;
}
void Eurodomest_Send(unsigned long address) {
int fpulse = 296; // Pulse witdh in microseconds
int fretrans = 7; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x800000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff=address;
// Send command
for (int i = 0; i < 24; i++) { // Eurodomest packet is 24 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
}
}
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 32);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
#endif //PLUGIN_TX_005

287
Plugins/Plugin_006.c Normal file
View File

@@ -0,0 +1,287 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-006 Blyss & Avidsen ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of receiving of the Blyss protocol
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* RF packets contain 106 pulses, 52 bits
*
* BLYSS Message Format:
* AAAAAAAA BBBBCCCC CCCCCCCC CCCCDDDD | EEEEFFFF FFFFGGGG GGGG
*
* A = Preamble, always 0xFE (0x32 in case of Avidsen)
* B = Global Channel (A=0,B=1,C=2,D=3)
* C = Address
* D = sub channel (channel 1=8, 2=4, 3=2, 4=1, 5=3) all channels = 0
* E = Light Status
* F = Rolling Code (0x98 -> 0xDA -> 0x1E -> 0xE6 -> 0x67)
* G = Time Stamp (random value?)
*
* Details https://skyduino.wordpress.com/2012/07/19/hack-partie-2-reverse-engineering-des-interrupteurs-domotique-blyss/
* https://barbudor.wiki.zoho.com/Système-domotique-Blyss-de-Castorama.html
*
* BlyssSend address,switch,cmd; => (16 bits,8 bits,on/off/allon/alloff)
* 20;0B;DEBUG;Pulses=106;Pulses(uSec)=2160,450,570,420,600,420,600,450,570,420,600,420,600,450,570,810,210,870,150,840,180,840,180,840,180,420,600,420,600,420,600,450,570,420,600,420,600,420,600,420,600,420,600,840,180,840,210,450,570,450,600,810,180,840,180,840,180,420,600,810,210,840,180,810,210,810,210,870,180,810,210,450,570,450,570,840,180,840,210,450,570,420,600,840,180,810,210,840,180,840,210,840,180,840,180,810,210,840,210,420,600,810,210,420,600,6990;
* 20;0C;Blyss;ID=ff98;SWITCH=A1;CMD=OFF;
\*********************************************************************************************/
#define BLYSS_PULSECOUNT 106
#define BLYSS_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_006
boolean Plugin_006(byte function, char *string) {
if (RawSignal.Number != BLYSS_PULSECOUNT) return false;
unsigned long bitstream=0L;
unsigned long bitstream1=0L;
byte bitcounter=0;
byte checksum=0;
int type=0;
//==================================================================================
// get bits
for(byte x=2;x < BLYSS_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x] > BLYSS_PULSEMID) {
if (bitcounter < 32) {
bitstream = (bitstream << 1);
} else {
bitstream1 = (bitstream1 << 1);
}
bitcounter++;
} else {
if (bitcounter < 32) {
bitstream = (bitstream << 1) | 0x1;
} else {
bitstream1 = (bitstream1 << 1) | 0x1;
}
bitcounter++;
}
}
//==================================================================================
// all bits received, make sure checksum is okay
//==================================================================================
checksum=((bitstream) >> 24); // test preamble
if ((checksum != 0xFE) && (checksum != 0x32) ) return false; // must be 0xFE/32
if (checksum == 0x32) type=1;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
// not seen the RF packet recently
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
byte status=((bitstream1) >> 16) &0x0f;
if (status > 3) return false;
byte channel=((bitstream) >> 20) &0x0f;
unsigned int address=((bitstream) >> 4) &0xffff;
byte subchan=(bitstream) &0xf;
channel=channel+0x41;
if (subchan==8) {
subchan=1;
} else
if (subchan==4) {
subchan=2;
} else
if (subchan==2) {
subchan=3;
} else
if (subchan==1) {
subchan=4;
} else
if (subchan==3) {
subchan=5;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
Serial.print( pbuffer );
// ----------------------------------
if (type == 0) {
Serial.print(F("Blyss;")); // Label
} else {
Serial.print(F("Avidsen;")); // Label
}
sprintf(pbuffer, "ID=%04x;", address); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
Serial.print( pbuffer );
Serial.print(F("CMD=")); // command
if (status==0) Serial.print(F("ON;"));
if (status==1) Serial.print(F("OFF;"));
if (status==2) Serial.print(F("ALLON;"));
if (status==3) Serial.print(F("ALLOFF;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_006
#ifdef PLUGIN_TX_006
void Blyss_Send(unsigned long address, byte devtype);
boolean PluginTX_006(byte function, char *string) {
boolean success=false;
//10;Avidsen;00ff98;A1;OFF;
//012345678901234567890123456
//10;Blyss;00ff98;A1;OFF;
//012345678901234567890123456
int offset=0;
if (strncasecmp(InputBuffer_Serial+3,"AVIDSEN;",8) == 0) { // Blyss Command eg.
offset=2;
}
if ((strncasecmp(InputBuffer_Serial+3,"BLYSS;",6) == 0) || (offset==2)) { // Blyss Command eg.
unsigned long Bitstream = 0L;
if (InputBuffer_Serial[15+offset] != ';') return success; // check
if (InputBuffer_Serial[18+offset] != ';') return success; // check
unsigned long Home=0; // Blyss channel A..P
byte Address=0; // Blyss subchannel 1..5
byte c;
byte subchan=0; // subchannel
InputBuffer_Serial[7+offset]=0x30;
InputBuffer_Serial[8+offset]=0x78;
InputBuffer_Serial[15+offset]=0;
Bitstream=str2int(InputBuffer_Serial+7+offset); // get address
c=tolower(InputBuffer_Serial[16+offset]); // A..P
if(c>='a' && c<='p'){Home=c-'a';}
c=tolower(InputBuffer_Serial[17+offset]); // 1..5
if(c>='1' && c<='5'){Address=Address+c-'0';}
if (Address==1) subchan=0x80;
if (Address==2) subchan=0x40;
if (Address==3) subchan=0x20;
if (Address==4) subchan=0x10;
if (Address==5) subchan=0x30;
Home = Home << 24;
Bitstream=(Bitstream) << 8;
Bitstream=Bitstream+subchan;
Bitstream=Bitstream+Home;
c = str2cmd(InputBuffer_Serial+19+offset); // ALL ON/OFF command
if (c == VALUE_OFF) {
Bitstream=Bitstream|1;
} else {
if (c == VALUE_ALLOFF) {
Bitstream=Bitstream|3;
} else
if (c == VALUE_ALLON) {
Bitstream=Bitstream|2;
}
}
Blyss_Send(Bitstream, offset); // Bitstream contains the middle part of the bitstream to send
success=true;
}
return success;
}
void Blyss_Send(unsigned long address, byte devtype) {
int fpulse = 400; // Pulse witdh in microseconds
int fretrans = 8; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x800000;
uint32_t fsendbuff;
unsigned char RollingCode[] = { 0x98, 0xDA, 0x1E, 0xE6, 0x67, 0x98};
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Turn on the RF transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
byte temp=(millis() &0xff); // used for the timestamp at the end of the RF packet
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
// send SYNC 1P low, 6P high
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 6);
// end send SYNC
// --------------
// Send preamble (0xfe) - 8 bits
if (devtype == 0) {
fsendbuff=0x32;
} else {
fsendbuff=0xfe;
}
fdatamask=0x80;
for (int i = 0; i < 8; i++) { // Preamble
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 2);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 2);
}
}
// --------------
fsendbuff=address;
fdatamask=0x8000000;
// Send command (channel/address/status) - 28 bits
for (int i = 0; i < 28; i++) {
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 2);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 2);
}
}
// --------------
// Send rolling code & timestamp - 16 bits
fsendbuff=RollingCode[nRepeat];
fsendbuff=(fsendbuff<<8)+temp;
//fsendbuff=0x9800 + temp;
fdatamask=0x8000;
for (int i = 0; i < 16; i++) {
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 2);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 2);
}
}
// --------------
digitalWrite(PIN_RF_TX_DATA, LOW);
//delayMicroseconds(fpulse * 18); // delay between RF retransmits
delay(24); // delay 23.8 ms
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // turn off the RF transmitter
digitalWrite(PIN_RF_RX_VCC,HIGH); // power on the RF receiver
RFLinkHW();
}
#endif // PLUGIN_TX_006

320
Plugins/Plugin_007.c Normal file
View File

@@ -0,0 +1,320 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-007 CONRAD RSL2 ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of receiving of the Conrad RSL2 protocol
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* RF packets contain 66 pulses, 32 bits
*
* Conrad RSL2 Message Format:
* AABBCDDD EEEEEEEE EEEEEEEE EEEEEEEE
*
* A = always 10
* B = Button code
* C = on/off command (inverted for some buttons/groups)
* D = group code
* E = 24 bit address
*
* Details: http://www.mikrocontroller.net/topic/252895
*
* ConradSend address,switch,cmd; => (16 bits,8 bits,on/off/allon/alloff)
20;5B;DEBUG;Pulses=66;Pulses(uSec)=400,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,1200,350,350,1225,350,1200,1200,350,350,1200,350,1200,1200,350,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350;
400,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,350,1200,350,1200,350,1200,
350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,1200,350,350,1225,350,1200,1200,350,
350,1200,350,1200,1200,350,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,
350,1200,350,1200,350;
20;3D;DEBUG;Pulses=68;Pulses(uSec)=600,6450,1290,330,390,1260,390,1260,360,1260,360,1260,390,1260,390,1260,1290,360,1260,360,1290,360,1290,330,1290,360,1260,360,1260,360,1290,330,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,1290,360,1260,360,360,1260,390,1260,360,1260,360,1260,360,1260,390,1260,1290,360,1290,360,1260,360,390,6990;
20;3E;DEBUG;Pulses=68;Pulses(uSec)=720,6450,1290,330,390,1260,360,1260,360,1260,390,1260,390,1260,360,1260,1260,360,1290,330,1290,330,1290,360,1260,360,1260,360,1290,330,1290,360,1290,360,360,1260,360,1260,390,1260,360,1260,360,1260,1260,360,1290,330,390,1260,360,1260,360,1260,360,1260,390,1260,390,1260,1260,360,1260,360,1290,330,390,6990;
20;3F;DEBUG;Pulses=68;Pulses(uSec)=630,6450,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,360,1260,1290,330,1290,330,1290,360,1260,360,1290,330,1290,330,1290,360,1260,360,1260,360,390,1260,390,1260,360,1260,360,1260,360,1260,1290,330,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,360,1260,1290,330,1290,330,1290,360,360,6990;
\*********************************************************************************************/
#define CONRADRSL2_PULSECOUNT 66
#define CONRADRSL2_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_007
boolean Plugin_007(byte function, char *string){
if ((RawSignal.Number != CONRADRSL2_PULSECOUNT) && (RawSignal.Number != CONRADRSL2_PULSECOUNT+2) ) return false;
unsigned long bitstream=0L;
byte checksum=0;
byte button=0;
byte group=0;
byte action=0;
byte start=0;
if (RawSignal.Number == CONRADRSL2_PULSECOUNT+2) {
start=2;
}
//==================================================================================
// get bits
for(byte x=1+start;x < RawSignal.Number-2;x=x+2) {
if (RawSignal.Pulses[x] > CONRADRSL2_PULSEMID) {
if (RawSignal.Pulses[x+1] > CONRADRSL2_PULSEMID) return false; // manchester check
bitstream = (bitstream << 1) | 0x1; // 1
} else {
if (RawSignal.Pulses[x+1] < CONRADRSL2_PULSEMID) return false; // manchester check
bitstream = (bitstream << 1); // 0
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// all bits received, make sure checksum is okay
//==================================================================================
checksum=(((bitstream) >> 30)&0x0f); // first two bits should always be '10'
if (checksum != 2) return false;
//==================================================================================
button=(((bitstream) >> 24)&0xff); // 10100011
// ----- check for possible valid values
if (button < 0x81) return false;
if (button > 0xbe) return false;
byte temp=(button)&0xf;
if (temp == 0x07 || temp == 0x0b || temp == 0x0f ) return false;
if (button == 0x83 || button == 0x86 || button == 0x89 || button == 0x8c || button == 0x91 ) return false;
if (button == 0x94 || button == 0x9a || button == 0x9d || button == 0xa1 || button == 0xa4 ) return false;
if (button == 0xaa || button == 0xad || button == 0xb1 || button == 0xb3 || button == 0xb4 ) return false;
if (button == 0xba || button == 0xbd ) return false;
// -----
group=(button) & 0x7; // -- 111
action=((button) >> 3) & 0x1; // -- a
button = ((button) >> 4) & 0x3; // --bb
// -----
if (group == 3) {
action=button;
button=0;
} else {
if (button==3) {
if (group == 6) { // toggle command bit
button=0;
action=(~action)&1;
}
if (group == 1 || group == 5) { // no toggle
button=4;
}
if (group == 0) {
action=(~action)&1; // toggle command bit
button=8;
}
if (group == 2 || group == 4) { // no toggle
button=12;
}
} else
if (button==0) {
if (group == 6 || group == 1) { // no toggle
button=1;
}
if (group == 5) { // toggle command bit
button=5;
action=(~action)&1;
}
if (group == 0 || group == 4) { // no toggle
button=9;
}
if (group == 2) { // toggle command bit
button=13;
action=(~action)&1;
}
} else
if (button==2) {
if (group == 6) { // toggle command bit
button=2;
action=(~action)&1;
}
if (group == 1 || group == 5) button=6; //
if (group == 0) { // toggle command bit
button=10;
action=(~action)&1;
}
if (group == 2 || group == 4) { // no toggle
button=14;
//action=(~action)&1;
}
} else
if (button==1) {
if (group == 6) { // toggle command bit
button=3;
action=(~action)&1;
}
if (group == 1 || group == 5) { // no toggle
button=7;
//action=(~action)&1;
}
if (group == 0) { // toggle command bit
button=11;
action=(~action)&1;
}
if (group == 2 || group == 4) { // no toggle
button=15;
//action=(~action)&1;
}
}
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Conrad;")); // Label
sprintf(pbuffer, "ID=%06lx;",((bitstream) &0xffffff) ); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", button); // Button number
Serial.print( pbuffer );
Serial.print(F("CMD=")); // command
if (group==3) {
Serial.print(F("ALL"));
}
if (action==1) {
Serial.print(F("ON;"));
} else { // 0 normal off, 2 group off
Serial.print(F("OFF;"));
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_007
#ifdef PLUGIN_TX_007
void RSL2_Send(unsigned long address);
boolean PluginTX_007(byte function, char *string) {
boolean success=false;
//10;CONRAD;000fa0;0;OFF;
//10;CONRAD;009200;1;ON;
//10;CONRAD;ff0607;1;OFF;
//012345678901234567890123
if (strncasecmp(InputBuffer_Serial+3,"CONRAD;",7) == 0) { // KAKU Command eg.
unsigned long bitstream=0L;
unsigned long command=0L;
if (InputBuffer_Serial[16] != ';') return success;
InputBuffer_Serial[8]=0x30;
InputBuffer_Serial[9]=0x78;
InputBuffer_Serial[16]=0;
bitstream=str2int(InputBuffer_Serial+8); // Address
byte temp=str2int(InputBuffer_Serial+17); // het button/unit number (0x00..0x0f)
if (temp < 16) { // No button with a number higher than 15
byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF
if (cmd==VALUE_OFF) {
if (temp == 0) command=0xbe;
if (temp == 1) command=0x81;
if (temp == 2) command=0xae;
if (temp == 3) command=0x9e;
if (temp == 4) command=0xb5;
if (temp == 5) command=0x8d;
if (temp == 6) command=0xa5;
if (temp == 7) command=0x95;
if (temp == 8) command=0xb8;
if (temp == 9) command=0x84;
if (temp ==10) command=0xa8;
if (temp ==11) command=0x98;
if (temp ==12) command=0xb2;
if (temp ==13) command=0x8a;
if (temp ==14) command=0xa2;
if (temp ==15) command=0x92;
} else // ON
if (cmd==VALUE_ON) {
if (temp == 0) command=0xb6;
if (temp == 1) command=0x8e;
if (temp == 2) command=0xa6;
if (temp == 3) command=0x96;
if (temp == 4) command=0xb9;
if (temp == 5) command=0x85;
if (temp == 6) command=0xa9;
if (temp == 7) command=0x99;
if (temp == 8) command=0xb0;
if (temp == 9) command=0x88;
if (temp ==10) command=0xa0;
if (temp ==11) command=0x90;
if (temp ==12) command=0xbc;
if (temp ==13) command=0x82;
if (temp ==14) command=0xac;
if (temp ==15) command=0x9c;
} else // AllON
if (cmd==VALUE_ALLON) {
command=0x93;
} else // AllOff
if (cmd==VALUE_ALLOFF) {
command=0xa3;
}
command=command << 24;
bitstream=bitstream+command;
}
RSL2_Send(bitstream); // the full bitstream to send
success=true;
}
return success;
}
void RSL2_Send(unsigned long address) {
int fpulse = 650; // Pulse witdh in microseconds 650?
int fpulse2 = 450; // Pulse witdh in microseconds 650?
int fretrans = 4; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff=address;
// send SYNC 1P High, 10P low
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 10);
// end send SYNC
// Send command
for (int i = 0; i < 32; i++) { // 32 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 3);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 1);
}
}
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 14);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
RFLinkHW();
}
#endif // PLUGIN_TX_007

250
Plugins/Plugin_008.c Normal file
View File

@@ -0,0 +1,250 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-008 Kambrook ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of receiving of the Kambrook protocol
* Device models: RF3399/RF3405/RF3672/RF3689/RF4471R
* Made by Ningbo Comen Electronics Technology Co. Ltd.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* RF packets contain 96 pulses, 48 bits
*
* Kambrook Message Format:
* AAAAAAAA BBBBBBBB BBBBBBBB BBBBBBBB CCCCCCCC DDDDDDDD
*
* A = Preamble, always 0x55
* B = Address
* C = Channel/Command
* D = Trailing, always 0xFF
*
* Details http://wiki.beyondlogic.org/index.php?title=Reverse_engineering_the_RF_protocol_on_a_Kambrook_Power_Point_Controller
*
* 20;33;DEBUG;Pulses=96;Pulses(uSec)=270,180,600,180,210,180,600,180,210,180,600,180,210,180,600,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,600,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,6990;
\*********************************************************************************************/
#define KAMBROOK_PULSECOUNT 96
#define KAMBROOK_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_008
boolean Plugin_008(byte function, char *string) {
if (RawSignal.Number != KAMBROOK_PULSECOUNT) return false;
unsigned long address=0L;
byte sync=0;
byte command=0;
byte trailing=0;
byte bitcounter=0;
byte status=0;
byte channel=0;
byte subchan=0;
//==================================================================================
// get bits
for(byte x=1;x<KAMBROOK_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x] > KAMBROOK_PULSEMID) {
if (bitcounter < 8) {
sync = (sync << 1) | 0x1;
} else
if (bitcounter < 32) {
address = (address << 1) | 0x1;
} else
if (bitcounter < 40) {
command = (command << 1) | 0x1;
} else {
trailing = (trailing << 1) | 0x1;
}
bitcounter++;
} else {
if (bitcounter < 8) {
sync = (sync << 1);
} else
if (bitcounter < 32) {
address = (address << 1);
} else
if (bitcounter < 40) {
command = (command << 1);
} else {
trailing = (trailing << 1);
}
bitcounter++;
}
}
//==================================================================================
// all bits received, make sure checksum/sanity check is okay
//==================================================================================
if (sync != 0x55) return false;
if (trailing != 0xff) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
// not seen the RF packet recently
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
//==================================================================================
status=(command)&1; // 0/1 off/on
subchan=(((command) >> 1)&7) + 1; // button code
if (status == 0) subchan--;
byte temp=(command) >> 4; // channel code
channel=0x41+temp;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Kambrook;")); // Label
sprintf(pbuffer, "ID=%06lx;",((address)&0xffffff) ); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
Serial.print( pbuffer );
Serial.print(F("CMD=")); // command
if (status==0) Serial.print(F("OFF;"));
if (status==1) Serial.print(F("ON;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_008
#ifdef PLUGIN_TX_008
void Kambrook_Send(unsigned long address);
boolean PluginTX_008(byte function, char *string) {
boolean success=false;
//10;kambrook;050325;a1;ON;
//012345678901234567890123
if (strncasecmp(InputBuffer_Serial+3,"KAMBROOK;",9) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[18] != ';') return false;
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78; // Get address from hexadecimal value
InputBuffer_Serial[18]=0x00; // Get address from hexadecimal value
unsigned long bitstream=0L; // Main placeholder
byte Home=0; // channel A..D
byte Address=0; // subchannel 1..5
byte c;
byte x=19; // teller die wijst naar het te behandelen teken
bitstream=str2int(InputBuffer_Serial+10); // Address
while((c=tolower(InputBuffer_Serial[x++]))!=';') {
if(c>='0' && c<='9'){Address=Address+c-'0';} // Home 0..9
if(c>='a' && c<='d'){Home=c-'a';} // Address a..d
}
Address=Address << 1; // shift left 1 bit
c=0;
c = str2cmd(InputBuffer_Serial+x); // ON/OFF command
if (c == VALUE_ON) {
Address--;
}
Address=Address & 0x0f;
// -------------------------------
Home = Home << 4; // move home to bits 4-7
bitstream=(bitstream) << 8; // shift main value 8 bits left
bitstream=bitstream + Home; // add to main value
bitstream=bitstream + Address; // add address bits to bits 0-3
// -------------------------------
Kambrook_Send(bitstream); // bitstream to send
success=true;
}
return success;
}
void Kambrook_Send(unsigned long address) {
int fpulse = 300; // Pulse witdh in microseconds
int fpulse2 = 700; // Pulse witdh in microseconds
int fretrans = 5; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x800000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
// --------------
// Send preamble (0x55) - 8 bits
fsendbuff=0x55;
fdatamask=0x80;
for (int i = 0; i < 8; i++) { // Preamble
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
}
}
// --------------
fsendbuff=address;
fdatamask=0x80000000;
// Send command (channel/address/status) - 32 bits
for (int i = 0; i < 32;i++){ //28;i++){
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
}
}
// --------------
// Send trailing bits - 8 bits
fsendbuff=0xFF;
fdatamask=0x80;
for (int i = 0; i < 8; i++) {
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
}
}
// --------------
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 14);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
RFLinkHW();
}
#endif // PLUGIN_008

347
Plugins/Plugin_009.c Normal file
View File

@@ -0,0 +1,347 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-06: X10 RF ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the X10 RF protocol.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Incoming event: "X10 <adres>, <On | Off>
* Send : "X10Send <Adres>, <On | Off>
*
* Address = A1 - P16
***********************************************************************************************
* Technical information:
* RF packets are 68 bits long transferring 64 manchester encoded bits resulting in 32 bits / 4 bytes.
*
* address address^ data data^
* 01100000 10011111 00000000 11111111 609F00FF
* 10011111 01100000 11111111 00000000 9F60FF00
*
* 4 bytes are transmitted, the second and fourth are the inverse of the first and third byte.
* So the actual data is only 2 bytes
*
* 01100000 00000000
* AAAABBBB CDEDDDDD
*
* A = Housecode 0110 a 6 0111 b 7 0100 c 4 0101 d 5 1000 e 8 1001 f 9 1010 g a 1011 h b
* 1110 i e 1111 j f 1100 k c 1101 l d 0000 m 0 0001 n 1 0010 o 2 0011 p 3
* B = Unitcode 1-8 / 9-16 indicator
* C = Group/Dimmer indicator
* D = Unitcode
* E = on/off indicator
*
* on
* 20;06;DEBUG;Pulses=68;Pulses(uSec)=3300,4225,400,375,400,1325,400,1325,400,1325,400,375,400,375,400,375,400,375,400,1325,400,375,400,375,400,375,400,1350,400,1350,375,1350,400,1350,400,375,400,375,400,375,400,1325,400,1325,400,375,400,375,400,375,400,1350,400,1325,400,1325,400,375,400,375,400,1325,400,1325,400,1325,400
* off
* 20;10;DEBUG;Pulses=68;Pulses(uSec)=3300,4225,400,375,400,1350,400,1350,400,1325,400,375,400,375,400,375,400,375,400,1325,400,375,400,375,400,375,400,1325,400,1325,400,1325,400,1325,400,375,400,375,400,1325,400,1350,400,1350,400,375,400,375,400,375,375,1350,400,1350,400,375,400,375,400,375,400,1325,400,1350,400,1325,400;
* 20;20;DEBUG;Pulses=66;Pulses(uSec)=425,350,375,1300,375,1300,375,1350,375,375,375,1350,375,375,375,375,375,1350,375,375,375,375,375,375,400,1350,375,375,400,1350,375,1350,400,1325,400,375,400,375,400,375,400,375,400,375,400,375,400,375,400,375,400,1325,400,1325,400,1325,400,1325,400,1325,400,1350,375,1350,375;
\*********************************************************************************************/
#define X10_PulseLength 66
#define X10_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_009
boolean Plugin_009(byte function, char *string) {
if ( (RawSignal.Number != (X10_PulseLength )) && (RawSignal.Number != (X10_PulseLength+2)) ) return false;
unsigned long bitstream=0L;
byte housecode=0;
byte unitcode=0;
byte command=0;
byte data[4];
byte start=0;
if (RawSignal.Number == X10_PulseLength+2) {
if ( (RawSignal.Pulses[1]*RawSignal.Multiply > 3000) && (RawSignal.Pulses[2]*RawSignal.Multiply > 3000) ) {
start=2;
} else {
return false; // not an X10 packet
}
}
// get all 24 bits
for(byte x=2+start;x < ((X10_PulseLength)+start) ;x+=2) {
if(RawSignal.Pulses[x] > X10_PULSEMID) {
bitstream = (bitstream << 1) | 0x1;
} else {
bitstream = (bitstream << 1);
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// order received data
data[0]=((bitstream)>>24)&0xff;
data[1]=((bitstream)>>16)&0xff;
data[2]=((bitstream)>>8)&0xff;
data[3]=(bitstream)&0xff;
// ----------------------------------
// perform sanity checks
data[1]=data[1]^0xff;
data[3]=data[3]^0xff;
if (data[0] != data[1]) return false;
if (data[2] != data[3]) return false;
// ----------------------------------
data[1]=data[1]&0x0f; // lower nibble only
data[0]=data[0]&0xf0; // upper nibble only
housecode=0;
if (data[0]==0x60) housecode=0;
if (data[0]==0x70) housecode=1;
if (data[0]==0x40) housecode=2;
if (data[0]==0x50) housecode=3;
if (data[0]==0x80) housecode=4;
if (data[0]==0x90) housecode=5;
if (data[0]==0xa0) housecode=6;
if (data[0]==0xb0) housecode=7;
if (data[0]==0xe0) housecode=8;
if (data[0]==0xf0) housecode=9;
if (data[0]==0xc0) housecode=10;
if (data[0]==0xd0) housecode=11;
if (data[0]==0x00) housecode=12;
if (data[0]==0x10) housecode=13;
if (data[0]==0x20) housecode=14;
if (data[0]==0x30) housecode=15;
if (data[2]==0x00) { unitcode=1; command=1;}
if (data[2]==0x20) { unitcode=1; command=0;}
if (data[2]==0x10) { unitcode=2; command=1;}
if (data[2]==0x30) { unitcode=2; command=0;}
if (data[2]==0x08) { unitcode=3; command=1;}
if (data[2]==0x28) { unitcode=3; command=0;}
if (data[2]==0x18) { unitcode=4; command=1;}
if (data[2]==0x38) { unitcode=4; command=0;}
if (data[2]==0x40) { unitcode=5; command=1;}
if (data[2]==0x60) { unitcode=5; command=0;}
if (data[2]==0x50) { unitcode=6; command=1;}
if (data[2]==0x70) { unitcode=6; command=0;}
if (data[2]==0x48) { unitcode=7; command=1;}
if (data[2]==0x68) { unitcode=7; command=0;}
if (data[2]==0x58) { unitcode=8; command=1;}
if (data[2]==0x78) { unitcode=8; command=0;}
if (data[2]==0x88) { unitcode=0; command=2;}
if (data[2]==0x98) { unitcode=0; command=3;}
if (data[2]==0x80) { unitcode=0; command=4;}
if (data[2]==0x90) { unitcode=0; command=5;}
if ( (data[1]==0x04) && (command < 2) ) {
unitcode=unitcode+8;
}
//==================================================================================
// ----------------------------------
// All is OK, build event
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("X10;")); // Label
sprintf(pbuffer, "ID=%02x;", 0x41+housecode); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%d;", unitcode);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if ( command == 0) {
Serial.print(F("OFF;"));
} else
if ( command == 1) {
Serial.print(F("ON;"));
} else
if ( command == 2) {
Serial.print(F("BRIGHT;"));
} else
if ( command == 3) {
Serial.print(F("DIM;"));
} else
if ( command == 4) {
Serial.print(F("ALLOFF;"));
} else
if ( command == 5) {
Serial.print(F("ALLON;"));
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_009
#ifdef PLUGIN_TX_009
void X10_Send(uint32_t address);
boolean PluginTX_009(byte function, char *string) {
boolean success=false;
//10;X10;000041;1;OFF;
//0123456789012345678
// Hier aangekomen bevat string het volledige commando. Test als eerste of het opgegeven commando overeen komt
if (strncasecmp(InputBuffer_Serial+3,"X10;",4) == 0) { // X10 Command eg.
unsigned long bitstream=0L;
byte x=14; // teller die wijst naar het te behandelen teken
byte command=0;
byte Home=0; // Home A..P
byte Address=0; // Blyss subchannel 1..5
byte c;
uint32_t newadd=0;
InputBuffer_Serial[ 9]=0x30;
InputBuffer_Serial[10]=0x78;
InputBuffer_Serial[13]=0;
Home=str2int(InputBuffer_Serial+9); // Home: A..P
if (Home < 0x51) // take care of upper/lower case
Home=Home - 'A';
else
if (Home < 0x71) // take care of upper/lower case
Home=Home - 'a';
else {
return success; // invalid value
}
while((c=tolower(InputBuffer_Serial[x++]))!=';'){ // Address: 1 to 16
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
}
if (Home == 0) c = 0x60;
if (Home == 1) c = 0x70;
if (Home == 2) c = 0x40;
if (Home == 3) c = 0x50;
if (Home == 4) c = 0x80;
if (Home == 5) c = 0x90;
if (Home == 6) c = 0xa0;
if (Home == 7) c = 0xb0;
if (Home == 8) c = 0xe0;
if (Home == 9) c = 0xf0;
if (Home ==10) c = 0xc0;
if (Home ==11) c = 0xd0;
if (Home ==12) c = 0x00;
if (Home ==13) c = 0x10;
if (Home ==14) c = 0x20;
if (Home ==15) c = 0x30;
if (Address > 7) {
c = c + 4;
Address=Address-8;
}
// ---------------
Home=str2cmd(InputBuffer_Serial+x);
if (Home == 0) { // DIM/BRIGHT command
if (strcasecmp(InputBuffer_Serial+x,"DIM")==0) {
command=3;
} else
if (strcasecmp(InputBuffer_Serial+x,"BRIGHT")==0) {
command=2;
}
c = c + 4;
} else {
if (Home==VALUE_ON) {
command=1;
} else
if (Home==VALUE_OFF) {
command=0;
} else
if (Home==VALUE_ALLOFF) {
command=4;
c = c + 4;
} else
if (Home==VALUE_ALLON) {
command=5;
c = c + 4;
}
}
if (Address == 1 && command == 1) bitstream=0x00;
if (Address == 1 && command == 0) bitstream=0x20;
if (Address == 2 && command == 1) bitstream=0x10;
if (Address == 2 && command == 0) bitstream=0x30;
if (Address == 3 && command == 1) bitstream=0x08;
if (Address == 3 && command == 0) bitstream=0x28;
if (Address == 4 && command == 1) bitstream=0x18;
if (Address == 4 && command == 0) bitstream=0x38;
if (Address == 5 && command == 1) bitstream=0x40;
if (Address == 5 && command == 0) bitstream=0x60;
if (Address == 6 && command == 1) bitstream=0x50;
if (Address == 6 && command == 0) bitstream=0x70;
if (Address == 7 && command == 1) bitstream=0x48;
if (Address == 7 && command == 0) bitstream=0x68;
if (Address == 8 && command == 1) bitstream=0x58;
if (Address == 8 && command == 0) bitstream=0x78;
if (command == 2) bitstream=0x88;
if (command == 3) bitstream=0x98;
if (command == 4) bitstream=0x80;
if (command == 5) bitstream=0x90;
// -----------------------------
newadd=bitstream <<8;
bitstream=bitstream^0xff;
newadd=newadd+bitstream;
bitstream=c^0xff;
bitstream=bitstream<<16;
newadd=newadd+bitstream;
bitstream=c;
bitstream=bitstream<<24;
newadd=newadd+bitstream;
bitstream=newadd;
// -----------------------------
X10_Send(bitstream); // full bitstream to send
success=true;
}
return success;
}
void X10_Send(uint32_t address) {
int fpulse = 375; // Pulse witdh in microseconds
int fretrans = 4; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Disable RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable RF transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff=address;
// send SYNC 12P High, 10P low
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 12);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 10);
// end send SYNC
// Send command
for (int i = 0; i < 32; i++) { // 32 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 4);
}
}
// Send Stop/delay
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 20);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable RF transmitter
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable RF receiver
RFLinkHW();
return;
}
#endif //PLUGIN_TX_009

242
Plugins/Plugin_010.c Normal file
View File

@@ -0,0 +1,242 @@
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-10 TRC02 RGB Controller ##
//#######################################################################################################
/*********************************************************************************************\
* Decodes signals from a wireless RGB TRC02 controller remote control
*
*
* Author : StuntTeam, Marek Zlatos,
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from a wireless TRC02 RGB controller remote control
* --------------------------------------------------------------------------------------------
* _Byte 0_ _Byte 1_ _Byte 2_ _Byte 3_ _Bit_
* 76543210 76543210 76543210 76543210 0
* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD E
*
* A = Rolling Code
* B = Rolling Code
* C = Rolling Code
* D = Command
* E = Checksum. bit is XOR of all bits in the RF message
*
* Commands:
* 00 ON
* 01 OFF
* 02 Dim Down
* 03 DIM UP
* 05 Color Mix UP
* 04 Color Mix Down
* 87 Color Wheel Red
* 34 Color Wheel Blue
* 78 Color Wheel Yellow
* 5D Color Wheel Green
*
* Sample:
* 20;30;DEBUG;Pulses=180;Pulses(uSec)=450,420,420,420,420,420,1410,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,390,1440,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,390,1440,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,6990
* TRC02:00000011 00000010 00111100 00000000 1
* 20;01;TRC02;ID=03023c;SWITCH=00;CMD=ON;
\*********************************************************************************************/
#define RGB_MIN_PULSECOUNT 180
#define RGB_MAX_PULSECOUNT 186
#define RGB_PULSE_STHI 1600/RAWSIGNAL_SAMPLE_RATE
#define RGB_PULSE_STLO 1300/RAWSIGNAL_SAMPLE_RATE
#define RGB_PULSE_HIHI 1100/RAWSIGNAL_SAMPLE_RATE
#define RGB_PULSE_HILO 900/RAWSIGNAL_SAMPLE_RATE
#define RGB_PULSE_LOHI 600/RAWSIGNAL_SAMPLE_RATE
#define RGB_PULSE_LOLO 400/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_010
boolean Plugin_010(byte function, char *string) {
if (RawSignal.Number < RGB_MIN_PULSECOUNT || RawSignal.Number > RGB_MAX_PULSECOUNT) return false;
unsigned long bitstream=0L; // holds first 32 bits
byte checksum=0; // holds the checksum calculation
byte crc=0; // holds the crc bit from the signal
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
byte bitmask = 0;
int command=0;
byte start_stop=0;
byte x=1;
//==================================================================================
for(x=1;x <RawSignal.Number-2;x++) { // get bytes
if (start_stop!=0x01) {
//if (RawSignal.Pulses[x]*RawSignal.Multiply > 1200 && RawSignal.Pulses[x]*RawSignal.Multiply < 1500) {
if (RawSignal.Pulses[x] > RGB_PULSE_STLO && RawSignal.Pulses[x] < RGB_PULSE_STHI) {
start_stop=0x01;
continue;
} else {
if (x > 100) return false; // bad packet
continue;
}
}
if (RawSignal.Pulses[x]*RawSignal.Multiply > 750 && RawSignal.Pulses[x]*RawSignal.Multiply < 1000) {
if (halfbit==1) { // cant receive a 1 bit after a single low value
return false; // pulse error, must not be a UPM packet or reception error
}
bitmask = !bitmask;
if (bitcounter < 32) {
if (bitmask == 1){
bitstream = (bitstream << 1);
} else {
bitstream = (bitstream << 1) | 0x1;
}
bitcounter++; // only need to count the first 10 bits
} else {
crc =1;
break;
}
halfbit=0; // wait for next first low or high pulse
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 625 && RawSignal.Pulses[x]*RawSignal.Multiply < 250) return false; // Not a valid UPM pulse length
if (halfbit == 0) { // 2 times a low value = 0 bit
halfbit=1; // first half received
} else {
if (bitcounter < 32) {
if (bitmask == 1){
bitstream = (bitstream << 1);
} else {
bitstream = (bitstream << 1) | 0x1;
}
checksum=checksum^1;
bitcounter++; // only need to count the first 10 bits
} else {
crc=0;
break;
}
halfbit=0; // wait for next first low or high pulse
}
}
}
//==================================================================================
// Validity checks
if (RawSignal.Pulses[x+2]*RawSignal.Multiply < 1200 || RawSignal.Pulses[x+2]*RawSignal.Multiply > 1500) return false;
//==================================================================================
// perform a checksum check to make sure the packet is a valid RGB control packet
// Checksum: xor all odd and all even bits should match the last bit
// ----------------------------------
if (checksum != crc) {
//Serial.println("crc2 error");
return false;
}
//==================================================================================
// now process the command
//==================================================================================
command = (bitstream) &0xff; // command
int id3 = (bitstream >> 8) &0xff;
bitstream = (bitstream >> 16) &0xffff; // rolling code
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("TRC02RGB;")); // Label
sprintf(pbuffer, "ID=%04x", bitstream); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "%02x;", id3);
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", command);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if (command==0x00) Serial.print("ON;");
else if (command==0x01) Serial.print(F("OFF;"));
else if (command==0x02) Serial.print(F("DIM DOWN;"));
else if (command==0x03) Serial.print(F("DIM UP;"));
else if (command==0x05) Serial.print(F("COLORMIX UP;"));
else if (command==0x04) Serial.print(F("COLORMIX DOWN;"));
else if (command==0x87) Serial.print(F("COLOR RED;"));
else if (command==0x34) Serial.print(F("COLOR BLUE;"));
else if (command==0x78) Serial.print(F("COLOR YELLOW;"));
else if (command==0x5D) Serial.print(F("COLOR GREEN;"));
else {
sprintf(pbuffer, "SET_LEVEL=%d;", command );
Serial.print( pbuffer );
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_010
#ifdef PLUGIN_TX_010
void TRC02_Send(unsigned long address, int command);
boolean PluginTX_010(byte function, char *string) {
//10;TRC02RGB;03023c;00;
//012345678901234567890123456
boolean success=false;
if (strncasecmp(InputBuffer_Serial+3,"TRC02RGB;",9) == 0) { // KAKU Command eg.
TRC02_Send(strtoul(InputBuffer_Serial+12,NULL,16),strtoul(InputBuffer_Serial+19,NULL,16));
success=true;
}
return success;
}
void TRC02_Send(unsigned long address, int command) {
int fpulse = 500;
int fretrans = 2; // Number of code retransmissions
byte crc = 0;
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
crc=0;
fsendbuff=address;
fsendbuff=(fsendbuff<<8)+command;
digitalWrite(PIN_RF_TX_DATA, HIGH); // start pulse
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
for (int i = 0; i < 32; i++) { // TRC02 packet is 32 bits + 1 bit crc
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
crc += crc^0;
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
crc += crc^1;
}
}
if (crc==1) { // crc pulse
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
} else {
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
}
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
#endif //PLUGIN_TX_010

444
Plugins/Plugin_011.c Normal file
View File

@@ -0,0 +1,444 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-11 Home Confort Smart Home - TEL-010 ##
//#######################################################################################################
/*********************************************************************************************\
* Decodes signals from a Home Confort Smart Home - TEL-010
* http://idk.home-confort.net/divers/t%C3%A9l%C3%A9commande-rf-pour-produits-smart-home
*
* Author : StuntTeam, François Pasteau
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from Home Confort Smart Home - TEL-010 devices
* --------------------------------------------------------------------------------------------
* _Byte 0_ _Byte 1_ _Byte 2_ _Byte 3_ _Byte 4_ _Byte 5_ _Bits_
* AAAAAAAA BBBBBBBB CCCDDDDD EEEEEEEE FFFFFFFF GGHHHHHH II
* 11111111 11111111 11100010 00000000 00000000 10000001 00 Type 1 (no address, using A1-D4)
* 00110110 10100100 01111010 00000000 00000000 10000001 00 Type 2 (using 19 bit? address and button number 1-?
*
* A = Address? (19 bits?)
* B = Address? (19 bits?)
* C = Address? (19 bits?)
* D = Command bits (see below)
* E = verification bytes?, Always 0x00? => possibly reserved for future use or other device types
* F = verification bytes?, Always 0x00? => possibly reserved for future use or other device types
* G = Command bits (see below)
* H = always '000001' ?
* I = Stop bits?, Always '00'
*
* D & G explanation:
* DDDDD GG
* 11233 45
* 00000 00
11010 10 D3
* 1=switch setting 00=A 10=B 01=C 11=D
* 2=group indicator 1=group command
* 3=button number 00=1 01=2 10=3 11=4
* 4=command 0=off, 1=on
* 5=group indicator 1=group command
* ------------
* 101010101010101010101010101010101010100101011001010101010101010101010101010101011001010101010110 00
* 111111111111111111100010000000000000000010000001 00 A3 on
* 20;17;DEBUG;Pulses=100;Pulses(uSec)=
* 2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,
* 575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,
* 575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,
* 550,250,550,250,550,750,50,250,50; =99
*
* 2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,550,250,550,250,550,750,50,250,50
\*********************************************************************************************/
#define HC_PULSECOUNT 100
#ifdef PLUGIN_011
boolean Plugin_011(byte function, char *string) {
if (RawSignal.Number != HC_PULSECOUNT ) return false;
if (RawSignal.Pulses[1]*RawSignal.Multiply < 2000) return false; // First (start) pulse needs to be long
unsigned long bitstream1=0; // holds first 24 bits
unsigned long bitstream2=0; // holds last 26 bits
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte command=0;
byte channel=0;
byte subchan=0;
byte group=0;
//==================================================================================
for(int x=2;x < HC_PULSECOUNT-2;x+=2) { // get bytes
if (RawSignal.Pulses[x]*RawSignal.Multiply > 500) { // long pulse
if (RawSignal.Pulses[x]*RawSignal.Multiply > 800) return false; // Pulse range check
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 400) return false; // Manchester check
if (bitcounter < 24) {
bitstream1 = (bitstream1 << 1) | 0x1;
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
}
bitcounter++; // only need to count the first 10 bits
} else { // short pulse
if (RawSignal.Pulses[x]*RawSignal.Multiply > 300) return false; // pulse range check
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 400) return false; // Manchester check
if (bitcounter < 24) {
bitstream1 = (bitstream1 << 1);
} else {
bitstream2 = (bitstream2 << 1);
}
bitcounter++; // only need to count the first 10 bits
}
if (bitcounter > 50) break;
}
if (RawSignal.Pulses[98]*RawSignal.Multiply > 300) return false; // pulse range check, last two pulses should be short
if (RawSignal.Pulses[99]*RawSignal.Multiply > 300) return false; // pulse range check
//==================================================================================
// first perform a check to make sure the packet is valid
byte tempbyte=(bitstream2 >>8) & 0xff;
if (tempbyte != 0x0) return false; // always 0x00?
tempbyte=(bitstream2 >>16) & 0xff;
if (tempbyte != 0x0) return false; // always 0x00?
tempbyte=(bitstream2) & 0x3f;
if (tempbyte != 0x01) return false; // low 6 bits are always '000001'?
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || ((RepeatingTimer+1500)<millis()) || SignalCRC != bitstream2 ) {
// not seen the RF packet recently
SignalCRC=bitstream2;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// now process the command / switch settings
//==================================================================================
tempbyte=(bitstream1 >> 3) & 0x03; // determine switch setting (a/b/c/d)
channel=0x41;
if (tempbyte==2) channel=0x42;
if (tempbyte==1) channel=0x43;
if (tempbyte==3) channel=0x44;
subchan=((bitstream1)&0x03)+1; // determine button number
command=(bitstream2 >> 7) & 0x01; // on/off command
group=(bitstream2 >> 6) & 0x01; // group setting
bitstream1=bitstream1 >> 5;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("HomeConfort;")); // Label
sprintf(pbuffer, "ID=%06lx;",((bitstream1) &0xffffff) ); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if (group==1) Serial.print(F("ALL"));
if (command==0) Serial.print(F("OFF;"));
if (command==1) Serial.print(F("ON;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_011
#ifdef PLUGIN_TX_011
void HomeConfort_Send(unsigned long bitstream1, unsigned long bitstream2);
boolean PluginTX_011(byte function, char *string) {
boolean success=false;
//10;HomeConfort;01b523;D3;ON;
//0123456789012345678901234567
if (strncasecmp(InputBuffer_Serial+3,"HomeConfort;",12) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[21] != ';') return success;
InputBuffer_Serial[13]=0x30;
InputBuffer_Serial[14]=0x78; // Get address from hexadecimal value
InputBuffer_Serial[21]=0x00; // Get address from hexadecimal value
unsigned long bitstream1=0L; // First Main placeholder
unsigned long bitstream2=0L; // Second Main placeholder
byte Home=0; // channel A..D
byte Address=0; // subchannel 1..5
byte c;
byte x=22; // pointer
// -------------------------------
bitstream1=str2int(InputBuffer_Serial+13); // Address (first 19 bits)
// -------------------------------
while((c=tolower(InputBuffer_Serial[x++]))!=';') {
if(c>='0' && c<='9'){Address=Address+c-'0';} // Home 0..9
if(c>='a' && c<='d'){Home=c-'a';} // Address a..d
}
// -------------------------------
// prepare bitstream1
// -------------------------------
bitstream1 = bitstream1 << 5; // make space for first 5 command bits
Address--; // 1..4 to 0..3
Address=Address & 0x03; // only accept 2 bits for the button number part
bitstream1=bitstream1+Address;
if (Home == 0) c=0; // A
if (Home == 1) c=2; // B
if (Home == 2) c=1; // C
if (Home == 3) c=3; // D
Home=c << 3; // shift left for the right position
bitstream1=bitstream1+Home;
// -------------------------------
// prepare bitsrteam2
c=0;
c = str2cmd(InputBuffer_Serial+x); // ON/OFF command
bitstream2=1; // value off
if (c == VALUE_ON) {
bitstream2=0x81; // value on
} else {
if (c == VALUE_ALLOFF) {
bitstream2=0x41;
bitstream1=bitstream1+4; // set group
} else
if (c == VALUE_ALLON) {
bitstream2=0xc1;
bitstream1=bitstream1+4; // set group
}
}
// -------------------------------
HomeConfort_Send(bitstream1,bitstream2); // bitstream to send
success=true;
}
return success;
}
/*
void HomeConfort_Send(unsigned long data1, unsigned long data2) {
int fpulse = 270; // Pulse width in microseconds
int fpulse2 = 710; // Pulse width in microseconds
int fretrans = 10; // Number of code retransmissions
unsigned long bitstream1 = 0L;
unsigned long bitstream2 = 0L;
// prepare data to send
for (unsigned short i=0; i<24; i++) { // reverse data bits
bitstream1<<=1;
bitstream1|=(data1 & B1);
data1>>=1;
}
for (unsigned short i=0; i<24; i++) { // reverse data bits
bitstream2<<=1;
bitstream2|=(data2 & B1);
data2>>=1;
}
// -------------------------------
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
// -------------------------------
// Prepare transmit
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
// send bits
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
data1=bitstream1;
data2=bitstream2;
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //270*10=2700
for (unsigned short i=0; i<24; i++) {
switch (data1 & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1);
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
break;
}
//Next bit
data1>>=1;
}
for (unsigned short i=0; i<24; i++) {
switch (data2 & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1); // 335*3=1005 260*5=1300 260*4=1040
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
break;
}
//Next bit
data2>>=1;
}
//Send termination/synchronisation-signal.
//digitalWrite(PIN_RF_TX_DATA, HIGH);
//delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 27);
//RawSignal.Pulses[98]=300/RawSignal.Multiply;
//RawSignal.Pulses[99]=175/RawSignal.Multiply;
//RawSignal.Delay=125; // Delay between RF packets
}
// End transmit
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
void HomeConfort_Send(unsigned long data1, unsigned long data2) {
int fpulse = 270; // Pulse width in microseconds
int fpulse2 = 710; // Pulse width in microseconds
int fretrans = 10; // Number of code retransmissions
unsigned long bitstream1 = 0L;
unsigned long bitstream2 = 0L;
// prepare data to send
for (unsigned short i=0; i<24; i++) { // reverse data bits
bitstream1<<=1;
bitstream1|=(data1 & B1);
data1>>=1;
}
for (unsigned short i=0; i<24; i++) { // reverse data bits
bitstream2<<=1;
bitstream2|=(data2 & B1);
data2>>=1;
}
// -------------------------------
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
// -------------------------------
// Prepare transmit
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
// send bits
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
data1=bitstream1;
data2=bitstream2;
digitalWrite(PIN_RF_TX_DATA, HIGH);
//delayMicroseconds(fpulse); //335
delayMicroseconds(335);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //270*10=2700
for (unsigned short i=0; i<24; i++) {
switch (data1 & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 1);
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
break;
}
//Next bit
data1>>=1;
}
for (unsigned short i=0; i<24; i++) {
switch (data2 & B1) {
case 0:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse2 * 1); // 335*3=1005 260*5=1300 260*4=1040
break;
case 1:
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse2 * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
break;
}
//Next bit
data2>>=1;
}
//Send termination/synchronisation-signal.
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 27);
//RawSignal.Pulses[98]=300/RawSignal.Multiply;
//RawSignal.Pulses[99]=175/RawSignal.Multiply;
//RawSignal.Delay=125; // Delay between RF packets
}
// End transmit
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
*/
/*
20;E4;DEBUG;Pulses=511;Pulses(uSec)=
330,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,150,210,600,630,150,210,600,630,180,180,600,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,600,180,600,180,600,180,600,210,600,210,600,630,150,210,180,
270,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,180,180,600,630,180,180,600,630,180,180,600,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,150,210,600,210,600,210,600,210,600,180,600,180,600,180,600,180,600,180,600,180,600,180,630,180,630,180,630,180,630,180,630,180,600,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,150,
270,2760,210,600,210,600,630,150,630,150,210,600,630,180,630,180,180,600,630,180,180,600,630,180,180,630,180,630,630,180,180,630,180,630,180,630,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,210,600,630,150,210,600,210,600,210,600,210,600,180,600,180,600,630,180,180,180,270,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,180,180,600,630,180,180,600,630,180,180,600,180,600,630,180,180,600,180,600,210,600,630,150,630,150,630,150,630,150,210,600,630,180,180,600,180,600,180,600,180,600,180,630,180,630,180,630,180,630,180,630,180,630,180,630,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,180,270,2760,210,600,180,600,630,180,630,180,180,630,630,180,630,180,180,630,630,180,180,630,630,180,180,630,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,210,600,210,600,210,600,210,600,210,600,210,600,210,600,210,600,630,180,180,600,180,630,180,630,180,630,180,630,180,630,630,180,180,180,270,2760,180,600,180,600,630,180,630,180,180;
20;CA;DEBUG;Pulses=100;Pulses(uSec)=
2490,180,630,150,630,600,180,600,180,150,630,600,180,600,180,150,630,630,180,150,630,630,180,150,630,150,630,630,180,150,630,150,630,150,630,630,180,600,180,600,180,600,180,150,630,600,180,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,630,180,180,60,6990;
*/
#define PLUGIN_011_RFLOW 270 // 300
#define PLUGIN_011_RFHIGH 720 // 800
void HomeConfort_Send(unsigned long bitstream1, unsigned long bitstream2) {
RawSignal.Repeats=8; // Number of RF packet retransmits
RawSignal.Delay=125; // Delay between RF packets
RawSignal.Number=100; // Length
uint32_t fdatabit;
uint32_t fdatamask = 0x800000;
// -------------------------------
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
// -------------------------------
RawSignal.Pulses[1]=2600/RawSignal.Multiply;
for (byte i=2; i<103; i=i+2) {
if (i<50) { // first 24 bits
fdatabit = bitstream1 & fdatamask; // Get most left bit
bitstream1 = (bitstream1 << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
RawSignal.Pulses[i] = PLUGIN_011_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_011_RFHIGH/RawSignal.Multiply;
} else { // Write 1
RawSignal.Pulses[i] = PLUGIN_011_RFHIGH/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_011_RFLOW/RawSignal.Multiply;
}
} else {
fdatabit = bitstream2 & fdatamask; // Get most left bit
bitstream2 = (bitstream2 << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
RawSignal.Pulses[i] = PLUGIN_011_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_011_RFHIGH/RawSignal.Multiply;
} else { // Write 1
RawSignal.Pulses[i] = PLUGIN_011_RFHIGH/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_011_RFLOW/RawSignal.Multiply;
}
}
}
RawSignal.Pulses[98]=300/RawSignal.Multiply;
RawSignal.Pulses[99]=175/RawSignal.Multiply;
RawSendRF();
}
#endif // PLUGIN_TX_011

309
Plugins/Plugin_012.c Normal file
View File

@@ -0,0 +1,309 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-03: FA500R ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the Elro Flamingo FA500 protocol.
* Also works with compatible devices like the Mumbi M-FS300 and Silvercrest 91210/60494 RCS AAA3680, Unitec eim 821/art.48111
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Incoming event: "FA500 <adres>,<On | Off>
* Send : "FA500Send <Adres>, <On | Off>
*
* Address = A/B/C/D matching the remote control buttons.
***********************************************************************************************
* Technical information:
* The FA500R remote control sends 3 different protocols.
* 4 x Method 1 - 28 bit code
* 6 x method 2 - AC compatible
* 5 x method 3 - 24/12 bit code
* It appears that the FA500S is only capable to react to the first method. So this has to be used to switch sockets
* Nodo can only distinguish the 3rd method properly. Method 1 and 2 have to be pulled apart first which
* is done via plugin 001.
*
* Device types:
* Elro FA500S Flamingo Switch
* Elro FA500DSS Flamingo Dimmer
* Elro FA500WD Flamingo Outdoor
* Elro FA500R Flamingo Remote Control
*
* PCB Markings:
* 50027.01B FLF-130105
* KT50039.01A FLF-13-06-03 Chip marking: S007V0.1
* KT50040.01A FLF-13-06-04
*
* http://forum.arduino.cc/index.php?topic=202556.0
*
* Sample:
* 20;60;DEBUG;Pulses=24;Pulses(uSec)=325,800,275,800,825,225,275,800,275,825,275,800,825,225,275,800,825,225,275,800,275,800,275;
* 20;61;DEBUG;Pulses=58;Pulses(uSec)=200,875,800,250,800,225,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,200,875,200,875,825,250,200,875,200,875,200,875,825,250,200,875,825,250,200,875,200,875,200,875,825,225,825,250,200,875,825,250,200,875,150;
* 20;3E;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,875,275,225,950,225,950,875,275,225,950,225,950,875,275,875,275,225,950,875,275,225,950,225,950,875,275,875,275,225,950,225,950,225,950,875,275,875,275,200,950,225,950,875,275,875,275,225,950,875,275,225,950,225;
* 20;3F;DEBUG;Pulses=64;Pulses(uSec)=525,250,200,900,200,4900,200,900,200,900,875,275,225,950,225,950,875,275,225,950,225,950,875,275,875,275,225,950,900,250,225,950,225,950,875,250,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,875,275,875,275,225,950,875,250,225,950,225;
* 20;40;DEBUG;Pulses=130;Pulses(uSec)=225,175,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
* 20;41;DEBUG;Pulses=126;Pulses(uSec)=225,200,125,1250,150,200,150,1250,150,175,150,1250,150,175,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1300,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,1275,150,225,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
* 20;42;DEBUG;Pulses=116;Pulses(uSec)=175,1275,150,1225,150,200,150,200,150,200,150,1250,150,1250,150,1300,150,1275,150,200,150,200,150,200,150,1275,150,1300,150,1300,150,1300,150,225,150,1300,150,225,150,225,150,1300,150,1300,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,225,150,1300,150,1300,150,225,150,1300,150,200,150,200,150,200,150,1275,150,1300,150,1300,150,1300,150,200,150,200,150,200,150,1300,150,1300,150,1300,150,1300,150,200,150,200,150,1275,150,225,150,1275,150,1300,150;
20;CC;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,900,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,875,250,225,950,225;
20;CD;DEBUG;Pulses=64;Pulses(uSec)=525,250,200,900,200,4900,225,900,200,925,875,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,900,250,225,950,225;
20;CE;DEBUG;Pulses=130;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,200,150,1300,150,200,175,1300,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,200,175,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
20;CF;DEBUG;Pulses=126;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,175,1300,150,1275,150,200,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
20;D0;DEBUG;Pulses=116;Pulses(uSec)=275,1250,150,1250,150,200,150,200,150,200,150,1250,150,1250,150,1300,150,1300,150,200,150,200,150,200,150,1300,150,1275,150,1300,150,1300,150,200,150,1300,150,200,150,200,150,1300,150,1300,150,1275,150,200,150,1275,150,225,150,1275,150,1300,150,225,150,1300,150,200,150,200,150,225,150,1300,150,1300,150,200,175,1275,175,200,150,200,150,200,150,1300,150,1275,150,1300,150,1275,175,200,150,200,150,200,150,1300,150,1300,150,1300,150,1275,150,200,150,200,175,1300,150,200,150,1300,150,1300,150;
20;D1;HomeEasy;ID=7a75a347;SWITCH=0b;CMD=ALLON;
20;D2;DEBUG;Pulses=50;Pulses(uSec)=3200,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,900,275,875,300,875,300,875,925,250,300,875,300,875,300,875,925,250,300,875,925,250,300,875,300,875,300;
20;D3;Kaku;ID=5f;SWITCH=20;CMD=OFF;
20;D4;DEBUG;Pulses=50;Pulses(uSec)=3150,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,925,250,300,875,300,875,300,875,900,250,300,875,925,250,300,875,300,875,300;
20;D5;Kaku;ID=5f;SWITCH=20;CMD=OFF;
20;CC;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,900,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,875,250,225,950,225;
20;86;DEBUG;Pulses=58;Pulses(uSec)=250,4500,225,800,225,800,825,200,225,800,225,800,825,200,225,800,225,800,825,200,825,200,225,800,825,200,225,825,225,800,825,200,825,200,225,800,225,825,225,800,825,200,825,200,225,800,225,825,825,200,825,200,225,800,825,200,225;
300,4500,225,800,225,825,825,200,225,800,225,800,825,200,825,200,225,800,825,200,225,800,825,200,825,200,825,200,225,800,825,200,825,200,825,200,225,825,225,800,825,200,825,200,225,800,225,825,225,800,225,800,825,200,825,200,225;
00010011010111011100110000110
0010010010100011111101011110
20;D5;DEBUG;Pulses=364;Pulses(uSec)=
250,4875,200,900,200,900,875,275,200,900,200,900,875,275,200,900,875,250,225,900,875,275,875,250,225,900,200,925,200,925,200,900,875,250,850,250,225,925,875,250,875,250,225,900,850,275,200,900,875,250,225,900,875,250,875,250,225,900,
200,4875,200,900,225,900,850,250,200,900,225,900,850,275,200,900,875,250,225,900,875,275,850,250,200,900,200,900,200,925,200,900,875,250,875,250,200,925,850,250,875,275,200,900,875,275,200,900,875,250,225,900,875,250,850,250,200,900,
200,4875,200,900,225,900,875,275,200,925,200,900,875,275,200,900,875,250,225,900,875,275,850,275,200,925,200,900,225,925,200,900,875,250,875,250,225,925,875,250,875,250,225,900,875,275,200,900,850,275,200,900,875,250,850,250,200,900,
200,4875,200,900,225,925,850,250,225,900,200,900,850,275,225,900,850,275,200,900,875,275,875,250,200,900,225,900,200,925,200,900,875,250,875,250,225,925,850,250,875,250,225,900,875,250,225,900,875,250,200,900,875,250,875,250,200,925,
150,2650,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1225,150,200,150,1225,150,200,150,1250,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,1225,150,225,150,1225,150,200,150,200,150,1250,150,1225,150,200,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1225,150,200,150,1250,150,200,150,1225,150,200,150,1225,150,200,150,1250,150,200,150,1250,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,1225,150,200,150;
\*********************************************************************************************/
#define FA500RM3_PulseLength 26
#define FA500RM1_PulseLength 58
#define FA500_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_012
boolean Plugin_012(byte function, char *string) {
if (RawSignal.Number!=(FA500RM3_PulseLength) && RawSignal.Number!=(FA500RM1_PulseLength)) return false;
byte type=0; // 0=KAKU 1=ITK 2=PT2262
byte housecode=0;
byte unitcode=0;
byte command=0;
unsigned long bitstream=0L;
unsigned long address=0L;
// ==========================================================================
if (RawSignal.Number==(FA500RM3_PulseLength) ) {
// get all 26pulses =>24 manchester bits => 12 actual bits
type=0;
for(byte x=2;x <=FA500RM3_PulseLength-2;x+=2) { // Method 3
if(RawSignal.Pulses[x] > FA500_PULSEMID) {
bitstream = (bitstream << 1) | 0x1;
} else {
bitstream = (bitstream << 1);
}
}
} else {
// get all 58pulses =>28 bits
type=1;
for(byte x=1;x <=FA500RM1_PulseLength-2;x+=2) { // method 1
if(RawSignal.Pulses[x] > FA500_PULSEMID) {
bitstream = (bitstream << 1) | 0x1;
} else {
bitstream = (bitstream << 1);
}
}
}
//==================================================================================
// perform sanity checks
if (bitstream==0) return false; // no bits detected?
if (type == 0) {
housecode=(((bitstream) >> 8) &0x0f);
unitcode=(( bitstream >> 1)& 0x7F);
if (unitcode != 0x0A) { // invalid housecode?
return false;
}
address=housecode;
command=(bitstream)&1;
} else {
// 001001 0010100011111101 0111 10
// ^^^^^^ ^^
address=bitstream;
address=address >> 22;
address=address << 2;
housecode=(bitstream)&3;
address=address+housecode;
// sort buttons based on first 6 bits and last 2 bits
if (address==0x26) { // A On/off
housecode=1;
} else
if (address==0x25) { // B On/off
housecode=4;
} else
if (address==0xe5) { // C On/off
housecode=5;
} else
if (address==0x66) { // D On/off
housecode=0;
} else {
return false;
}
command=2; // initialize to "unknown"
// Trick: here we use the on/off command from the other packet type as it is not detected in the current packet, it was passed via Pluses[0] in plugin 1
if (RawSignal.Pulses[0]*RawSignal.Multiply > 1000 && RawSignal.Pulses[0]*RawSignal.Multiply < 1400) {
command=0;
} else
if (RawSignal.Pulses[0]*RawSignal.Multiply > 100 && RawSignal.Pulses[0]*RawSignal.Multiply < 400) {
command=1;
}
address=bitstream;
}
if (command > 1) {
//Serial.println("FA500R error3");
return false;
}
if (housecode != 0x01 && housecode != 0x04 && housecode != 0x05 && housecode != 0x00) { // invalid button code?
//Serial.println("FA500R error4");
return false;
}
//==================================================================================
// if (housecode == 1) housecode = 0x41; // A 0001 0001010 0/1 08 A 1
// if (housecode == 4) housecode = 0x42; // B 0100 0001010 0/1 20 B 4
// if (housecode == 5) housecode = 0x43; // C 0101 0001010 0/1 28 C 5
// if (housecode == 0) housecode = 0x44; // D 0000 0001010 0/1 00 D 0
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("FA500;")); // Label
if (type == 0) {
sprintf(pbuffer, "ID=%02x%02x;", unitcode, housecode); // ID
} else {
sprintf(pbuffer, "ID=%08lx;",(address) ); // ID
}
Serial.print( pbuffer );
if (type == 0) {
sprintf(pbuffer, "SWITCH=%02x%02x;", unitcode, housecode); // ID
} else {
sprintf(pbuffer, "SWITCH=%02x;", housecode); // ID
}
Serial.print( pbuffer );
Serial.print(F("CMD="));
if ( command == 1) {
Serial.print(F("ON;"));
} else
if ( command == 0) {
Serial.print(F("OFF;"));
} else {
Serial.print(F("UNKOWN;"));
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
return true;
}
#endif //PLUGIN_012
#ifdef PLUGIN_TX_012
void Flamingo_Send(int funitc, int fcmd);
boolean PluginTX_012(byte function, char *string) {
boolean success=false;
//10;FA500;001b523;D3;ON;
//012345678901234567890123
if (strncasecmp(InputBuffer_Serial+3,"FA500;",6) == 0) { // FA500 Command
if (InputBuffer_Serial[16] != ';') return false;
unsigned long bitstream=0L;
byte Home=0;
byte c;
InputBuffer_Serial[7]=0x30;
InputBuffer_Serial[8]=0x78;
bitstream=str2int(InputBuffer_Serial+7); // get address
c=tolower(InputBuffer_Serial[17]); // 1..5
if(c>='1' && c<='5'){Home=Home+c-'0';}
c=0;
c |= str2cmd(InputBuffer_Serial+20)==VALUE_OFF; // ON/OFF command
Flamingo_Send(bitstream, c);
success=true;
}
return success;
}
void Flamingo_Send(int fbutton, int fcmd) {
int fpulse = 350; // Pulse witdh in microseconds
int fretrans = 9; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;
uint32_t fsendbuff;
uint32_t fsendbuff1;
uint32_t fsendbuff2;
uint32_t fsendbuff3;
uint32_t fsendbuff4;
if (fcmd == 0) { // OFF
fsendbuff1=0x24D319A0; // A Off
fsendbuff2=0x246008E0;
fsendbuff3=0x26BB9860;
fsendbuff4=0x26D4BFA0;
//fsendbuff1=0xD86E6650;
//fsendbuff2=0xDABDF710;
//fsendbuff3=0xDA42A790;
//fsendbuff4=0xDA614050;
} else { // ON
fsendbuff1=0x2561B560; // A On
fsendbuff2=0x24A3F5E0;
fsendbuff3=0x27B27B60;
fsendbuff4=0x24543A20;
//fsendbuff1=0xD97A4A10;
//fsendbuff2=0xDA9A8490;
//fsendbuff3=0xDB58C5D0;
//fsendbuff4=0xDBF40A90;
}
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat < fretrans; nRepeat++) {
if (nRepeat %4 ==0 ) fsendbuff=fsendbuff1;
if (nRepeat %4 ==1 ) fsendbuff=fsendbuff2;
if (nRepeat %4 ==2 ) fsendbuff=fsendbuff3;
if (nRepeat %4 ==3 ) fsendbuff=fsendbuff4;
Serial.println(fsendbuff,HEX);
// send SYNC 1P High, 15P low
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 15);
// end send SYNC
// Send command
for (int i = 0; i < 28; i++) { // Flamingo command is only 28 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
}
//digitalWrite(PIN_RF_TX_DATA, LOW);
//delayMicroseconds(fpulse * 15);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
RFLinkHW();
}
#endif //PLUGIN_TX_012

276
Plugins/Plugin_013.c Normal file
View File

@@ -0,0 +1,276 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-13: Powerfix RCB-i 3600 ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the Powerfix RCB-i 3600 protocol
* Works with: Powerfix RCB-i 3600 - 4 power outlets and a remote, Quigg GT7000
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical information:
* Partially based on http://wiki.pilight.org/doku.php/quigg_switch_gt_7000_v7_0
*
* The Powerfix/Chacon RF packets are 42 pulses long resulting in 20 bits data packets
*
* 0000 1000 0000 000 1 0 0 0 1
* AAAA AAAA AAAA BBC D E F G H
*
* A = 12 bits address (Chacon:0000 0000 0000 Powerfix:0000 1000 0000)
* B = 2 bits Unit code (bits reversed)
* C = Group Command (to all devices)
* D = State (ON/OFF/DIM UP/DIM DOWN)
* E = Dim command (1=dim/bright command)
* F = always 0
* G = Parity bit calculated over command bits (BCDEFH)
* H = unknown, copy of D (state)
*
* -------------------------------------------
* Powerfix:
* 0000 1000 0000 000 1 0 0 0 1 1 on
* 0000 1000 0000 000 0 0 0 0 0 1 off
* 0000 1000 0000 100 1 0 0 1 1 2 on
* 0000 1000 0000 100 0 0 0 1 0 2 off
* 0000 1000 0000 010 1 0 0 0 0 3 on
* 0000 1000 0000 010 0 0 0 0 1 3 off
* 0000 1000 0000 110 1 0 0 1 0 4 on
* 0000 1000 0000 110 0 0 0 1 1 4 off
* 0000 1000 0000 111 0 0 0 0 1 all off
* 0000 1000 0000 111 1 0 0 0 0 all on
* 0000 1000 0000 111 1 1 0 1 0 dim
* 0000 1000 0000 111 0 1 0 1 1 bright
* -------------------------------------------
* Chacon:
* 0000 0000 0000 000 1 0 0 0 1 1 ON
* 0000 0000 0000 000 0 0 0 0 0 1 OFF
* 0000 0000 0000 100 1 0 0 1 1 2 ON
* 0000 0000 0000 100 0 0 0 1 0 2 OFF
* 0000 0000 0000 010 1 0 0 0 0 3 ON
* 0000 0000 0000 010 0 0 0 0 1 3 OFF
* 0000 0000 0000 110 1 0 0 1 0 4 ON
* 0000 0000 0000 110 0 0 0 1 1 4 OFF
* 0000 0000 0000 111 1 0 0 0 0 All ON
* 0000 0000 0000 111 0 0 0 0 1 All OFF
* 0000 0000 0000 111 1 1 0 1 0 All DIM
* 0000 0000 0000 111 0 1 0 1 1 All Bright
* -------------------------------------------
* Sample Powerfix:
* 20;10;DEBUG;Pulses=42;Pulses(uSec)=630,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1200,540,1200,570,1170,1230,540,570,1200,540,1200,540,1170,1230,540,6990;
*
* BUTTON: DIM
* 20;05;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1250,625,1225,625,1250,1275,575,600,1250,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,1300,575,1300,575,1300,575,1300,600,1300,550,625,1225,1300,550,625,1175;
* 00101010110010101010101011010101010011001
* BUTTON: BRIGHT
* 20;12;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,600,1250,600,1250,600,1250,1275,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,550,1300,575,1300,550,625,1250,1300,550,625,1225,1300,575,1300,525;
* 00101010110010101010101011010100110011010
* BUTTON: ALL OFF
* 20;18;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1250,1275,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,1300,575,1300,550,1300,550,625,1250,650,1200,625,1225,650,1225,1300,500;
* 00101010110010101010101011010100101010110
* BUTTON: ALL ON
* 20;15;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,600,1250,625,1225,625,1225,1275,575,625,1225,625,1225,625,1250,625,1225,650,1200,625,1225,625,1225,1300,550,1300,575,1300,550,1300,575,650,1225,625,1225,625,1225,625,1175;
* 00101010110010101010101011010101001010101
* BUTTON: 1 ON
* 20;04;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1225,1300,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,1300,575,625,1225,625,1225,625,1225,1300,500;
* 0101010110010101010101010101011001010110
* BUTTON: 1 OFF
* 20;07;DEBUG;Pulses=42;Pulses(uSec)=600, 600,1250,600,1250,625,1250,625,1225,1275,575,625,1225,600,1250,625,1275,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1175;
* 0101010110010101010101010101010101010101
* BUTTON: 2 ON
* 20;0A;DEBUG;Pulses=42;Pulses(uSec)=575,600,1250,625,1225,625,1225,625,1225,1300,550,625,1225,625,1225,625,1275,625,1225,625,1225,625,1225,625,1225,1300,550,625,1225,625,1225,1300,575,625,1225,625,1225,1300,575,1300,500;
* 0101010110010101010101011001011001011010
* BUTTON: 2 OFF
* 20;0D;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1250,1300,550,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,575,625,1225,625,
1225,625,1250,625,1225,650,1225,1300,550,625,1175;
* 0101010110010101010101011001010101011001
\*********************************************************************************************/
#define POWERFIX_PulseLength 42
#define POWEFIX_PULSEMID 900/RAWSIGNAL_SAMPLE_RATE
#define POWEFIX_PULSEMIN 450/RAWSIGNAL_SAMPLE_RATE
#define POWEFIX_PULSEMAX 1400/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_013
boolean Plugin_013(byte function, char *string) {
if (RawSignal.Number!= POWERFIX_PulseLength) return false;
unsigned long bitstream=0L;
unsigned int address=0;
byte unitcode=0;
byte button=0;
byte command=0;
byte parity=0;
byte bitcount=0;
// ==========================================================================
if (RawSignal.Pulses[1] > POWEFIX_PULSEMID) return false; // start pulse must be short
for (byte x=2;x<POWERFIX_PulseLength-1;x+=2) {
if (RawSignal.Pulses[x] > POWEFIX_PULSEMID) {
if (RawSignal.Pulses[x] > POWEFIX_PULSEMAX) return false; // Long pulse too long
if (RawSignal.Pulses[x+1] > POWEFIX_PULSEMID) return false; // pulse sequence check 01/10
bitstream = (bitstream << 1) | 0x1;
if (bitcount > 11) parity=parity^1;
} else {
if (RawSignal.Pulses[x] < POWEFIX_PULSEMIN) return false; // Short pulse too short
if (RawSignal.Pulses[x+1] < POWEFIX_PULSEMID) return false; // pulse sequence check 01/10
bitstream = (bitstream << 1);
}
bitcount++;
}
//==================================================================================
// Perform Sanity Checks
if (parity != 0) return false; // Parity check
if (((bitstream)&0x4) == 4) return false; // Tested bit should always be zero
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || (RepeatingTimer<millis()+1500) || SignalCRC != bitstream ) {
// not seen the RF packet recently
SignalCRC=bitstream;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Sort data
address=((bitstream)>>8); // 12 bits address
unitcode=((bitstream >> 6)& 0x03);
if (unitcode==2) button=1; // bits are simply reversed
if (unitcode==1) button=2;
if (unitcode==3) button=3;
parity=((bitstream)&0x3f); // re-use parity variable
command=((parity)>>4)&0x01; // On/Off command
if (((parity)&0x08) == 0x08) { // dim command
command=command+2;
} else {
if (((parity)&0x20) == 0x20) { // group command
command=command+4;
}
}
//==================================================================================
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Powerfix;")); // Label
sprintf(pbuffer, "ID=%04x;", address); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", button); // ID
Serial.print( pbuffer );
Serial.print(F("CMD="));
if ( command == 0) {
Serial.print(F("OFF;"));
} else
if ( command == 1) {
Serial.print(F("ON;"));
} else
if ( command == 2) {
Serial.print(F("BRIGHT;"));
} else
if ( command == 3) {
Serial.print(F("DIM;"));
} else
if ( command == 4) {
Serial.print(F("ALLOFF;"));
} else
if ( command == 5) {
Serial.print(F("ALLON;"));
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_013
#ifdef PLUGIN_TX_013
void Powerfix_Send(unsigned long bitstream);
boolean PluginTX_013(byte function, char *string) {
boolean success=false;
//10;POWERFIX;000080;0;ON;
//012345678901234567890123
if (strncasecmp(InputBuffer_Serial+3,"POWERFIX;",9) == 0) {
if (InputBuffer_Serial[18] != ';') return success;
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78;
InputBuffer_Serial[18]=0x00; // Get address from hexadecimal value
unsigned long bitstream=0L; // Main placeholder
byte command=0;
byte c;
// -------------------------------
bitstream=str2int(InputBuffer_Serial+10); // Address, first 12 bits of the 20 bits in total
bitstream=(bitstream)<<8; // shift left so that we can add the 8 command bits
// -------------------------------
byte temp=str2int(InputBuffer_Serial+19);// button/unit number (0..3)
if (temp==1) command=0x82;
if (temp==2) command=0x40;
if (temp==3) command=0xc2;
// -------------------------------
c=0;
c = str2cmd(InputBuffer_Serial+21); // ON/OFF command
if (c == VALUE_ON) {
command=command | 0x10; // turn "on" bit for on command
} else {
if (c == VALUE_ALLOFF) { // set "all off" bits
command=0xe0;
} else
if (c == VALUE_ALLON) {
command=0xf0; // set "all on" bits
}
}
// not supported yet..
// dim: command=0xfa
// bright: command=0xea;
// -------------------------------
bitstream=bitstream+command;
// -------------------------------
Powerfix_Send(bitstream); // bitstream to send
success=true;
}
return success;
}
#define PLUGIN_013_RFLOW 650
#define PLUGIN_013_RFHIGH 1300
void Powerfix_Send(unsigned long bitstream) {
RawSignal.Repeats=7; // Number of RF packet retransmits
RawSignal.Delay=20; // Delay between RF packets
RawSignal.Number=42; // Length
uint32_t fdatabit;
uint32_t fdatamask = 0x80000;
byte parity=1; // to calculate the parity bit
// -------------------------------
RawSignal.Pulses[1]=PLUGIN_013_RFLOW/RawSignal.Multiply; // start pulse
for (byte i=2; i<40; i=i+2) { // address and command bits
fdatabit = bitstream & fdatamask; // Get most left bit
bitstream = (bitstream << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
RawSignal.Pulses[i] = PLUGIN_013_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_013_RFHIGH/RawSignal.Multiply;
} else { // Write 1
parity=parity^1;
RawSignal.Pulses[i] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
RawSignal.Pulses[i+1]= PLUGIN_013_RFLOW/RawSignal.Multiply;
}
}
// parity
if (parity == 0) { // Write 0
RawSignal.Pulses[40] = PLUGIN_013_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[41] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
} else { // Write 1
RawSignal.Pulses[40] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
RawSignal.Pulses[41] = PLUGIN_013_RFLOW/RawSignal.Multiply;
}
RawSendRF();
}
#endif // PLUGIN_TX_013

147
Plugins/Plugin_014.c Normal file
View File

@@ -0,0 +1,147 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-14: Ikea Koppla ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the Ikea Koppla protocol
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical information:
* Packets are variable length as zero bits are 2 pulses and 1 bits are single pulses.
* Pulse lengths are ~1600 for a 0 bit and two times ~750 for a 1 bit
* Packets contain 28 bits
*
* AAAA BBBB CCCCCCCCCC DD EEEEEE FF
* 1110 0011 0000000001 01 000010 01 on
* 1110 0011 0000000001 01 010110 01 off
* 1110 1111 1111111111 00 001110 10 Pair
*
* A = Preamble, Always '1110'
* B = System code 0-0x0f
* C = Unit code bit selection, order: ch10,1,2,3,4,5,6,7,8,9
* D = Checksum on B
* E = Level and Fade
* F = Checksum on D
*
* Sample:
* 20;07;DEBUG;Pulses=38;Pulses(uSec)=825,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,750,1600,775,750,1625,1600,1625,1600,775,750,1625,1600,775,750;
* 20;08;DEBUG;Pulses=40;Pulses(uSec)=925,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,775,1600,775,750,1625,750,750,1625,775,750,775,750,1625,1600,750,750;
\*********************************************************************************************/
#define KOPPLA_PulseLength_MIN 36
#define KOPPLA_PulseLength_MAX 52
#define KOPPLA_PULSEMID 1300/RAWSIGNAL_SAMPLE_RATE
#define KOPPLA_PULSEMAX 1850/RAWSIGNAL_SAMPLE_RATE
#define KOPPLA_PULSEMIN 650/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_014
boolean Plugin_014(byte function, char *string) {
if ((RawSignal.Number < KOPPLA_PulseLength_MIN) || (RawSignal.Number > KOPPLA_PulseLength_MAX) ) return false;
unsigned long bitstream=0L;
byte preamble=0;
unsigned int sysunit=0;
byte levelfade=0;
byte command=0;
byte level=0;
int i=0;
byte checksum1=0;
byte checksum2=0;
byte checksum=0x03;
byte tempcrc=0;
// ==========================================================================
for (byte x=1;x < RawSignal.Number;x++) {
if (RawSignal.Pulses[x] > KOPPLA_PULSEMID) { // long pulse, 0 bit
if (RawSignal.Pulses[x] > KOPPLA_PULSEMAX) return false; // long pulse is too long
bitstream = (bitstream << 1); // 0 bit
} else { // Short pulse
if (RawSignal.Pulses[x] < KOPPLA_PULSEMIN) return false; // short pulse is too short
if (RawSignal.Pulses[x+1] > KOPPLA_PULSEMID) return false; // need 2 short pulses for a 1 bit
if (RawSignal.Pulses[x+1] < KOPPLA_PULSEMIN) return false; // second short pulse is too short
x++; // skip second short pulse
bitstream = (bitstream << 1) | 0x1; // 1 bit
}
}
//==================================================================================
// Sort data and perform sanity checks
//==================================================================================
if (bitstream==0) return false; // No bits detected?
if ((((bitstream) >> 24)&0x0f) != 0x0e) return false; // Preamble should always be '1110'
sysunit=(((bitstream) >> 10)& 0x03fff); // 4 bits system code and 10 bits unit code
checksum1=(((bitstream) >> 8) &0x03); // first checksum
levelfade=(((bitstream) >> 2)& 0x3f); // 6 bits level and face code
checksum2=((bitstream)&0x03); // second checksum
// calculate checksum 1
checksum=3;
for (i=0;i<7;i++) {
tempcrc=((sysunit) >> (i*2)) & 3;
checksum=checksum ^ tempcrc;
}
if (checksum1 != checksum) return false;
// calculate checksum 2
checksum=3;
for (i=0;i<3;i++) {
tempcrc=((levelfade) >> (i*2)) & 3;
checksum=checksum ^ tempcrc;
}
if (checksum2 != checksum) return false;
// sort command / dim bits
if ((levelfade) == 0x2) { // on
command=1;
} else
if ((levelfade) == 0x16) { // off
command=0;
} else
if ((levelfade) == 0x0) { // up
command=2;
} else
if ((levelfade) == 0x4) { // down
command=3;
} else {
command=4;
for (i=2;i<6;i++) {
level=level<<1;
level=level | ((levelfade)>>i)&0x01;
}
}
//==================================================================================
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Ikea Koppla;")); // Label
sprintf(pbuffer, "ID=%04x;", sysunit); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", levelfade); // ID
Serial.print( pbuffer );
Serial.print(F("CMD="));
if ( command == 0) {
Serial.print(F("OFF;"));
} else
if ( command == 1) {
Serial.print(F("ON;"));
} else
if ( command == 2) {
Serial.print(F("BRIGHT;"));
} else
if ( command == 3) {
Serial.print(F("DIM;"));
} else {
sprintf(pbuffer, "SET_LEVEL=%d;", level );
Serial.print( pbuffer );
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_014

270
Plugins/Plugin_015.c Normal file
View File

@@ -0,0 +1,270 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-15: HomeEasy EU ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst en verzending HomeEasy EU zenders
* die werken volgens de automatische codering (Ontvangers met leer-knop)
*
* LET OP: GEEN SUPPORT VOOR DIRECTE DIMWAARDES!!!
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technische informatie:
* Analyses Home Easy Messages and convert these into an eventcode
* Only new EU devices with automatic code system are supported
* Only On / Off status is decoded, no DIM values
* Only tested with Home Easy HE300WEU transmitter, doorsensor and PIR sensor
* Home Easy message structure, by analyzing bitpatterns so far ...
* AAAAAAAAAAA BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB CCCC DD EE FFFFFF G
* 11000111100 10111100011101110010001111100011 1100 10 11 000111 1 HE301EU ON
* 11000111100 10111100011101110010001111100011 1100 01 11 000111 1 HE301EU OFF
* 11000111100 1001 01 11 001011 HE842/844 ON
* 11000111100 01111010011100110010001011000111 1000 11 11 001011 0000000 HE842/844 OFF
* 1000 10 11 000111 HE844 ALLON;
* 1000 01 11 000111 HE844 ALLOFF;
* 11000111100 01111000111101100110010011000111 1000 11 11 000111 0000000
*
* A = Startbits/Preamble,
* B = Address, 32 bits
* C = Unknown, Possibly: Device type
* D = Command, 1 bit only?
* E = Group indicator
* F = Channel 0-15
* G = Stopbit
*
* SAMPLE:
* Pulses=116;Pulses(uSec)=200,1175,125,1175,125,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,150,200,125,1175,150,1175,150,1175,125,1175,150,200,125,200,150,1175,125,1175,150,200,125,1175,125,1175,150,200,150,200,150,1175,150,200,150,1175,150,200,150,1175,150,200,150,200,125,1175,150,200,125,1175,150,1175,125,1175,150,200,125,200,125,200,150,200,125,1175,150,1175,150,1175,150,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,125,1175,125,200,125,1175,150,1150,125;
* HE preamble: 11000111100 (63C) Address: 1111001101100101010010111000011 (79B2A5C3) Stopbits: 0 (0) Commands: 10001111001011 Command: 0 Channel: 1011 Group: 1
* 20;04;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLOFF;
*
* Preamble 200,1175,125,1175,125,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,
* Address 150,200,125,1175,150,1175,150,1175,125,1175,150,200,125,200,150,1175,125,1175,150,200,125,1175,125,1175,150,200,150,200,150,1175,150,200,150,1175,150,200,150,1175,150,200,150,200,125,1175,150,200,125,1175,150,1175,125,1175,150,200,125,200,125,200,150,200,125,1175,150,1175,
* Command 150,1175,150,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,125,1175,125,200,125,1175,150,1150, - 125;
\*********************************************************************************************/
#define HomeEasy_PulseLength 116
#define HomeEasy_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_015
boolean Plugin_015(byte function, char *string) {
if (RawSignal.Number != HomeEasy_PulseLength) return false;
unsigned long preamble = 0L;
unsigned long address = 0L;
unsigned long bitstream = 0L;
byte rfbit =0;
byte command = 0;
byte group = 0;
byte channel = 0;
byte type = 0;
byte temp = 0;
RawSignal.Pulses[0]=0; // undo any Home Easy to Kaku blocking that might be active
//==================================================================================
// convert pulses into bit sections (preamble, address, bitstream)
for(byte x=1;x<=HomeEasy_PulseLength;x=x+2) {
if ((RawSignal.Pulses[x] < HomeEasy_PULSEMID) && (RawSignal.Pulses[x+1] > HomeEasy_PULSEMID))
rfbit = 1;
else
rfbit = 0;
if ( x<=22) preamble = (preamble << 1) | rfbit; // 11 bits preamble
if ((x>=23) && (x<=86)) address = (address << 1) | rfbit; // 32 bits address
if ((x>=87) && (x<=114)) bitstream = (bitstream << 1) | rfbit; // 15 remaining bits
}
//==================================================================================
// To prevent false positives make sure the preamble is correct, it should always be 0x63c
// We compare only 10 bits to compensate for the first bit being seen incorrectly by some receiver modules
if ((preamble & 0x3ff) != 0x23c) return false; // comparing 10 bits is enough to make sure the packet is valid
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if(SignalHash!=SignalHashPrevious || (RepeatingTimer<millis()+1500) || SignalCRC != bitstream ) {
// not seen the RF packet recently
SignalCRC=bitstream;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
type = ((bitstream >> 12) & 0x3); // 11b for HE301
channel = (bitstream) & 0x3f;
if (type==3) { // HE301
command = ((bitstream >> 8) & 0x1); // 0=on 1=off (both group and single device)
group = ((bitstream >> 7) & 0x1); // 1=group
} else { // HE800 21c7 = off 22c7=on
temp = ((bitstream >> 8) & 0x7); // 1=group
if (temp < 3) group=1;
command = ((bitstream >> 9) & 0x1); // 0=off 1=on
if (group==1) command=(~command)&1; // reverse bit for group: 1=group off 0=group on
}
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("HomeEasy;"); // Label
sprintf(pbuffer, "ID=%08lx;",(address) ); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", channel);
Serial.print( pbuffer );
strcpy(pbuffer,"CMD=");
if ( group == 1) {
strcat(pbuffer,"ALL");
}
if ( command == 1) {
strcat(pbuffer,"OFF;");
} else {
strcat(pbuffer,"ON;");
}
Serial.print( pbuffer );
Serial.println();
// ----------------------------------
RawSignal.Repeats = true;
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_015
#ifdef PLUGIN_TX_015
void HomeEasyEU_Send(unsigned long address, unsigned long command);
boolean PluginTX_015(byte function, char *string) {
boolean success=false;
//10;HomeEasy;7900b200;b;ON;
//10;HomeEasy;d900ba00;23;OFF;
//10;HomeEasy;79b2a5c3;b;ON;
//10;HomeEasy;7a7322c7;b;ON;
//01234567890123456789012345
if (strncasecmp(InputBuffer_Serial+3,"HOMEEASY;",9) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[20] != ';') return false;
unsigned long bitstream = 0L;
unsigned long commandcode = 0L;
byte cmd=0;
byte group=0;
// ------------------------------
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78;
InputBuffer_Serial[20]=0x00;
bitstream=str2int(InputBuffer_Serial+10); // Get Address from hexadecimal value
// ------------------------------
InputBuffer_Serial[19]=0x30;
InputBuffer_Serial[20]=0x78; // Get home from hexadecimal value
commandcode=str2int(InputBuffer_Serial+19); // Get Button number
// ------------------------------
if (InputBuffer_Serial[23] == ';') { // Get command
cmd=str2cmd(InputBuffer_Serial+24);
} else {
cmd=str2cmd(InputBuffer_Serial+23);
}
if (cmd == VALUE_OFF) cmd = 0; // off
if (cmd == VALUE_ON) cmd = 1; // on
if (cmd == VALUE_ALLON) {cmd = 1; group=1;} // allon
if (cmd == VALUE_ALLOFF){cmd = 0; group=1;} // alloff
// ------------------------------
commandcode=commandcode & 0x3f; // get button number
if (group == 1) { // HE8xx: 21xx/22xx HE3xx: 31xx/32xx (off/on) (HE3xx code works for HE8xx)
commandcode=commandcode | 0x30C0; // group
if (cmd == 1) {
commandcode=(commandcode & 0xfdff) | 0x200; // group on > 32cx
} else {
commandcode=commandcode | 0x100; // group off > 31cx
}
} else { // HE8xx: 23cx/25cx HE3xx: 2D4x/2E4x (off/on) (HE3 code works for HE8xx)
commandcode=commandcode | 0x2040; // non-group
if (cmd == 1) {
commandcode=(commandcode & 0xfdff) | 0xe00; // On > 2ECx
} else {
commandcode=commandcode | 0xd00; // Off > 2DCx
}
}
//-----------------------------------------------
HomeEasyEU_Send(bitstream, commandcode);
success=true;
}
return success;
}
void HomeEasyEU_Send(unsigned long address, unsigned long command) {
int fpulse = 275; // Pulse witdh in microseconds
int fretrans = 5; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
// -------------- Send Home Easy preamble (0x63c) - 11 bits
fsendbuff=0x63c;
fdatamask=0x400;
for (int i = 0; i < 11; i++) { // Preamble
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 5);
}
}
// -------------- Send Home Easy device Address
fsendbuff=address;
fdatamask=0x80000000;
// Send Address - 32 bits
for (int i = 0; i < 32;i++){ //28;i++){
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 5);
}
}
// -------------- Send Home Easy command bits - 14 bits
fsendbuff=command; // 0xFF;
fdatamask=0x2000;
for (int i = 0; i < 14; i++) {
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 5);
}
}
// -------------- Send stop
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 26);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
RFLinkHW();
}
#endif // PLUGIN_TX_015

261
Plugins/Plugin_030.c Normal file
View File

@@ -0,0 +1,261 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-30 AlectoV1 ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the protocol used for outdoor sensors of the Alecto weather stations
* following protocol version 1
* This Plugin works at least with: Alecto WS3500, Silvercrest, Otio sht-10, Otio sht-20
* Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160
* Alecto WS4500, Ventus W044, Balance RF-WS105
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technische informatie:
* Message Format: (9 nibbles, 36 bits):
*
* Format for Temperature Humidity
* AAAAAAAA BBBB CCCC CCCC CCCC DDDDDDDD EEEE
* 00110110 1000 1011 0111 0000 00011100 0110
* RC Type Temperature___ Humidity Checksum
* A = Rolling Code (includes channel number on low 2 bits of nibble1 (10=ch1 01=ch2 11=ch3) )
* B = Message type (xyyx = temp/humidity if yy <> '11') => only accepting yy = 00 for negative temperatures for now
* 4 bits: bit 0 = battery state 0=OK, 1= below 2.6 volt
* bit 1&2 = 00/01/10 = temp/hum is transmitted, 11=non temp is transmitted
* bit 3 = 0=scheduled transmission, 1=requested transmission (button press)
* C = Temperature (two's complement)
* D = Humidity BCD format
* E = Checksum
*
* Sample:
* 20;F4;DEBUG;Pulses=74;Pulses(uSec)=450,1900,350,1900,350,3975,350,3975,350,1900,350,3975,350,3975,350,1900,350,3975,350,1900,350,1900,350,1900,350,3975,350,1900,350,3975,350,3975,350,1900,350,3975,350,3975,350,3975,350,1900,350,1900,350,1900,350,1900,350,1900,350,1900,350,1900,350,3975,350,3975,350,3975,350,1900,350,1900,350,1900,350,3975,350,3975,350,2025,350;
* 20;F5;Alecto V1;ID=006c;TEMP=00ed;HUM=38;
*
* Format for Rain
* AAAAAAAA BBBB CCCC DDDD DDDD DDDD DDDD EEEE
* 01100001 0110 1100 1010 1011 0010 0000 0010
* RC Type Rain Checksum
* A = Rolling Code
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
* C = fixed to 1100
* D = Rain (bitvalue * 0.25 mm)
* E = Checksum
*
* Sample:
* 20;A8;DEBUG;Pulses=74;Pulses(uSec)=550,1925,425,4100,425,4100,425,1975,425,1975,425,1975,425,1975,425,4100,400,2000,425,4100,425,4100,425,1975,425,4100,425,4100,425,1975,425,1975,425,4100,425,1975,425,4100,400,1975,425,4100,425,1975,425,4100,425,4100,425,1975,450,1975,425,4100,450,1950,450,1950,450,1950,425,1975,450,1950,450,1950,475,1925,500,4025,475,1950,475;
* 20;A9;Alecto V1;ID=0086;RAIN=04d5;
*
* Format for Windspeed
* AAAAAAAA BBBB CCCC CCCC CCCC DDDDDDDD EEEE
* RC Type Windspd Checksum
* A = Rolling Code
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
* C = Fixed to 1000 0000 0000
* D = Windspeed (bitvalue * 0.2 m/s, correction for webapp = 3600/1000 * 0.2 * 100 = 72)
* E = Checksum
*
* Format for Winddirection & Windgust
* AAAAAAAA BBBB CCCD DDDD DDDD EEEEEEEE FFFF
01110000 0000 1111 1011 0000 00000000 0101
* RC Type Winddir Windgust Checksum
* A = Rolling Code
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
* C = Fixed to 111x
* D = Wind direction 0-511 in 0.7 degree steps?
* E = Windgust (bitvalue * 0.2 m/s, correction for webapp = 3600/1000 * 0.2 * 100 = 72)
* F = Checksum
*
* Sample:
* 20;53;DEBUG;Pulses=74;Pulses(uSec)=425,3800,350,1825,350,1825,325,1825,350,1825,325,3800,350,3800,350,1825,325,3800,350,1825,325,1800,350,1825,350,1825,325,1825,325,3800,325,1825,350,1800,350,1825,325,3825,325,3800,325,1825,325,1825,325,1800,325,1825,350,3800,325,1825,325,3800,350,1800,350,1800,350,3800,350,1825,325,1825,325,1825,325,1825,350,1825,325,1925,325;
\*********************************************************************************************/
#define WS3500_PULSECOUNT 74
#ifdef PLUGIN_030
boolean Plugin_030(byte function, char *string) {
if (RawSignal.Number != WS3500_PULSECOUNT) return false;
unsigned long bitstream=0L;
byte nibble0=0;
byte nibble1=0;
byte nibble2=0;
byte nibble3=0;
byte nibble4=0;
byte nibble5=0;
byte nibble6=0;
byte nibble7=0;
byte checksum=0;
int temperature=0;
byte humidity=0;
unsigned int rain=0;
byte windspeed=0;
byte windgust=0;
int winddirection=0;
byte checksumcalc = 0;
byte rc=0;
byte battery=0;
//==================================================================================
for(byte x=2; x<=64; x=x+2) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 700) return false; // in between pulses should be short
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2560) {
bitstream = ((bitstream >> 1) |(0x1L << 31));
} else {
bitstream = (bitstream >> 1);
}
}
for(byte x=66; x<=72; x=x+2) {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2560) {
checksum = ((checksum >> 1) |(0x1L << 3));
} else {
checksum = (checksum >> 1);
}
}
//==================================================================================
if (bitstream == 0) return false; // Perform a sanity check
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+1000<millis()) && (SignalCRC != bitstream)) || (SignalCRC != bitstream) ) {
// not seen the RF packet recently
SignalCRC=bitstream;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Sort nibbles
nibble7 = (bitstream >> 28) & 0xf;
nibble6 = (bitstream >> 24) & 0xf;
nibble5 = (bitstream >> 20) & 0xf;
nibble4 = (bitstream >> 16) & 0xf;
nibble3 = (bitstream >> 12) & 0xf;
nibble2 = (bitstream >> 8) & 0xf;
nibble1 = (bitstream >> 4) & 0xf;
nibble0 = bitstream & 0xf;
//==================================================================================
// Perform checksum calculations, Alecto checksums are Rollover Checksums by design!
if ((nibble2 & 0x6) != 6) { // temperature packet
checksumcalc = (0xf - nibble0 - nibble1 - nibble2 - nibble3 - nibble4 - nibble5 - nibble6 - nibble7) & 0xf;
} else {
if ((nibble3 & 0x7) == 3) { // Rain packet
checksumcalc = (0x7 + nibble0 + nibble1 + nibble2 + nibble3 + nibble4 + nibble5 + nibble6 + nibble7) & 0xf;
} else { // Wind packet
checksumcalc = (0xf - nibble0 - nibble1 - nibble2 - nibble3 - nibble4 - nibble5 - nibble6 - nibble7) & 0xf;
}
}
if (checksum != checksumcalc) return false;
//==================================================================================
battery=(nibble2)&0x1; // get battery indicator
nibble2=(nibble2)&0x06; // prepare nibble to contain only the needed bits
nibble3=(nibble3)&0x07; // prepare nibble to contain only the needed bits
//==================================================================================
rc = bitstream & 0xff;
if ((nibble2) != 6) { // nibble 2 needs to be set to something other than 'x11x' to be a temperature packet
// Temperature packet
temperature = (bitstream >> 12) & 0xfff;
//fix 12 bit signed number conversion
if ((temperature & 0x800) == 0x800) {
if ((nibble2 & 0x6) != 0) return false; // reject alecto v4 on alecto v1... (causing high negative temperatures with valid checksums)
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
humidity = (16 * nibble7) + nibble6;
if (humidity > 0x99) return false; // Humidity out of range, assume ALL data is bad?
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V1;")); // Label
sprintf(pbuffer, "ID=%02x%02x;", (rc &0x03), (rc &0xfc) ); // ID is split into channel number and rolling code
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
if (humidity < 0x99) { // Some AlectoV1 devices actually lack the humidity sensor and always report 99%
sprintf(pbuffer, "HUM=%02x;", humidity); // Only report humidity when it is below 99%
Serial.print( pbuffer );
}
if (battery==0) {
Serial.print("BAT=OK;");
} else {
Serial.print("BAT=LOW;");
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
} else {
if ((nibble3) == 3) { // Rain packet
rain = ((bitstream >> 16) & 0xffff);
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V1;")); // Label
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "RAIN=%04x;", rain);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
if ((nibble3) == 1) { // windspeed packet
windspeed = ((bitstream >> 24) & 0xff);
windspeed = windspeed*72;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V1;")); // Label
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", windspeed);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
if ((nibble3) == 7) { // winddir packet
winddirection = ((bitstream >> 15) & 0x1ff) / 45; // ???
winddirection = winddirection & 0x0f;
windgust = ((bitstream >> 24) & 0xff);
windgust = windgust*72;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V1;")); // Label
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "WINDIR=%04d;", winddirection);
Serial.print( pbuffer );
sprintf(pbuffer, "WINGS=%04x;", windgust);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
}
return false;
}
#endif // PLUGIN_030

181
Plugins/Plugin_031.c Normal file
View File

@@ -0,0 +1,181 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-31 AlectoV3 ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren
* WS1100, WS1200, WSD-19
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technische informatie:
* Decodes signals from Alecto Weatherstation outdoor unit, type 3 (94/126 pulses, 47/63 bits, 433 MHz).
* WS1100 Message Format: (7 bits preamble, 5 Bytes, 40 bits):
* AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE
* Temperature Humidity Checksum
* A = start/unknown, first 8 bits are always 11111111
* B = Rolling code
* C = Temperature (10 bit value with -400 base)
* D = Checksum
* E = Humidity
*
* WS1200 Message Format: (7 bits preamble, 7 Bytes, 56 bits):
* AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF
* Temperature Rain LSB Rain MSB ???????? Checksum
* A = start/unknown, first 8 bits are always 11111111
* B = Rolling code
* C = Temperature (10 bit value with -400 base)
* D = Rain ( * 0.3 mm)
* E = ?
* F = Checksum
AAAAAAA AAAABBBB BBBBCCCC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF
1111111 00111010 01010010 10000010 00000000 00000000 11111111 10111010 1 24,2 gr 0 mm
1111111 00111010 01010010 10000010 00000001 00000000 11111111 11111100 0 24,2 gr 0,3 mm
1111111 00111010 01010010 10000010 00000010 00000000 11111111 00110110 0 24,2 gr 0,6 mm
1111111 00111010 01010010 10000010 00001000 00000000 11111111 11101000 1 24,2 gr 2,4 mm
1111111 00111010 01010010 10000010 00001101 00000000 11111111 10000111 0 24,2 gr 3.9 mm
1111111 00111010 01010010 01110001 00001101 00000000 11111111 01000010 0 22,5 gr 3,9 mm
1111111 00111010 01010010 01010111 00001101 00000000 11111111 00111011 1 19,9 gr 3,9 mm
1111111 00111010 01010010 00111110 00010010 00000000 11111111 00111001 1 17,4 gr 5,4 mm
1111111 00111010 01010010 00101000 00010010 00000000 11111111 00001000 0 15,2 gr 5,4 mm
1111111 00111010 01010001 00101011 10011010 00000001 11111111 10100011 -10,1 gr/123,0 mm
WS1200 temp:-101
WS1200 rain LSB:154
WS1200 rain MSB:1
WS1200 rain:1230
1111111 00111010 01010001 10101101 10011111 00000001 11111111 00110100 2,9 gr/124,5mm
WS1200 temp:29
WS1200 rain LSB:159
WS1200 rain MSB:1
WS1200 rain:1245
* 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;
* 20;AF;Alecto V3;ID=009a;TEMP=ffe7;RAIN=7a;
\*********************************************************************************************/
#define WS1100_PULSECOUNT 94
#define WS1200_PULSECOUNT 126
#define ALECTOV3_PULSEMID 300/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_031
uint8_t Plugin_031_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len);
unsigned int Plugin_031_ProtocolAlectoRainBase=0;
boolean Plugin_031(byte function, char *string) {
if ((RawSignal.Number != WS1100_PULSECOUNT) && (RawSignal.Number != WS1200_PULSECOUNT)) return false;
unsigned long bitstream1=0L;
unsigned long bitstream2=0L;
byte rc=0;
int temperature=0;
byte humidity=0;
unsigned int rain=0;
byte checksum=0;
byte checksumcalc=0;
byte data[6];
//==================================================================================
for (byte x=15; x<=77; x=x+2) { // get first 32 relevant bits
if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) {
bitstream1 = (bitstream1 << 1) | 0x1;
} else {
bitstream1 = (bitstream1 << 1);
}
}
for (byte x=79; x<=141; x=x+2) { // get second 32 relevant bits
if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) {
bitstream2 = (bitstream2 << 1) | 0x1;
} else {
bitstream2 = (bitstream2 << 1);
}
}
//==================================================================================
if (bitstream1 == 0) return false; // Sanity check
data[0] = (bitstream1 >> 24) & 0xff; // Sort data
data[1] = (bitstream1 >> 16) & 0xff;
data[2] = (bitstream1 >> 8) & 0xff;
data[3] = (bitstream1 >> 0) & 0xff;
data[4] = (bitstream2 >> 24) & 0xff;
data[5] = (bitstream2 >> 16) & 0xff;
// ----------------------------------
if (RawSignal.Number == WS1200_PULSECOUNT) { // verify checksum
checksum = (bitstream2 >> 8) & 0xff;
checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 6);
} else {
checksum = (bitstream2 >> 24) & 0xff;
checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 4);
}
if (checksum != checksumcalc) return false;
// ----------------------------------
rc = (bitstream1 >> 20) & 0xff;
temperature = ((bitstream1 >> 8) & 0x3ff); // 299=12b -400 (0x190) = FF9b
//temperature = ((bitstream1 >> 8) & 0x3ff) - 400; // 299=12b -400 (0x190) = FF9b
if (temperature < 400) { // negative temperature value
temperature = 400 - temperature;
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V3;")); // Label
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
if (RawSignal.Number == WS1100_PULSECOUNT) {
humidity = bitstream1 & 0xff; // alleen op WS1100?
sprintf(pbuffer, "HUM=%02x;", humidity);
Serial.print( pbuffer );
} else {
rain = (((bitstream2 >> 24) & 0xff) * 256) + ((bitstream1 >> 0) & 0xff);
// check if rain unit has been reset!
if (rain < Plugin_031_ProtocolAlectoRainBase) Plugin_031_ProtocolAlectoRainBase=rain;
if (Plugin_031_ProtocolAlectoRainBase > 0) {
//UserVar[basevar+1 -1] += ((float)rain - Plugin_031_ProtocolAlectoRainBase) * 0.30;
sprintf(pbuffer, "RAIN=%02x;", (rain)&0xff);
Serial.print( pbuffer );
}
Plugin_031_ProtocolAlectoRainBase = rain;
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
/*********************************************************************************************\
* Calculates CRC-8 checksum
* reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/
* http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/
* https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp
\*********************************************************************************************/
uint8_t Plugin_031_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len)
{
uint8_t crc = 0;
// Indicated changes are from reference CRC-8 function in OneWire library
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
crc <<= 1; // changed from right shift
if (mix) crc ^= 0x31;// changed from 0x8C;
inbyte <<= 1; // changed from right shift
}
}
return crc;
}
#endif // PLUGIN_031

121
Plugins/Plugin_032.c Normal file
View File

@@ -0,0 +1,121 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-32 AlectoV4 ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the protocol used for outdoor sensors of the Alecto weather stations
* following protocol version 4
* This Plugin works at least with: Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor sensors
* But probably with many others as the OEM sensor is sold under many brand names
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technische informatie:
* Message Format: (9 nibbles, 36 bits):
*
* Format for Temperature Humidity
* AAAAAAAA AAAA BCDD EEEE EEEE EEEE FFFFFFFF
* 01011100 0001 1000 1111 0111 1011 00001110
01110000 0000 1111 1011 0000 0000 00000101
10110101 0000 1x00 01001001
01000101 1000 0110 1111 0000 1100 00100110
01011111 1101 1000 0000 1111 0001 00001110
01000101 1000 0010
*
* A = Rolling Code
* B = 1 (fixed value)
* C = 0=scheduled transmission, 1=requested transmission (button press)
* D = Channel number (00=ch1 01=ch2 10=ch3)
* E = Temperature (two's complement)
* F = Humidity BCD format
*
* 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;
* 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;
* 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;
\*********************************************************************************************/
#ifdef PLUGIN_032
boolean Plugin_032(byte function, char *string) {
if (RawSignal.Number < 74 || RawSignal.Number > 78 ) return false;
unsigned long bitstream=0L;
int temperature=0;
int humidity=0;
byte rc=0;
byte rc2=0;
//==================================================================================
byte start=0;
if (RawSignal.Number == 78) start=4;
if (RawSignal.Number == 76) start=2;
for(int x=2+start; x<=56+start; x=x+2) { // Get first 28 bits
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false;
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3000) {
bitstream = (bitstream << 1) | 0x01;
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1500) {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false;
bitstream = (bitstream << 1);
} else {
return false;
}
}
}
for(int x=58+start;x<=72+start; x=x+2) { // Get remaining 8 bits
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false;
if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) {
humidity = (humidity << 1) | 0x01;
} else {
humidity = (humidity << 1);
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+3000) < millis()) ) { // 1000
// not seen the RF packet recently
if (bitstream == 0) return false; // Sanity check
if (humidity==0) return false; // Sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Sort data
rc = (bitstream >> 20) & 0xff;
rc2= (bitstream >> 12) & 0xfb;
if ( ((rc2)&0x08) != 0x08) return false; // needs to be 1
temperature = (bitstream) & 0xfff;
//fix 12 bit signed number conversion
if ((temperature & 0x800) == 0x800) {
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
if (humidity > 99) return false; // Humidity out of range
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Alecto V4;")); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc, rc2); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
if (humidity < 99) { // Only report valid humidty values
sprintf(pbuffer, "HUM=%02d;", humidity); // decimal value..
Serial.print( pbuffer );
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_032

95
Plugins/Plugin_033.c Normal file
View File

@@ -0,0 +1,95 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-33 Conrad ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding Conrad Pool Thermomether model 9771
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from a Conrad Model 9771 Pool Thermometer, (80 pulses, 40 bits, 433 MHz).
* Message Format:
* AAAAAAAA BBBBBBBB CCCCCCCCCC DD EEEE FFFF GGGG
* 00000000 00010010 1100101101 01 1001 0001 1001
*
* A = Always 0 ?
* B = Device id ?
* C = Temperature digits
* D = Temperature ones
* E = Temperature tens
* F = Always 1?
* G = Unknown
*
* Sample:
* 20;8D;DEBUG;Pulses=80;Pulses(uSec)=1890,5760,1890,5730,1890,5760,1890,5730,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,5910,1830,1890,5640,1890,5760,5910,1830,1890,5640,5910,1830,1860,5640,5910,1830,1890,5610,5910,1830,5910,1830,5910,1830,1890,5400,5910,1830,1890,5610,1890,5760,5910,1830,5910,1830,1890,5520,1890,5760,5910,1860,1890,5610,1890,5760,1890,5760,5910,1830,1890,5610,5910,1830,5910,1830,1860,6990;
\*********************************************************************************************/
#define CONRAD_PULSECOUNT 80
#define CONRAD_PULSEMAX 5000/RAWSIGNAL_SAMPLE_RATE
#define CONRAD_PULSEMIN 2300/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_033
boolean Plugin_033(byte function, char *string) {
if (RawSignal.Number != CONRAD_PULSECOUNT) return false;
unsigned long bitstream=0L;
unsigned int temperature=0;
unsigned int rc=0;
byte checksum=0;
byte bitcount=0; // bit counter (counting first 8 bits that need
//==================================================================================
// get all 28 bits
for(byte x=1;x <=CONRAD_PULSECOUNT-1;x+=2) {
if (RawSignal.Pulses[x] > CONRAD_PULSEMAX) {
if (RawSignal.Pulses[x+1] > CONRAD_PULSEMAX) if ( (x+1) < CONRAD_PULSECOUNT ) return false; // invalid pulse length
if (bitcount > 7) {
bitstream = (bitstream << 1) | 0x1;
} else {
return false; // first 8 bits should all be zeros
}
bitcount++;
} else {
if (RawSignal.Pulses[x] > CONRAD_PULSEMIN) return false; // invalid pulse length
if (RawSignal.Pulses[x+1] < CONRAD_PULSEMIN) return false; // invalid pulse length
if (bitcount > 7) bitstream = (bitstream << 1);
bitcount++;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
Serial.println(bitstream,HEX);
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis() ) || (SignalCRC != bitstream) ) {
SignalCRC=bitstream; // not seen the RF packet recently
if (bitstream == 0) return false; // Perform a sanity check
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
checksum = (bitstream >> 4) & 0x0f;
if (checksum != 0x01) return false;
rc=(bitstream >> 24);
temperature=(bitstream >> 14) & 0x3ff;
temperature=temperature-500;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("Conrad;")); // Label
sprintf(pbuffer, "ID=%04x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_033

313
Plugins/Plugin_034.c Normal file
View File

@@ -0,0 +1,313 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-34 Cresta ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst van Cresta temperatuur weerstation buitensensoren
* Tevens alle sensoren die het Cresta (Hideki) protocol volgen waaronder:
* Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W,
* WXR810, DV928, Ventus W906
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Cresta Weatherstation outdoor unit, (29 pulses, 28 bits, 433 MHz).
* Message Format can be found at: http://members.upc.nl/m.beukelaar/Crestaprotocol.pdf
* Thermo/Hygro: 10 bytes, seen as 128, 132, 134, 136, 138 pulses
* Anemometer: 14 bytes
* UV Index: 11 bytes
* Rain: 9 bytes, seen as 132, 136 pulses
\*********************************************************************************************/
#define CRESTA_MIN_PULSECOUNT 124 // unknown until we have a collection of all packet types but this seems to be the minimum
#define CRESTA_MAX_PULSECOUNT 284 // unknown until we have a collection of all packet types
#define CRESTA_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_034
byte Plugin_034_reverseBits(byte data);
byte Plugin_034_WindDirSeg(byte data);
boolean Plugin_034(byte function, char *string){
if ((RawSignal.Number < CRESTA_MIN_PULSECOUNT) || (RawSignal.Number > CRESTA_MAX_PULSECOUNT) ) return false;
int sensor_data=0;
int windtemp=0;
int windchill=0;
int windgust=0;
int windspeed=0;
int winddirection=0;
int uv=0;
byte checksum=0;
byte data[18];
byte length=0;
byte channel=0;
int units=0;
byte battery=0;
byte bytecounter=0; // used for counting the number of received bytes
byte bitcounter=0; // counts number of received bits (converted from pulses)
int pulseposition=1; // first pulse is always empty
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
byte parity=0; // to calculate byte parity
// ==================================================================================
// get bytes and determine if byte parity is set correctly for the cresta protocol on the fly
do {
//if(RawSignal.Pulses[pulseposition]*RawSignal.Multiply > 700) { // high value = 1 bit
if(RawSignal.Pulses[pulseposition] > CRESTA_PULSEMID) { // high value = 1 bit
if (halfbit==1) { // cant receive a 1 bit after a single low value
return false; // pulse error, must not be a Cresta packet or reception error
}
if (bitcounter==8) {
if (parity != 1) { // now receiving parity bit
return false; // parity error, must not be a Cresta packet or reception error
} else {
bitcounter=0; // reset for next byte
parity=0; // reset for next byte
halfbit=0; // wait for next first low or high pulse
bytecounter++; // 1 byte received
}
} else {
data[bytecounter] = (data[bytecounter] << 1) | 0x1; // 1 bit
parity=parity ^1; // update parity
bitcounter++; // received a bit
halfbit=0; // waiting for first low or a new high pulse
}
} else {
if (halfbit == 0) { // 2 times a low value = 0 bit
halfbit=1; // first half received
} else {
if (bitcounter==8) {
if (parity != 0) { // now receiving parity bit
return false; // parity error, must not be a Cresta packet or reception error
} else {
bitcounter=0; // reset for next byte
parity=0; // reset for next byte
halfbit=0; // wait for next first low or high pulse
bytecounter++; // 1 byte received
}
} else {
data[bytecounter] = (data[bytecounter] << 1); // 0 bit
parity=parity ^0; // update parity
bitcounter++; // received a bit
halfbit=0; // wait for next first low or high pulse
}
}
}
pulseposition++; // point to next pulse
if (pulseposition > RawSignal.Number) break; // reached the end? done processing
} while(bytecounter < 16); // receive maximum number of bytes from pulses
// ==================================================================================
// all bytes received, make sure checksum is okay
// ==================================================================================
for (byte i=0;i<bytecounter;i++) {
data[i] = Plugin_034_reverseBits( data[i] );
}
// get packet length
length=data[2] & 0x3f; // drop bits 6 and 7
length >>= 1; // drop bit 0
if (length > 20) return false; // Additional check for illegal packet lengths to protect against false positives.
if (length == 0) return false; // Additional check for illegal packet lengths to protect against false positives.
// Checksum: XOR of all bytes from byte 1 till byte length+2, should result in 0
checksum=0;
for (byte i=1;i< length+2 ;i++){
checksum=checksum^data[i];
}
if (checksum != 0) return false;
// ==================================================================================
// now process the various sensor types
// ==================================================================================
if ( data[1] > 0x1f && data[1] < 0x40) channel=1;
if ( data[1] > 0x3f && data[1] < 0x60) channel=2;
if ( data[1] > 0x5f && data[1] < 0x80) channel=3;
if ( data[1] > 0x7f && data[1] < 0xa0) channel=1; // no channel settings on Anemometer/rainmeter and uvsensor
if ( data[1] > 0x9f && data[1] < 0xc0) channel=4;
if ( data[1] > 0xbf && data[1] < 0xE0) channel=5;
data[3]=(data[3])&0x1f;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
unsigned long tempval=data[3];
tempval=((tempval)<<16)+((data[1])<<8)+channel;
if((SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis() && SignalCRC != tempval) || (SignalCRC != tempval) ) {
SignalCRC=tempval; // not seen the RF packet recently
} else {
return true; // already seen the RF packet recently
}
// ----------------------------------
battery=(data[2])>>6;
// ----------------------------------
if (data[3] == 0x0c ) { // Anemometer
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
sensor_data=((data[5]&0x3f) * 100) + units;
if ((data[5] & 0x80) != 0x80) {
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
}
windtemp=sensor_data;
units=((data[6]>>4)*10) + (data[6]&0x0f) ;
sensor_data=((data[7]&0x3f) * 100) + units;
if ((data[7] & 0x80) != 0x80) {
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
}
windchill=sensor_data;
windspeed=((data[9]&0x0F)*100) + ((data[8]>>4)*10) + (data[8]&0x0F);
windgust=((data[10]>>4)*100) + ((data[10]&0x0F)*10) + (data[9]>>4);
//windspeed = (data[9] << 8) + data[8];
//windgust = (data[10] << 4) + ( (data[9] &0xf0) >> 4 );
winddirection = Plugin_034_WindDirSeg( ((data[11] &0xf0) >> 4) );
winddirection = winddirection & 0x0f; // make sure we dont get overflows
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Cresta;ID=")); // Label
PrintHexByte(data[1]);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";WINDIR=%04d;", winddirection);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", windspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "WINGS=%04x;", windgust);
Serial.print( pbuffer );
sprintf(pbuffer, "WINTMP=%04x;", windtemp);
Serial.print( pbuffer );
sprintf(pbuffer, "WINCHL=%04x;", windchill);
Serial.print( pbuffer );
if ( battery != 0) {
Serial.print(F("BAT=OK;")); // Label
} else {
Serial.print(F("BAT=LOW;")); // Label
}
Serial.println();
//==================================================================================
} else
// ----------------------------------
if (data[3] == 0x0d ) { // UV Sensor
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
sensor_data=((data[5]&0x3f) * 100) + units;
if ((data[5] & 0x80) != 0x80) {
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
}
// UV sensor reports the temperature but does not report negative values!, skip temperature info?
uv = ((data[8] & 0x0f)<<8)+data[7];
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Cresta;ID=")); // Label
PrintHexByte(data[1]);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
Serial.print( pbuffer );
sprintf(pbuffer, "UV=%04x;", uv);
Serial.print( pbuffer );
if ( battery != 0) {
Serial.print(F("BAT=OK;")); // Label
} else {
Serial.print(F("BAT=LOW;")); // Label
}
Serial.println();
//==================================================================================
} else // 9F 80 CC 4E 00 00 66 64
// ---------------------------------- // 9f 80 cc 4e 01 00 66 65
if (data[3] == 0x0e ) { // Rain meter // 9F 80 CC 4E 76 00 66 12
sensor_data = (data[5]<<8)+data[4]; // 80=rain 4e=>0E = rain
sensor_data=sensor_data*7; // 66 = always 66 rain units * 0.7 = mm.
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Cresta;ID=")); // Label
PrintHexByte(data[1]);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";RAIN=%04x;", sensor_data);
Serial.print( pbuffer );
if ( battery != 0) {
Serial.print(F("BAT=OK;"));
} else {
Serial.print(F("BAT=LOW;"));
}
Serial.println();
//==================================================================================
} else
// ----------------------------------
if (data[3] == 0x1e ) { // Thermo/Hygro
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
sensor_data=((data[5]&0x3f) * 100) + units;
if ((data[5] & 0x80) != 0x80) {
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
}
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Cresta;ID=")); // Label
PrintHexByte(data[1]);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", data[6]);
Serial.print( pbuffer );
if ( battery != 0) {
Serial.print(F("BAT=OK;"));
} else {
Serial.print(F("BAT=LOW;"));
}
Serial.println();
//==================================================================================
} else {
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Cresta;DEBUG;ID=")); // Label
PrintHexByte(data[1]);
PrintHexByte(channel);
// ----------------------------------
PrintHex8( data, length+2);
Serial.print(F(";"));
Serial.println();
//==================================================================================
}
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
// *********************************************************************************************
// * Reverse all bits in a byte
// *********************************************************************************************
byte Plugin_034_reverseBits(byte data) {
byte b = data;
for (byte i = 0; i < 8; ++i) {
data = (data << 1) | (b & 1);
b >>= 1;
}
return data;
}
byte Plugin_034_WindDirSeg(byte data) {
// Encrypted using: a=-a&0xf; b=a^(a>>1);
data ^= (data & 8) >> 1; /* Solve bit 2 */
data ^= (data & 4) >> 1; /* Solve bit 1 */
data ^= (data & 2) >> 1; /* Solve bit 0 */
return -data & 0xf;
}
#endif // PLUGIN_034

110
Plugins/Plugin_035.c Normal file
View File

@@ -0,0 +1,110 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-35 Imagintronix ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding Imagintronix sensors
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
*
* ~0.5ms high puls followed by ~1ms pause = high
* ~1.5ms high puls followed by ~1ms pause = low
*
* Message Format:
* 11111111 01010101 00000101 01000101 11111111 10011110
* FF550545FF9E
* AABCDDEEFFGG
*
* A = Preamble, always FF
* B = TX type, always 5
* C = Address (5/6/7) > low 2 bits = 1/2/3
* D = Soil moisture 05%
* E = temperature
* F = security code, always F
* G = Checksum 55+05+45+FF=19E CRC value = 9E
*
* Sample:
* 20;02;DEBUG;Pulses=96;Pulses(uSec)=390,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1260,870,420,870,1260,870,420,870, 1230,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,1230,870,1260,870,420,870,1260,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,420,870,1260,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1230,870,1260,870,420,870,420,870,420,840,420,840,1260,6990;
* 111111110101010100000101010001011111111110011110
\*********************************************************************************************/
#define IMAGINTRONIX_PULSECOUNT 96
#define IMAGINTRONIX_PULSEMID 1000/RAWSIGNAL_SAMPLE_RATE
#define IMAGINTRONIX_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_035
boolean Plugin_035(byte function, char *string) {
if (RawSignal.Number != IMAGINTRONIX_PULSECOUNT) return false;
unsigned int temperature=0;
unsigned int rc=0;
byte checksum=0;
byte data[8];
unsigned long bitstream=0L;
//==================================================================================
byte bytecounter=0; // used for counting the number of received bytes
byte bitcounter=0; // counts number of received bits (converted from pulses)
// get bits
for(byte x=1;x < IMAGINTRONIX_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSEMID) { // long pulse = 0 bit
if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false;
data[bytecounter] = (data[bytecounter] << 1); // 0 bit
bitcounter++; // received a bit
} else { // Short pulse = 1 bit
if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSESHORT) return false; // Short pulse too long?
if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false;
data[bytecounter] = (data[bytecounter] << 1) | 0x1; // 1 bit
bitcounter++; // received a bit
}
// prepare for next bit/byte
if (bitcounter==8) { // received 8 bits?
bitcounter=0; // reset for next byte
bytecounter++; // byte received, increase counter
if (bytecounter > 7) return false; // overflow, should not happen
}
}
//==================================================================================
// Verify packet and calculate checksum
//==================================================================================
if (data[0] != 0xff) return false;
checksum=data[1]+data[2]+data[3]+data[4];
if (((checksum)&0xff) != data[5]) return false;
if ( (data[1] >>4) != 0x5) return false;
if (data[4] != 0xff) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ) {
//SignalCRC=bitstream; // not seen the RF packet recently
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
rc=(data[1])&0x03;
temperature=(data[3]) << 4;
temperature=temperature/2;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("Imagintronix;")); // Label
sprintf(pbuffer, "ID=%04x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", data[2]);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_035

117
Plugins/Plugin_040.c Normal file
View File

@@ -0,0 +1,117 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-40 Mebus ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding Mebus weatherstation outdoor sensors
* It concerns Mebus sensors that are not following the Cresta (Hideki) protocol
* Also sold as Stacja Pogody WS-9941-M
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from a Mebus Weatherstation outdoor unit, (58 pulses, 28 bits, 433 MHz).
* Mebus Message Format:
* AAAA BBBB BBBB CCCC CCCC CCCC DDEF
*
* A = Checksum value AAAA=((BBBB+BBBB+CCCC+CCCC+DDEF)-1)&0x0f
* B = Changes after each reset, no change during normal operation. (Device 'Session' ID)
* 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)
* D = Channel number 1/2/3
* E = Always 1
* F = 0 when "normal" data transmit, 1 when "requested" data transmit (TX button press)
*
* 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;
* 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;
* 20;81;Mebus;ID=6701;TEMP=010c;
\*********************************************************************************************/
// ==================================================================================
// MEBUS bit packets
// 0000 1101 1001 0000 1100 1000 0111
// 0100 1101 1001 0000 1101 1100 0110
// 0100 1101 1001 0000 1100 1101 0110
// 1001 1101 1001 0000 1101 1100 1011
// 1011 1101 1001 0001 0000 1111 0110 27.1
// 0010 0110 1110 0000 0000 1001 0110 0.9
// 0011 0110 1110 1111 1000 0011 0110 -12.5 (1111 1000 0011=3971, 4096-3971=125
// |----------|----------> temperature 0 - 51.1
// |-|---------------------> set when minus temperatures -51.2 - 0
// ==================================================================================
#define MEBUS_PULSECOUNT 58
#ifdef PLUGIN_040
boolean Plugin_040(byte function, char *string) {
if (RawSignal.Number != MEBUS_PULSECOUNT) return false;
unsigned long bitstream=0L;
unsigned int temperature=0;
byte rc=0;
byte checksum=0;
byte data[7];
byte channel=0;
//==================================================================================
// get all 28 bits
for(byte x=2;x <=MEBUS_PULSECOUNT-2;x+=2) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; // make sure inbetween pulses are not too long
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3400) {
bitstream = (bitstream << 1) | 0x1;
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false; // invalid pulse length
if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false; // invalid pulse length
bitstream = (bitstream << 1);
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis() && SignalCRC != bitstream) || (SignalCRC != bitstream) ) {
SignalCRC=bitstream; // not seen the RF packet recently
if (bitstream == 0) return false; // Perform a sanity check
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
data[0] = (bitstream >> 24) & 0x0f; // prepare nibbles from bit stream
data[1] = (bitstream >> 20) & 0x0f;
data[2] = (bitstream >> 16) & 0x0f;
data[3] = (bitstream >> 12) & 0x0f;
data[4] = (bitstream >> 8) & 0x0f;
data[5] = (bitstream >> 4) & 0x0f;
data[6] = (bitstream >> 0) & 0x0f;
//==================================================================================
// first perform a checksum check to make sure the packet is a valid mebus packet
checksum=data[1]+data[2]+data[3]+data[4]+data[5]+data[6];
checksum=(checksum-1)&0xf;
if (checksum != data[0]) return false;
//==================================================================================
rc=(data[1]<<4) + data[2];
channel=(data[6])>>2;
temperature=(data[3]<<8)+(data[4]<<4)+data[5];
if (temperature > 3000) {
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("Mebus;")); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc, channel);// ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temperature);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_040

250
Plugins/Plugin_041.c Normal file
View File

@@ -0,0 +1,250 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-43 LaCrosse ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
* It also works for all non LaCrosse sensors that follow this protocol.
* WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, WS7000-20: Thermo/Humidity/Barometer
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Meteo Sensor: (162 pulses)
* Each frame is 80 bits long. It is composed of:
* 10 bits of 0 (preamble)
* 14 blocks of four bits separated by a 1 bit to be checked and skipped
*
* 0100 0111 1000 0101 0010 0100 0000 0011 0001 0001 1000 1101 1110 1011
* aaaa bbbb cccc cccc cccc dddd dddd dddd eeee eeee eeee ffff gggg hhhh
*
* a = sensor type (04=Meteo sensor)
* b = sensor address
* c = temperature BCD, reversed
* d = humidity BCD, reversed
* e = air pressure, BCD reversed + 200 offset in hPa
* f = unknown?
* g = xor value
* h = checksum value
*
* Sample:
* 20;07;DEBUG;Pulses=162;Pulses(uSec)=825,275,750,275,750,300,750,300,750,300,750,275,750,275,750,300,750,300,750,300,250,800,725,300,750,300,250,800,725,300,225,800,225,800,250,800,250,800,725,300,250,800,725,300,750,300,725,300,250,800,250,800,225,800,750,300,250,800,725,300,250,800,725,300,250,800,725,300,725,300,250,800,725,300,725,300,250,800,725,300,250,800,725,300,725,300,725,300,725,300,250,800,225,800,225,800,725,300,725,300,225,800,225,800,725,300,725,300,725,300,250,800,250,800,725,300,725,300,725,300,250,800,725,300,725,300,725,300,225,800,225,800,225,800,725,300,225,800,225,800,250,800,725,300,225,800,225,800,225,800,250,800,250,800,225,800,725,300,225,800,225,600;
* 1010101010101010101001101001100101010110011010100101011001100110011010011010011001101010100101011010010110101001011010100110101001010110010101100101010101011001 00
* 0000000000 1 0010 1 1110 1 0001 1 1010 1 0100 1 0010 1 0000 1 1100 1 1000 1 1000 1 0001 1 1011 1 0111 1 1101 0
* 0010 1110 0001 1010 0100 0010 0000 1100 1000 1000 0001 1011 0111 1101
* 0100 0111 1000 0101 0010 0100 0000 0011 0001 0001 1000 1101 1110 1011
* 4 7 852 403 118 D E B
* 25.8 30.4 811+200
* --------------------------------------------------------------------------------------------
* Rain Packet: (92 pulses)
* Each frame is 46 bits long. It is composed of:
* 10 bits of 0 (preamble)
* 7 blocks of four bits separated by a 1 bit to be checked and skipped
*
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
* Example
* 0000000000 0010 1111 1011 0010 1011 1111 1101
* aaaa bbbb ccc1 ccc2 ccc3 dddd eeee
* 2 F B 2 B F D
*
* a = sensor type (2=Rain meter)
* b = sensor address
* c = rain data (LSB thus the right order is c3 c2 c1)
* d = Check Xor : (2 ^ F ^ B ^ 2 ^ B ^ F) = 0
* e = Check Sum : (const5 + 2 + F + B + 2 + B + F) and F = D
* --------------------------------------------------------------------------------------------
* Wind packet: (122 pulses)
* Each frame is composed of:
* 10bits of 0 (preamble)
* 10 blocks of four bits separated by a bit 1 to be checked and skipped
*
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
* Example
* 0000000000 0011 0111 0101 0000 0001 0101 0100 0111 0110 1011
* aaaa bbbb cccc cccc cccc dddd dddd ddee ffff gggg
* 3 7 5 0 1 5 4 1 3 6 B
*
* a = sensor type (2=Rain meter)
* b = sensor address
* c = speed
* d = direction
* f = Check Xor
* g = Check Sum
* --------------------------------------------------------------------------------------------
* UV packet (132 pulses)
\*********************************************************************************************/
#define LACROSSE41_PULSECOUNT1 92 // Rain sensor
#define LACROSSE41_PULSECOUNT2 162 // Meteo sensor
#define LACROSSE41_PULSECOUNT3 122 // Wind sensor
#define LACROSSE41_PULSECOUNT4 132 // Brightness sensor
#define LACROSSE41_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_041
boolean Plugin_041(byte function, char *string) {
boolean success=false;
if ( (RawSignal.Number != LACROSSE41_PULSECOUNT1) && (RawSignal.Number != LACROSSE41_PULSECOUNT2) &&
(RawSignal.Number != LACROSSE41_PULSECOUNT3) && (RawSignal.Number != LACROSSE41_PULSECOUNT4) ) return false;
unsigned long bitstream1=0L; // holds first 16 bits
unsigned long bitstream2=0L; // holds last 28 bits
int sensor_data=0;
byte checksum=0;
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte bytecounter=0; // used for counting the number of received bytes
byte data[18];
//==================================================================================
// Check preamble
for(int x=1;x<20;x+=2) {
if ((RawSignal.Pulses[x] < LACROSSE41_PULSEMID) || (RawSignal.Pulses[x+1] > LACROSSE41_PULSEMID) ) {
return false; // bad preamble bit detected, abort
}
}
if ((RawSignal.Pulses[21] > LACROSSE41_PULSEMID) || (RawSignal.Pulses[22] < LACROSSE41_PULSEMID) ) {
return false; // There should be a 1 bit after the preamble
}
// get bits/nibbles
for(int x=23;x<RawSignal.Number-2;x+=2) {
if (RawSignal.Pulses[x] < LACROSSE41_PULSEMID) { // 1 bit
data[bytecounter] = ((data[bytecounter] >> 1) | 0x08); // 1 bit, store in reversed bit order
} else {
data[bytecounter] = ((data[bytecounter] >> 1)&0x07); // 0 bit, store in reversed bit order
}
bitcounter++;
if (bitcounter == 4) {
x=x+2;
if (x > RawSignal.Number-2) break; // dont check the last marker
if ((RawSignal.Pulses[x] > LACROSSE41_PULSEMID) || (RawSignal.Pulses[x+1] < LACROSSE41_PULSEMID) ) {
return false; // There should be a 1 bit after each nibble
}
bitcounter=0;
bytecounter++;
if (bytecounter > 17) return false; // received too many nibbles/bytes, abort
}
}
//==================================================================================
// all bytes received, make sure checksum is okay
//==================================================================================
// check xor value
checksum=0;
for (byte i=0;i<bytecounter;i++){
checksum=checksum^data[i];
}
if (checksum !=0) return false; // all (excluding last) nibbles xored must result in 0
// check checksum value
checksum=5;
for (byte i=0;i<bytecounter;i++){
checksum=checksum + data[i];
}
checksum=checksum & 0x0f;
if (checksum != (data[bytecounter])) return false; // all (excluding last) nibble added must result in last nibble value
//==================================================================================
// Prevent repeating signals from showing up, skips every second packet!
//==================================================================================
unsigned long tempval=(data[4])>>1;
tempval=((tempval)<<16)+((data[3])<<8)+data[2];
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
// not seen this RF packet recently
SignalCRC=tempval;
} else {
return true; // already seen the RF packet recently, but still want the humidity
}
//==================================================================================
// now process the various sensor types
//==================================================================================
// Output
// ----------------------------------
if (data[0] == 0x04) { // Meteo sensor
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosseV3;ID=")); // Label
PrintHex8( data,2);
sensor_data = data[4]*100;
sensor_data = sensor_data + data[3]*10;
sensor_data = sensor_data + data[2];
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
Serial.print( pbuffer );
sensor_data = data[7]*10;
sensor_data = sensor_data + data[6];
sprintf(pbuffer, "HUM=%04d;", sensor_data);
Serial.print( pbuffer );
sensor_data = data[10]*100;
sensor_data = sensor_data + data[9]*10;
sensor_data = sensor_data + data[8];
sensor_data = sensor_data + 200;
sprintf(pbuffer, "BARO=%04x;", sensor_data);
Serial.println( pbuffer );
RawSignal.Repeats=false;
RawSignal.Number=0;
success=true;
} else
if (data[0] == 0x02) { // Rain sensor
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosseV3;ID=")); // Label
PrintHex8( data,2);
sensor_data = data[4]*100;
sensor_data = sensor_data + data[3]*10;
sensor_data = sensor_data + data[2];
sprintf(pbuffer, ";RAIN=%04x;", sensor_data);
Serial.println( pbuffer );
RawSignal.Repeats=false;
RawSignal.Number=0;
success=true;
} else
if (data[0] == 0x03) { // wind sensor
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosseV3;ID=")); // Label
PrintHex8( data,2);
sensor_data = data[4]*100;
sensor_data = sensor_data + data[3]*10;
sensor_data = sensor_data + data[2];
sprintf(pbuffer, ";WINSP=%04x;", sensor_data);
Serial.print( pbuffer );
sensor_data = ((data[7])>>2)*100;
sensor_data = sensor_data + data[6]*10;
sensor_data = sensor_data + data[5];
sensor_data = sensor_data / 22.5;
sprintf(pbuffer, "WINDIR=%04x;", sensor_data);
Serial.println( pbuffer );
RawSignal.Repeats=false;
RawSignal.Number=0;
success=true;
} else
if (data[0] == 0x05) { // UV sensor
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosseV3;ID=")); // Label
PrintHex8( data,2);
sensor_data = data[4]*100;
sensor_data = sensor_data + data[3]*10;
sensor_data = sensor_data + data[2];
sprintf(pbuffer, ";UV=%04x;", sensor_data);
Serial.println( pbuffer );
RawSignal.Repeats=false;
RawSignal.Number=0;
success=true;
}
//==================================================================================
return success;
}
#endif // PLUGIN_041

293
Plugins/Plugin_042.c Normal file
View File

@@ -0,0 +1,293 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-42 UPM/Esic ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst van UPM/Esic weerstation buitensensoren
* Tevens alle sensoren die het UPM/Esic (W.H. Mandolyn International Ltd) protocol volgen waaronder:
* UPM, Esic, Emos, DVM, Clas Ohlson, Dickson
* WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from a UPM/Esic Weatherstation outdoor unit, (52/54 pulses, 36 bits, 433 MHz).
* Supports two packet formats
* --------------------------------------------------------------------------------------------
* FORMAT 1:
*
* ____Byte 0_____ ____Byte 1_____ ____Byte 2_____ ____Byte 3_____ _Nib4__
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 3 2 1 0
* x x x x c c c c d d y y b S S S s s s s s P P P p p p p p p p p z z C C
*
* x = Constant, 1100, probably preamble
* c = House Code (0 - 15)
* d = Device Code (1 - 4) ?
* y = ?
* b = Low battery indication
* S = Secondary value - Humidity/Wind direction (high bits)
* s = Secondary value - Humidity/Wind direction (low bits)
* P = Primary value - Temperature/Rain/Wind speed value (high bits)
* p = Primary value - Temperature/Rain/Wind speed value (low bits)
* z = Sequence number 0 - 2. Messages are sent in bursts of 3. For some senders this is always 0
* C = Checksum. bit 1 is XOR of odd bits, bit 0 XOR of even bits in message
*
* If HouseCode = 10 and deviceCode = 2, then p and P is Wind speed
* and h and H is Wind direction
*
* If HouseCode = 10 and deviceCode = 3, then p and P is rain
*
* Temp (C) = RawValue / 16 - 50
* Rain (total mm) = RawValue * 0,7
* Wind Speed (mph)= RawValue (* 1/3,6 for km/h)
* Humidity (%) = RawValue / 2
* Wind direction (deg) = RawValue * 22,5
* --------------------------------------------------------------------------------------------
* FORMAT 2:
*
* ____Byte 0_____ ____Byte 1_____ ____Byte 2_____ ____Byte 3_____ _Nib4__
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 3 2 1 0
* x x x x c c c c d d y y b h h h h h h h T T T T T T T T t t t t t t t p
*
* x = Constant, 1100, probably preamble
* c = House Code (0 - 15)
* d = Device (Channel) Code (1 - 4) ?
* y = ?
* b = ?
* h = Humidity (7 bits) (0111011 = 59 %)
* T = Temperature (8 bits) (see below)
* t = Temperature (7 bits) (see below)
* p = Parity (xor of all bits should give 0)
*
* The temperature is transmitted as (temp + 50.0) * 128, which equals (temp * 128) + 6400. Adding 50.0 °C makes
* all values positive, an unsigned 15 bit integer where the first 8 bits correspond to the whole part of the temperature
* (here 01001001, decimal 73, substract 50 = 23). Remaining 7 bits correspond to the fractional part.
* Sample:
* 20;64;DEBUG;Pulses=52;Pulses(uSec)=875,875,825,875,1725,1800,1725,1800,1725,850,825,1800,1725,875,800,850,825,1800,1725,1800,800,875,800,850,1725,1800,825,850,1725,850,825,1800,1725,1800,825,850,1725,875,800,1800,800,875,800,850,825,850,1725,1800,1750,1800,475;
* 11000001 00110000 11100100 01100000 0010
*
*20;C3;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,1975,1875,1975,1850,975,850,1975,1850,975,850,975,850,2000,1850,975,875,975,850,975,850,2000,850,975,1850,2000,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,1975,1850,2000,1850,1975,225;
*20;C4;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,2000,1875,2000,1850,975,850,2000,1850,975,850,975,850,2000,1850,975,875,950,875,975,850,2000,850,975,1850,2000,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,2000,1850,2000,1850,2000,225;
*20;C5;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,2000,1875,2000,1850,975,850,2000,1850,975,850,975,850,2000,1850,975,875,975,850,975,850,1975,850,975,1850,1975,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,2000,1850,2000,1850,2000,225;
*20;32;DEBUG;Pulses=48;Pulses(uSec)=850,900,875,900,1850,1875,1850,1875,1850,900,875,1875,1850,900,875,900,875,1875,1850,900,875,1875,1850,1875,1825,900,875,1875,875,900,1850,1875,875,900,875,900,1850,1875,1825,1875,1850,1875,1850,1875,1825,1875,500;
*20;33;UPM/Esic;ID=0001;TEMP=0104;HUM=33;BAT=OK;
925,900,875,900,1825,1875,1850,1875,1850,900,
875,1875,1850,900,850,900,850,1875,1850,900,
850,1875,1850,900,850,1875,1850,1875,875,900,
1850,1875,875,900,875,900,1825,1875,1850,900,
875,1875,1850,900,875,1875,850,900,875,900,
500 51
0011111011 0011010111 0110011101 10100
\*********************************************************************************************/
#define UPM_MIN_PULSECOUNT 46
#define UPM_MAX_PULSECOUNT 56
#define UPM_PULSELOHI 1100/RAWSIGNAL_SAMPLE_RATE
#define UPM_PULSEHIHI 2075/RAWSIGNAL_SAMPLE_RATE
#define UPM_PULSEHILO 1600/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_042
boolean Plugin_042(byte function, char *string) {
if (RawSignal.Number < UPM_MIN_PULSECOUNT || RawSignal.Number > UPM_MAX_PULSECOUNT) return false;
byte rc=0;
unsigned long bitstream1=0L; // holds first 10 bits
unsigned long bitstream2=0L; // holds last 26 bits
int temperature=0;
int humidity=0;
int rain=0;
int winds=0;
int windd=0;
byte battery=0;
byte units=0;
byte devicecode=0;
byte checksum=0;
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
byte msgformat=0;
//==================================================================================
for(int x=1;x <RawSignal.Number;x++) { // get bytes
if ((RawSignal.Pulses[x] > UPM_PULSEHILO) && (RawSignal.Pulses[x] < UPM_PULSEHIHI)) {
if (halfbit==1) { // UPM cant receive a 1 bit after a single low value
return false; // pulse error, must not be a UPM packet or reception error
}
if (bitcounter < 10) {
bitstream1 = (bitstream1 << 1);
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1);
bitcounter++; // only need to count the first 10 bits
}
halfbit=0; // wait for next first low or high pulse
} else {
if ((RawSignal.Pulses[x] > UPM_PULSELOHI) ) return false; // Not a valid UPM pulse length
if (halfbit == 0) { // 2 times a low value = 0 bit
halfbit=1; // first half received
} else {
if (bitcounter < 10) {
bitstream1 = (bitstream1 << 1) | 0x1;
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
bitcounter++; // only need to count the first 10 bits
}
halfbit=0; // wait for next first low or high pulse
}
}
if (bitcounter > 36) return false; // too many bits, it cant be the right protocol
}
//==================================================================================
if ( (bitstream1 >> 6 ) != 0x0c ) return false; // sanity check, first 4 bits should always be '1100' to be a valid UPM/Esic packet
if ( bitstream1 == 0x00 ) return false; // sanity check
if ( bitstream2 == 0x00 ) return false; // sanity check
//==================================================================================
for (byte i=0;i<9;i=i+2){ // perform a checksum check to make sure the packet is a valid UPM/Esic packet
checksum=checksum ^ ((bitstream1 >> i) &3); // Checksum - xor all odd and all even bits should match the last two bits
}
for (byte i=2;i<25;i=i+2){
checksum=checksum ^ ((bitstream2 >> i) &3);
}
if (checksum == (bitstream2 &3 )) { // did the format 1 checksum calculation match?
msgformat=1; // Yes, set it
} else { // else perform a bit parity check to see if we have format 2
checksum=checksum ^ ((bitstream2) &3); // xor the last 2 bits
units = (checksum >> 1) & 0x01; // get the odd bit of the checksum result
checksum=(checksum & 0x01) ^ units; // xor the odd with the even bit of the checksum result
if (checksum == 0) { // did the format 2 parity checksum calculation match?
msgformat=2;
} else {
return false;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+1000<millis()) && (SignalCRC != bitstream1)) || (SignalCRC != bitstream1) ) {
SignalCRC=bitstream1; // not seen the RF packet recently
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
// now process the various sensor types
//==================================================================================
units=bitstream1 & 0x03; // housecode format 1&2
rc=units; // housecode format 1&2
devicecode=(bitstream1 >> 2) & 0x0f; // devicecode format 1&2
//==================================================================================
if (msgformat==1) {
battery = (bitstream2 >> 23) & 1; // battery state 1=low 0=ok
if ((rc==10) && (devicecode==2)) { // wind
units = (bitstream2 >> 4) & 0x0f;
winds = (bitstream2 >> 8) & 0x7f;
windd = (bitstream2 >> 15) & 0x0f; //0xff; // wind direction
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";UPM/Esic;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(devicecode);
// ----------------------------------
sprintf(pbuffer, ";WINSP=%02x;", winds);
Serial.print( pbuffer );
sprintf(pbuffer, "WINDIR=%04d;", windd);
Serial.print( pbuffer );
if (battery==1) { // battery status
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
//==================================================================================
} else
if ((rc==10) && (devicecode==3)) { // rain
units = (bitstream2 >> 4) & 0x0f;
rain = (bitstream2 >> 8) & 0x7f;
rain = rain * 7; // Serial.print( (float)rain * 0.7 );
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";UPM/Esic;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(devicecode);
// ----------------------------------
sprintf(pbuffer, ";RAIN=%04x;", rain);
Serial.print( pbuffer );
if (battery==1) { // battery status
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
//==================================================================================
} else { // temperature & Humidity
units = (bitstream2 >> 4) & 0x0f; // temperature
temperature = (bitstream2 >> 8) & 0x7f;
temperature = temperature-50;
temperature = (temperature*10) + units;
if (temperature > 0x3e8) return false;
humidity = (bitstream2 >> 15) & 0xff; // humidity
humidity = humidity / 2;
//if (humidity==0) return false; // dont accept Bad humidity status
//if (temperature > 1000) return false; // dont accept bad temperature
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";UPM/Esic;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(devicecode);
// ----------------------------------
sprintf(pbuffer,";TEMP=%04x;", temperature);
Serial.print( pbuffer );
sprintf(pbuffer,"HUM=%02d;", humidity); // Humidity 0x15 = 21% decimal
Serial.print( pbuffer );
if (battery==1) { // battery status
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
//==================================================================================
}
} else {
units = (bitstream2 >> 1) & 0x7f; // temperature
temperature = (bitstream2 >> 8) & 0xff;
temperature = temperature-50;
temperature = (temperature*100) + units;
temperature = temperature/10;
if (temperature > 0x3e8) return false;
humidity = (bitstream2 >> 16) & 0x7f; // humidity
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";UPM/Esic F2;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(devicecode);
// ----------------------------------
sprintf(pbuffer,";TEMP=%04x;", temperature);
Serial.print( pbuffer );
sprintf(pbuffer,"HUM=%02x;", humidity);
Serial.print( pbuffer );
Serial.println();
//==================================================================================
}
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_042

211
Plugins/Plugin_043.c Normal file
View File

@@ -0,0 +1,211 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-43 LaCrosse ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
* It also works for all non LaCrosse sensors that follow this protocol.
* Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4, Lacrosse TX4U
* WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, WS7000-20: Thermo/Humidity/Barometer
* TFA 30.3125 (temperature + humidity), TFA 30.3120.90 (temperature)
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* Decodes signals from a LaCrosse Weatherstation outdoor unit, (88 pulses, 44 bits, 433 MHz).
* Partially based on http://www.f6fbb.org/domo/sensors/tx3_th.php
*
* Temperature sensor (TX3)
* Each frame is 44 bits long. It is composed of:
* • 2 blocks of four bits = 0A (start sequence)
* • 8 blocks of four bits (data)
* • 1 block of four bits (checksum)
*
* The active values of the frames are explained below:
*
* Example
* 0000 1010 0000 0000 1110 0111 0011 0001 0111 0011 1101
* aaaa aaaa bbbb cccc cccd eeee ffff gggg hhhh iiii jjjj
* 0 A 0 0 7 0 7 3 1 7 3 D
*
* 000a0004070705030705
* 20;d8;LaCrosse;ID=0401;TEMP=00fd;
* 000a0e04070608000608
* 20;d9;LaCrosse;ID=0403;HUM=68;
*
* • a = Start sequence (always 0000 1010)
* • b = Packet type (0=Thermo E=hygro)
* • c = Address of sensor (changes when inserting batteries)
* • d = Parity bit (c+d+e bits sum is even)
* • e-i = Measured values:
* e = tens (x 10)
* f = ones (x 1)
* g = digits (x 0.1) (is zero in case of humidity)
* h = copy of e value
* i = copy of f value
* • j = Checksum (Lower four bits of the sum of all words)
*
* Checksum: (0 + A + 0 + 0 + E + 7 + 3 + 1 + 7 + 3) and F = D D
* Sample:
* 20;11;DEBUG;Pulses=88;Pulses(uSec)=1200,875,1125,875,1125,875,1125,900,400,900,1150,875,400,900,1150,875,1125,875,1125,875,1150,875,1150,875,400,900,400,875,375,900,1150,875,1125,875,400,900,1150,875,1125,875,1125,875,400,900,400,875,1125,900,400,875,1150,875,1150,900,1125,875,1150,875,400,900,400,875,400,900,1150,875,400,900,400,875,1125,875,400,900,1150,900,1125,875,1150,875,375,900,400,900,400,900,400;
* 20;9E;DEBUG;Pulses=88;Pulses(uSec)=1300,925,1225,925,1225,925,1200,925,425,925,1225,925,425,925,1225,925,1225,925,1225,925,1225,925,1225,925,1225,925,425,925,1225,925,1225,925,1225,925,425,925,425,925,1225,925,1225,925,425,925,425,925,425,925,1225,925,425,925,425,925,1225,925,425,925,1225,925,1225,925,1225,925,1225,925,425,925,425,925,425,925,1200,925,425,925,425,925,1225,925,1225,925,425,925,425,925,1225;
* 20;9F;LaCrosse;ID=0403;TEMP=010c;
* 20;A1;DEBUG;Pulses=88;Pulses(uSec)=1325,925,1225,925,1225,925,1225,925,425,925,1225,925,425,925,1225,925,425,925,425,925,425,925,1225,925,1225,925,425,925,1225,925,1225,925,1225,925,425,925,425,925,1225,925,1225,925,425,925,1225,925,425,925,1225,925,425,950,425,925,1225,925,1225,925,1225,925,1225,925,1225,925,1225,925,425,925,1225,925,425,925,1200,925,425,925,425,925,1225,925,425,925,1225,925,1225,925,1225;
* 20;A2;LaCrosse;ID=0403;HUM=56;
* 1275,925,1225,925,1225,925,1200,925,425,925,1225,925,425,925,1225,900,1225,925,1200,925,1225,925,1225,925,1225,925,425,925,1225,925,1200,925,1225,925,425,925,425,900,1225,900,1225,925,425,925,425,925,425,925,1225,900,425,925,1225,925,1225,925,1225,925,425,950,1225,900,425,950,1225,925,425,925,425,900,425,950,1200,900,425,925,1225,925,1225,925,425,925,425,925,425,925,425
20;76;DEBUG;Pulses=88;Pulses(uSec)=810,1440,1200,930,1200,960,1200,930,390,930,1200,930,420,960,1200,930,1200,930,1200,930,1200,930,1200,930,1200,930,420,930,1200,960,1200,930,1200,930,420,930,420,930,1200,930,1200,960,390,930,420,930,420,960,1200,930,390,930,1200,930,420,930,1200,960,1170,930,1200,930,420,930,1200,930,420,930,420,930,420,930,1200,930,420,930,1200,930,420,930,420,930,420,930,1200,930,420,6990;
0000 1010 0000 0100 0110 0111 0101 0001 0111 0101 1101
20;78;DEBUG;Pulses=88;Pulses(uSec)=240,1980,1200,960,1200,960,1200,960,390,930,1200,930,390,960,1200,960,390,930,420,930,420,930,1200,930,1200,960,390,930,1200,930,1200,930,1200,930,420,930,420,930,1200,930,1200,930,420,930,420,930,1200,930,1200,930,420,960,1200,960,390,960,1200,930,1200,930,1200,930,1200,930,1200,930,420,960,390,930,1200,930,1200,960,390,930,1200,930,420,930,420,930,1200,930,1200,930,1200,6990;
0;29;DEBUG;Pulses=86;Pulses(uSec)=1260,930,1200,930,1200,930,420,960,1200,930,420,930,1200,930,1200,930,1200,930,1200,930,1200,930,1200,930,390,930,1200,960,1200,960,1200,930,420,930,390,960,1200,960,1200,930,420,930,420,930,390,960,1200,960,390,930,1200,930,1200,930,1200,930,420,930,420,960,1200,960,1200,930,390,960,390,960,390,930,1200,960,420,930,1200,930,1200,930,1200,930,1200,930,1200,930,1200,6990;
20;2A;DEBUG;Pulses=50;Pulses(uSec)=1200,900,1140,870,390,900,360,900,390,900,1140,930,420,930,1200,930,1200,930,1200,930,420,930,390,960,1200,930,1200,930,390,930,420,960,390,930,1200,930,390,960,1200,960,1200,930,1200,960,1170,930,1200,930,1200,6990;
20;2B;DEBUG;Pulses=86;Pulses(uSec)=1230,960,1200,960,1200,930,390,960,1200,930,420,930,1200,930,420,930,390,960,420,930,1200,930,1200,930,420,930,1200,960,1170,960,1200,930,390,930,420,930,390,930,1200,930,420,930,390,930,1200,960,1200,930,420,930,420,960,390,930,1200,930,1200,930,1200,930,1200,930,1200,930,390,960,390,930,1200,960,1200,930,420,930,420,960,390,930,420,960,390,930,1200,930,420,6990;
* --------------------------------------------------------------------------------------------
* Rain Packet:
* Each frame is 46 bits long. It is composed of:
* 10bits of 0 (start sequence)
* 7 blocks of four bits separated by a bit 1 to be checked and skipped
*
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
* Example
* 0000 0000 0010 1111 1011 0010 1011 1111 1101
* aaaa bbbb ccc1 ccc2 ccc3 dddd eeee
* 2 F B 2 B F D
*
* a = sensor type (2=Rain meter)
* b = sensor address
* c = rain data (LSB thus the right order is c3 c2 c1)
* d = Check Xor : (2 ^ F ^ B ^ 2 ^ B ^ F) = 0
* e = Check Sum : (const5 + 2 + F + B + 2 + B + F) and F = D
\*********************************************************************************************/
#define LACROSSE43_PULSECOUNT 88
#define LACROSSE43_PULSEMID 750/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE43_PULSEMAX 1350/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE43_PULSEMINMAX 550/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE43_MIDLO 800/RAWSIGNAL_SAMPLE_RATE
#define LACROSSE43_MIDHI 1000/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_043
boolean Plugin_043(byte function, char *string) {
boolean success=false;
if ( (RawSignal.Number < LACROSSE43_PULSECOUNT - 4) || (RawSignal.Number > LACROSSE43_PULSECOUNT + 4) ) return false;
unsigned long bitstream1=0L; // holds first 16 bits
unsigned long bitstream2=0L; // holds last 28 bits
int temperature=0;
int humidity=0;
byte checksum=0;
byte bitcounter=0; // counts number of received bits (converted from pulses)
byte data[10];
//==================================================================================
// get bytes
for(int x=1;x<RawSignal.Number;x+=2) {
if ((RawSignal.Pulses[x+1] < LACROSSE43_MIDLO) || (RawSignal.Pulses[x+1] > LACROSSE43_MIDHI)) {
if (x < 2) { // Make sure the first bit is correct..
RawSignal.Pulses[1]=1200/RAWSIGNAL_SAMPLE_RATE;
} else {
if (x+1 < RawSignal.Number) return false; // in between pulse check
}
}
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMID) {
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMAX) return false;
if (bitcounter < 16) {
bitstream1 = (bitstream1 << 1);
bitcounter++; // only need to count the first 16 bits
} else {
bitstream2 = (bitstream2 << 1);
}
} else {
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMINMAX) return false;
if (bitcounter < 16) {
bitstream1 = (bitstream1 << 1) | 0x1;
bitcounter++; // only need to count the first 16 bits
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
}
}
}
//==================================================================================
// all bytes received, make sure checksum is okay
//==================================================================================
if ((bitstream1 == 0) && (bitstream2 == 0)) return false;
data[0] = (bitstream1 >> 12) & 0x0f; // prepare nibbles from bit stream
if (data[0] != 0x00) return false;
data[1] = (bitstream1 >> 8) & 0x0f;
if (data[1] != 0x0a) return false;
data[2] = (bitstream1 >> 4) & 0x0f;
data[3] = (bitstream1 >> 0) & 0x0f;
data[4] = (bitstream2 >> 24) & 0x0f;
data[5] = (bitstream2 >> 20) & 0x0f;
data[6] = (bitstream2 >> 16) & 0x0f;
data[7] = (bitstream2 >> 12) & 0x0f;
data[8] = (bitstream2 >> 8) & 0x0f;
data[9] = (bitstream2 >> 4) & 0x0f;
//==================================================================================
// first perform a checksum check to make sure the packet is a valid LaCrosse packet
for (byte i=0;i<10;i++){
checksum=checksum + data[i];
}
checksum=checksum & 0x0f;
if (checksum != (bitstream2 &0x0f )) return false;
//==================================================================================
// Prevent repeating signals from showing up, skips every second packet!
//==================================================================================
unsigned long tempval=(data[4])>>1;
tempval=((tempval)<<16)+((data[3])<<8)+data[2];
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
// not seen this RF packet recently
SignalCRC=tempval;
} else {
return true; // already seen the RF packet recently, but still want the humidity
}
//==================================================================================
// now process the various sensor types
//==================================================================================
// Output
// ----------------------------------
if (data[2] == 0x00) {
temperature = data[5]*100;
temperature = temperature + data[6]*10;
temperature = temperature + data[7];
temperature = temperature-500;
data[4]=(data[4])>>1;
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosse;ID=")); // Label
PrintHex8( data+3,2);
sprintf(pbuffer, ";TEMP=%04x;", temperature);
Serial.println( pbuffer );
RawSignal.Repeats=false;
RawSignal.Number=0;
success=true;
} else
if (data[2] == 0x0e) {
humidity=(data[5]*16)+data[6];
if (humidity==0) return false; // humidity should not be 0
data[4]=(data[4])>>1;
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("LaCrosse;ID=")); // Label
PrintHex8( data+3,2);
sprintf(pbuffer, ";HUM=%02x;", (humidity)&0xff);
Serial.println( pbuffer );
RawSignal.Repeats=true;
RawSignal.Number=0;
success=true;
}
//==================================================================================
return success;
}
#endif // PLUGIN_043

111
Plugins/Plugin_044.c Normal file
View File

@@ -0,0 +1,111 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-44 Auriol V3 ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the Auriol protocol for sensor type Z32171A
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Auriol Weatherstation outdoor unit, (40 bits, 433 MHz).
*
* Auriol Message Format:
* 1011 1111 1001 1010 0110 0001 1011 0100 1001 0001
* B F 9 A 6 1 B 4 9 1
* AAAA AAAA BBBB CCDD EEEE EEEE EEEE FFFF FFFF GGHH
*
* A = ID?
* B = Rolling code?
* C = possibly battery indicator ?
* D = trend (2 bits) indicating temp equal/up/down ?
* E = Temperature => 0x61b (0x61b-0x4c4)=0x157 *5)=0x6b3 /9)=0xBE => 0xBE = 190 decimal!
* F = humidity: 49%
* G = ?
* H = channel: 1 (2 bits)
*
* Sample:
* 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;
\*********************************************************************************************/
#define AURIOLV3_PULSECOUNT 82
#ifdef PLUGIN_044
boolean Plugin_044(byte function, char *string) {
if (RawSignal.Number != AURIOLV3_PULSECOUNT) return false;
unsigned long bitstream1=0L;
unsigned long bitstream2=0L;
byte rc=0;
byte channel=0;
byte bitcounter=0;
unsigned long temperature=0;
byte humidity=0;
//==================================================================================
// get all the bits we need (40 bits)
for(int x=2;x < AURIOLV3_PULSECOUNT;x+=2) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 650) return false;
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3500) {
if (bitcounter < 16) {
bitstream1 = (bitstream1 << 1) | 0x1;
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
}
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false;
if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false;
if (bitcounter < 16) {
bitstream1 = (bitstream1 << 1);
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1);
}
}
}
//==================================================================================
// Perform sanity checks and prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
if (bitstream1 == 0) return false; // not seen the RF packet recently
if (bitstream2 == 0) return false;
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
rc = (bitstream1 >> 8) & 0xff ; // get rolling code
temperature = ((bitstream2)>>12) & 0xfff; // get 12 temperature bits
temperature = (temperature - 0x4c4) & 0xffff;
temperature = (((temperature) * 5) / 9) & 0xffff;
if (temperature > 3000) {
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
humidity = (bitstream2 >> 4) & 0xff ; // humidity
channel=(bitstream2) & 0x03; // channel number
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Auriol V3;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temperature); // temp
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", humidity); // hum
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_044

105
Plugins/Plugin_045.c Normal file
View File

@@ -0,0 +1,105 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-45 Auriol ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the Auriol protocol (Z31743) and other devices following the same protocol (Rubicson?)
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Auriol Weatherstation outdoor unit, (32/36 bits, 433 MHz).
* Auriol Message Format:
* 1101 0110 1000 0000 1101 1111 1111 0000
* AAAA AAAA BCCC DDDD DDDD DDDD EEEE FFFG
*
* A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number)
* B = Battery status, 1=OK, 0=LOW
* C = Always 000
* 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)
* E = Unknown
* F = Unknown
* G = sum of all bits xored together
*
* Sample:
* 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;
* 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;
\*********************************************************************************************/
#define AURIOL_PULSECOUNT 66
#ifdef PLUGIN_045
boolean Plugin_045(byte function, char *string) {
if (RawSignal.Number != AURIOL_PULSECOUNT) return false;
unsigned long bitstream=0L;
unsigned int temperature=0;
byte rc=0;
byte bat=0;
byte checksumcalc=0;
//==================================================================================
if (RawSignal.Number == AURIOL_PULSECOUNT) {
for(int x=2;x < AURIOL_PULSECOUNT;x+=2) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; // inbetween pulses should not exceed a length of 550
if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) { // long bit = 1
bitstream = (bitstream << 1) | 0x1;
} else {
if(RawSignal.Pulses[x]*RawSignal.Multiply < 1600) return false; // pulse length too short to be valid?
if(RawSignal.Pulses[x]*RawSignal.Multiply > 2200) return false; // pulse length between 2000 - 3000 is invalid
bitstream = (bitstream << 1); // short bit = 0
}
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ) {
// not seen the RF packet recently
if (bitstream == 0) return false; // Perform a sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
for (int i=1;i<32;i++) { // Perform a checksum calculation to make sure the received packet is a valid Auriol packet
checksumcalc=checksumcalc^ ((bitstream>>i)&0x01);
}
if (checksumcalc != (bitstream&0x01) ) return false;
rc = (bitstream >> 20) & 0x07; // get 3 bits to perform another sanity check
if (rc != 0) return false; // selected bits should always be 000
//==================================================================================
bat= (bitstream >> 23) & 0x01; // get battery strength indicator
temperature = (bitstream >> 8) & 0xfff; // get 12 temperature bits
rc = (bitstream >> 24) & 0xff; // get rolling code
if (temperature > 3000) {
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Auriol;ID=00")); // Label
PrintHexByte(rc);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temperature);
Serial.print( pbuffer );
if (bat==0) { // battery status
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_045

141
Plugins/Plugin_046.c Normal file
View File

@@ -0,0 +1,141 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-46 Auriol / Xiron ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the Auriol protocol for sensor type Z31055A-TX and Xiron
* Watshome YT6018-2 (From Fujian Youtong)
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Auriol and Xiron Weatherstation outdoor unit, (36 bits, 433 MHz).
*
* Auriol Message Format:
* 10100100 10 00 000011100110 1111 00000000 Temp = 23.60
* AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF
* A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number)
* B = Battery status indicator on highest bit, 1=OK 0=LOW
* C = Always 00 (Most likely channel number)
* 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)
* E = Always 1111 ?
* F = Always 0000 0000 ?
*
* Xiron Message Format:
* 01101110 10 00 000011101101 1111 00110011
* AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF
* ID ?? Ch Temperature ? Humidity
*
* A = ID (Rolling Code, changes after battery replacement)
* B = Battery status indicator on highest bit, 1=OK 0=LOW
* C = Channel (1,2,3)
* 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)
* E = Always 1111 ?
* F = Humidity
*
*
* Sample:
* 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,
\*********************************************************************************************/
#define PLUGIN_ID 46
#define AURIOLV2_PULSECOUNT 74
#ifdef PLUGIN_046
boolean Plugin_046(byte function, char *string) {
if (RawSignal.Number != AURIOLV2_PULSECOUNT) return false;
unsigned long bitstream1=0L;
unsigned long bitstream2=0L;
byte rc=0;
byte bat=0;
int temperature=0;
int humidity=0;
byte channel=0;
byte bitcounter=0;
byte type=0;
//==================================================================================
// get all the bits we need (36 bits)
for(int x=2;x < AURIOLV2_PULSECOUNT;x+=2) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 700) return false;
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1400) {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false;
if (bitcounter < 24) {
bitstream1 = (bitstream1 << 1) | 0x1;
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
}
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1100) return false;
if (RawSignal.Pulses[x]*RawSignal.Multiply < 500) return false;
if (bitcounter < 24) {
bitstream1 = (bitstream1 << 1);
bitcounter++; // only need to count the first 10 bits
} else {
bitstream2 = (bitstream2 << 1);
}
}
}
//==================================================================================
if (bitstream1==0) return false; // Perform sanity check
if ((bitstream2 & 0xF00) != 0xF00) return false; // check if 'E' has all 4 bits set
if ((bitstream2 & 0xfff) != 0xF00) {
type=1; // Xiron
if (RawSignal.Pulses[0] != PLUGIN_ID) {
return false; // only accept plugin_001 translated Xiron packets
}
} else {
type=0; // Auriol
rc = (bitstream1 >> 12) & 0x07; // get 3 bits
if (rc != 0) return false; // should always be '000'
}
//==================================================================================
bat= (bitstream1 >> 15) & 0x01; // get battery strength indicator
rc = (bitstream1 >> 16) & 0xff; // get rolling code
channel = ((bitstream1 >> 12) & 0x3)+1; // channel indicator
temperature = (bitstream1) & 0xfff; // get 12 temperature bits
if (temperature > 3000) {
temperature=4096-temperature; // fix for minus temperatures
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
temperature=temperature | 0x8000; // turn highest bit on for minus values
} else {
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
}
if (type == 1) {
humidity = (bitstream2) & 0xff ; // humidity
}
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
if (type == 0) {
Serial.print(F(";Auriol V2;ID=")); // Label
} else {
Serial.print(F(";Xiron;ID=")); // Label
}
PrintHexByte(rc);
PrintHexByte(channel);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temperature);
Serial.print( pbuffer );
if (type == 1) {
sprintf(pbuffer, "HUM=%02d;", humidity);
Serial.print( pbuffer );
}
if (bat==0) { // battery status
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_046

974
Plugins/Plugin_048.c Normal file
View File

@@ -0,0 +1,974 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-48 Oregon V1/2/3 ##
//#######################################################################################################
/*********************************************************************************************\
* This protocol takes care of receiving Oregon Scientific outdoor sensors that use the V1, V2 and V3 protocol
*
* models: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X,
* THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500,
* THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122
* THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave, RGR928
* UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, RGR126, BTHG968
*
* Author : StuntTeam, Thibaut Girka
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v0.1 beta
*********************************************************************************************
* Technical information:
* Supports Oregon V1, V2 and V3 protocol messages
* Core code from https://github.com/Cactusbone/ookDecoder/blob/master/ookDecoder.ino
* Copyright (c) 2014 Charly Koza cactusbone@free.fr Copyright (c) 2012 Olivier Lebrun olivier.lebrun@connectingstuff.net
* Copyright (c) 2012 Dominique Pierre (zzdomi) Copyright (c) 2010 Jean-Claude Wippler jcw@equi4.com
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
\*********************************************************************************************/
#define OSV3_PULSECOUNT_MIN 50 // 126
#define OSV3_PULSECOUNT_MAX 290 // make sure to check the max length in plugin 1 as well..!
#ifdef PLUGIN_048
/*
* Many devices use 160 bits, known exceptions:
* 0xEA4c 136 bits // TH132N
* 0xEA7c 240 bits // UV138
* 0x5A5D / 1A99 176 bits // THGR918 / WTGR800
* 0x5A6D 192 bits // BTHR918N
* 0x8AEC 192 bits // RTGR328N
* 0x9AEC 208 bits // RTGR328N
* 0xDA78 144 bits // UVN800
* 0x2A19 184 bits // RCR800
* 0x2A1d 168 bits // WGR918
*/
// =====================================================================================================
class DecodeOOK {
protected:
byte total_bits, bits, flip, state, pos, data[25];
virtual char decode(word width) = 0;
public:
enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };
// -------------------------------------
DecodeOOK() { resetDecoder(); }
// -------------------------------------
bool nextPulse(word width) {
if (state != DONE)
switch (decode(width)) {
case -1: resetDecoder(); break;
case 1: done(); break;
}
return isDone();
}
// -------------------------------------
bool isDone() const { return state == DONE; }
// -------------------------------------
const byte* getData(byte& count) const {
count = pos;
return data;
}
// -------------------------------------
void resetDecoder() {
total_bits = bits = pos = flip = 0;
state = UNKNOWN;
}
// -------------------------------------
// add one bit to the packet data buffer
// -------------------------------------
virtual void gotBit(char value) {
total_bits++;
byte *ptr = data + pos;
*ptr = (*ptr >> 1) | (value << 7);
if (++bits >= 8) {
bits = 0;
if (++pos >= sizeof data) {
resetDecoder();
return;
}
}
state = OK;
}
// -------------------------------------
// store a bit using Manchester encoding
// -------------------------------------
void manchester(char value) {
flip ^= value; // manchester code, long pulse flips the bit
gotBit(flip);
}
// -------------------------------------
// move bits to the front so that all the bits are aligned to the end
// -------------------------------------
void alignTail(byte max = 0) {
// align bits
if (bits != 0) {
data[pos] >>= 8 - bits;
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] >> bits) | (data[i + 1] << (8 - bits));
bits = 0;
}
// optionally shift bytes down if there are too many of 'em
if (max > 0 && pos > max) {
byte n = pos - max;
pos = max;
for (byte i = 0; i < pos; ++i)
data[i] = data[i + n];
}
}
// -------------------------------------
void reverseBits() {
for (byte i = 0; i < pos; ++i) {
byte b = data[i];
for (byte j = 0; j < 8; ++j) {
data[i] = (data[i] << 1) | (b & 1);
b >>= 1;
}
}
}
// -------------------------------------
void reverseNibbles() {
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] << 4) | (data[i] >> 4);
}
// -------------------------------------
void done() {
while (bits)
gotBit(0); // padding
state = DONE;
}
};
/*
class OregonDecoderV1_org : public DecodeOOK {
public:
OregonDecoderV1_org() {}
virtual char decode(word width) {
if (200 <= width && width < 1200) {
byte w = width >= 700;
switch (state) {
case UNKNOWN:
if (w == 0)
++flip;
else if (10 <= flip && flip <= 50) {
flip = 1;
manchester(1);
}
else
return -1;
break;
case OK:
if (w == 0)
state = T0;
else
manchester(1);
break;
case T0:
if (w == 0)
manchester(0);
else
return -1;
break;
}
return 0;
}
if (width >= 2500 && pos >= 9)
return 1;
return -1;
}
};
*/
class OregonDecoderV1 : public DecodeOOK {
public:
OregonDecoderV1() {}
virtual char decode(word width) {
if (900 <= width && width < 3400) {
byte w = width >= 2000;
switch (state) {
case UNKNOWN: // Detect preamble
if (w == 0)
++flip;
else
return -1;
break;
case OK:
if (w == 0)
state = T0;
else
manchester(1);
break;
case T0:
if (w == 0)
manchester(0);
else
return -1;
break;
default: // Unexpected state
return -1;
}
return (pos == 4) ? 1 : 0; // Messages are fixed-size
}
if (width >= 3400) {
if (flip < 10 || flip > 50)
return -1; // No preamble
switch (state) {
case UNKNOWN:
// First sync pulse, lowering edge
state = T1;
break;
case T1:
// Second sync pulse, lowering edge
state = T2;
break;
case T2:
// Last sync pulse, determines the first bit!
if (width <= 5900) {
state = T0;
flip = 1;
} else {
state = OK;
flip = 0;
manchester(0);
}
break;
}
return 0;
}
return -1;
}
};
class OregonDecoderV2 : public DecodeOOK {
public:
OregonDecoderV2() {}
// -------------------------------------
// add one bit to the packet data buffer
// -------------------------------------
virtual void gotBit(char value) {
if (!(total_bits & 0x01))
{
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
}
total_bits++;
pos = total_bits >> 4;
if (pos >= sizeof data) {
resetDecoder();
return;
}
state = OK;
}
// -------------------------------------
virtual char decode(word width) {
//if (200 <= width && width < 1200) {
// byte w = width >= 675;
if (150 <= width && width < 1200) {
byte w = width >= 600;
switch (state) {
case UNKNOWN:
if (w != 0) {
// Long pulse
++flip;
}
else if (w == 0 && 24 <= flip) {
// Short pulse, start bit
flip = 0;
state = T0;
}
else {
// Reset decoder
return -1;
}
break;
case OK:
if (w == 0) {
// Short pulse
state = T0;
}
else {
// Long pulse
manchester(1);
}
break;
case T0:
if (w == 0) {
// Second short pulse
manchester(0);
}
else {
// Reset decoder
return -1;
}
break;
}
}
else if (width >= 2500 && pos >= 8) {
return 1;
}
else {
return -1;
}
return total_bits == 160 ? 1 : 0;
}
};
class OregonDecoderV3 : public DecodeOOK {
public:
OregonDecoderV3() {}
// -------------------------------------
// add one bit to the packet data buffer
// -------------------------------------
virtual void gotBit(char value) {
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
total_bits++;
pos = total_bits >> 3;
if (pos >= sizeof data) {
resetDecoder();
return;
}
state = OK;
}
// -------------------------------------
virtual char decode(word width) {
if (200 <= width && width < 1200) {
byte w = width >= 675;
switch (state) {
case UNKNOWN:
if (w == 0)
++flip;
else if (32 <= flip) {
flip = 1;
manchester(1);
}
else
return -1;
break;
case OK:
if (w == 0)
state = T0;
else
manchester(1);
break;
case T0:
if (w == 0)
manchester(0);
else
return -1;
break;
}
}
else {
return -1;
}
return total_bits == 80 ? 1 : 0;
}
};
OregonDecoderV1 orscV1;
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;
volatile word pulse;
// =====================================================================================================
// =====================================================================================================
byte osdata[13];
void reportSerial(class DecodeOOK& decoder) {
byte pos;
const byte* data = decoder.getData(pos);
for (byte i = 0; i < pos; ++i) {
if (i < 13) osdata[i]=data[i];
}
decoder.resetDecoder();
}
// =====================================================================================================
// calculate a packet checksum by performing a
byte checksum(byte type, int count, byte check) {
byte calc=0;
// type 1, add all nibbles, deduct 10
if (type == 1) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
} else
// type 2, add all nibbles up to count, add the 13th nibble , deduct 10
if (type == 2) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc += (osdata[6]&0xF);
calc=calc-10;
} else
// type 3, add all nibbles up to count, subtract 10 only use the low 4 bits for the compare
if (type == 3) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
calc=(calc&0x0f);
} else
if (type == 4) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
}
if (check == calc ) return 0;
return 1;
}
// =====================================================================================================
boolean Plugin_048(byte function, char *string) {
if ((RawSignal.Number < OSV3_PULSECOUNT_MIN) || (RawSignal.Number > OSV3_PULSECOUNT_MAX) ) return false;
byte rc=0;
byte found = 0;
int temp = 0;
byte hum = 0;
int comfort = 0;
int baro = 0;
int forecast = 0;
int uv = 0;
int wdir = 0;
int wspeed = 0;
int awspeed = 0;
int rain = 0;
int raintot = 0;
word p = pulse;
// ==================================================================================
for (int x = 1; x < RawSignal.Number; x++) {
//for (int x = 0; x < RawSignal.Number; x++) {
p = RawSignal.Pulses[x]*RawSignal.Multiply;
if (p != 0) {
if (orscV1.nextPulse(p)) {
reportSerial(orscV1);
found=1;
}
if (orscV2.nextPulse(p)) {
reportSerial(orscV2);
found=2;
}
if (orscV3.nextPulse(p)) {
reportSerial(orscV3);
found=3;
}
}
}
if (found == 0) return false;
// ==================================================================================
// Protocol and device info:
// ==================================================================================
//Serial.print("Oregon V");
//Serial.print(found);
//Serial.print(": ");
//for(byte x=0; x<13;x++) {
// Serial.print( osdata[x],HEX );
// Serial.print((" "));
//}
//Serial.println();
//Serial.print("Oregon ID=");
unsigned int id=(osdata[0]<<8)+ (osdata[1]);
rc=osdata[0];
//Serial.println(id,HEX);
// ==================================================================================
// Process the various device types:
// ==================================================================================
// Oregon V1 packet structure
// SL-109H, AcuRite 09955
// TEMP + CRC
// ==================================================================================
// 8487101C
// 84+87+10=11B > 1B+1 = 1C
if (found==1) { // OSV1
int sum = osdata[0]+osdata[1]+osdata[2]; // max. value is 0x2FD
sum= (sum &0xff) + (sum>>8); // add overflow to low byte
if (osdata[3] != (sum & 0xff) ) {
//Serial.println("CRC Error");
return false;
}
// -------------
//temp = ((osdata[2]>>4) * 100) + ((osdata[1] & 0x0F) * 10) + ((osdata[1] >> 4));
//if ((osdata[2] & 0x02) == 2) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
temp = ((osdata[2] & 0x0F) * 100) + ((osdata[1] >> 4) * 10) + ((osdata[1] & 0x0F));
if ((osdata[2] & 0x20) == 0x20) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";OregonV1;ID=00")); // Label
//sprintf(pbuffer, "ID=00%02x;", rc & 0xCF);
PrintHexByte((rc)&0xcf); // rolling code + channel
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temp);
Serial.print( pbuffer );
if (osdata[2] & 0x80) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
}
// ==================================================================================
// ea4c Outside (Water) Temperature: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131
// TEMP + BAT + CRC
// ca48 Pool (Water) Temperature: THWR800
// 0a4d Indoor Temperature: THR128, THR138, THC138
// ==================================================================================
// OSV2 EA4C20725C21D083 // THN132N
// OSV2 EA4C101360193023 // THN132N
// OSV2 EA4C40F85C21D0D4 // THN132N
// OSV2 EA4C20809822D013
// 0123456789012345
// 0 1 2 3 4 5 6 7
if(id == 0xea4c || id == 0xca48 || id == 0x0a4d) {
byte sum=(osdata[7]&0x0f) <<4;
sum=sum+(osdata[6]>>4);
if ( checksum(2,6, sum) !=0) { // checksum = all nibbles 0-11+13 results is nibbles 15 <<4 + 12
//Serial.println("CRC Error");
return false;
}
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon Temp;ID=")); // Label
//PrintHexByte(rc);
PrintHexByte(osdata[3]);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temp);
Serial.print( pbuffer );
//if ((osdata[3] & 0x0F) >= 4) {
if ((osdata[4] & 0x0c) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// 1a2d Indoor Temp/Hygro: THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, THGR268, THGR122X
// 1a3d Outside Temp/Hygro: THGR918, THGRN228NX, THGN500
// fa28 Indoor Temp/Hygro: THGR810
// *aac Outside Temp/Hygro: RTGR328N
// ca2c Outside Temp/Hygro: THGR328N
// fab8 Outside Temp/Hygro: WTGR800
// TEMP + HUM sensor + BAT + CRC
// ==================================================================================
// OSV2 AACC13783419008250AD[RTGR328N,...] Id:78 ,Channel:0 ,temp:19.30 ,hum:20 ,bat:10
// OSV2 1A2D40C4512170463EE6[THGR228N,...] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
// OSV2 1A2D1072512080E73F2C[THGR228N,...] Id:72 ,Channel:1 ,temp:20.50 ,hum:78 ,bat:90
// OSV2 1A2D103742197005378E // THGR228N
// OSV3 FA28A428202290834B46 //
// OSV3 FA2814A93022304443BE // THGR810
// OSV2 1A2D1002 02060552A4C
// 1A3D10D91C273083..
// 1A3D10D90C284083..
// 01234567890123456789
// 0 1 2 3 4 5
// F+A+2+8+1+4+A+9+3+0+2+2+3+0+4+4=4d-a=43
if(id == 0xfa28 || id == 0x1a2d || id == 0x1a3d || (id&0xfff)==0xACC || id == 0xca2c || id == 0xfab8 ) {
if ( checksum(1,8,osdata[8]) !=0) return false; // checksum = all nibbles 0-15 results is nibbles 16.17
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// -------------
hum = ((osdata[7] & 0x0F)*16)+ (osdata[6] >> 4);
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon TempHygro;ID=")); // Label
PrintHexByte(osdata[1]);
PrintHexByte(osdata[3]);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temp);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", hum);
Serial.print( pbuffer );
if ((osdata[4] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// 5a5d Indoor Temp/Hygro/Baro: Huger - BTHR918
// 5a6d Indoor Temp/Hygro/Baro: BTHR918N, BTHR968. BTHG968
// TEMP + HUM + BARO + FORECAST + BAT
// NO CRC YET
// ==================================================================================
// 5A 6D 00 7A 10 23 30 83 86 31
// 5+a+6+d+7+a+1+2+3+3+8+3=47 -a=3d +8=4f +8+6=55
// 5+a+6+d+7+a+1+2+3+3=3c-a=32
// 5+a+6+d+7+a+1+2+3+3+0+8+3+8+6=55 -a =4b +3=4e !=1
// 0 1 2 3 4 5 6 7 8 9
if(id == 0x5a6d || id == 0x5a5d || id == 0x5d60) {
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// -------------
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
//0: normal, 4: comfortable, 8: dry, C: wet
int tmp_comfort = osdata[7] >> 4;
if (tmp_comfort == 0x00)
comfort=0;
else if (tmp_comfort == 0x04)
comfort=1;
else if (tmp_comfort == 0x08)
comfort=2;
else if (tmp_comfort == 0x0C)
comfort=3;
// -------------
baro = (osdata[8] + 856); // max value = 1111 / 0x457
//2: cloudy, 3: rainy, 6: partly cloudy, C: sunny
int tmp_forecast = osdata[9]>>4;
if (tmp_forecast == 0x02)
forecast = 3;
else if (tmp_forecast == 0x03)
forecast = 4;
else if (tmp_forecast == 0x06)
forecast = 2;
else if (tmp_forecast == 0x0C)
forecast = 1;
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon BTHR;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";TEMP=%04x;", temp);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", hum);
Serial.print( pbuffer );
sprintf(pbuffer, "HSTATUS=%d;", comfort);
Serial.print( pbuffer );
sprintf(pbuffer, "BARO=%04x;", baro);
Serial.print( pbuffer );
sprintf(pbuffer, "BFORECAST=%d;", forecast);
Serial.print( pbuffer );
//below is not correct, and for now discarded
//if (((osdata[3] & 0x0F) & 0x04) != 0) {
// Serial.print("BAT=LOW;");
//} else {
// Serial.print("BAT=OK;");
//}
Serial.println();
} else
// ==================================================================================
// 2914 Rain Gauge:
// 2d10 Rain Gauge:
// 2a1d Rain Gauge: RGR126, RGR682, RGR918, RGR928, PCR122
// 2A1D0065502735102063
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0=3e-a=34 != 63
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0+6=44-a=3A
// ==================================================================================
if(id == 0x2a1d || id == 0x2d10 || id == 0x2914) { // Rain sensor
//Checksum - add all nibbles from 0 to 8, subtract 9 and compare
/*
int cs = 0;
for (byte i = 0; i < pos-2; ++i) { //all but last byte
cs += data[i] >> 4;
cs += data[i] & 0x0F;
}
int csc = (data[8] >> 4) + ((data[9] & 0x0F)*16);
cs -= 9; //my version as A fails?
Serial.print(csc);
Serial.print(" vs ");
Serial.println(cs);
*/
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon Rain;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[3]);
// ----------------------------------
sprintf(pbuffer, ";RAIN=%04x;", rain);
Serial.print( pbuffer );
sprintf(pbuffer, "RAINTOT=%04x;", raintot);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// 2a19 Rain Gauge: PCR800
// RAIN + BAT + CRC
// ==================================================================================
// OSV3 2A19048E399393250010
// 01234567890123456789
// 0 1 2 3 4 5 6 7 8 9
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
if(id == 0x2a19) { // Rain sensor
int sum = (osdata[9] >> 4);
if ( checksum(3,9,sum) !=0) { // checksum = all nibbles 0-17 result is nibble 18
//Serial.print("CRC Error, ");
return false;
}
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
//Serial.print(" RainTotal=");
//raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
//Serial.print(raintot);
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon Rain2;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[4]);
// ----------------------------------
sprintf(pbuffer,";RAIN=%04x;", rain);
Serial.print( pbuffer );
//sprintf(pbuffer, "RAINTOT=%04x;", raintot);
//Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// 1a89 Anemometer: WGR800
// WIND DIR + SPEED + AV SPEED + CRC
// ==================================================================================
// OSV3 1A89048800C026400543
// OSV3 1A89048800C00431103B
// OSV3 1a89048848c00000003e W
// OSV3 1a890488c0c00000003e E
// 1A89042CB0C047000147
// 0 1 2 3 4 5 6 7 8 9
// 1+A+8+9+0+4+8+8+0+0+C+0+0+4+3+1+1+0=45-a=3b
if(id == 0x1a89) { // Wind sensor
if ( checksum(1,9,osdata[9]) !=0) return false;
wdir=((osdata[4] >> 4) & 0x0f);
// -------------
wspeed = (osdata[6] >> 4) * 10;
wspeed = wspeed + (osdata[6] &0x0f) * 100;
wspeed = wspeed + (osdata[5] &0x0f);
// -------------
awspeed = (osdata[8] >> 4) * 100;
awspeed = awspeed + (osdata[7] &0x0f) * 10;
awspeed = awspeed + (osdata[7] >> 4);
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon Wind;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";WINDIR=%04d;", wdir);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", wspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// 3a0d Anemometer: Huger-STR918, WGR918
// 1984 Anemometer:
// 1994 Anemometer:
// WIND DIR + SPEED + AV SPEED + BAT + CRC
// 3A0D006F400800000031
// ==================================================================================
if(id == 0x3A0D || id == 0x1984 || id == 0x1994 ) {
if ( checksum(1,9,osdata[9]) !=0) {
//Serial.print("CRC Error, ");
return false;
}
wdir = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F * 10) ) + (osdata[4] >> 4);
wdir=wdir / 22.5;
wspeed = ((osdata[7] & 0x0F) * 100) + ((osdata[6]>>4) * 10) + ((osdata[6] & 0x0F)) ;
awspeed = ((osdata[8]>>4) * 100) + ((osdata[8] & 0x0F) * 10)+((osdata[7] >>4)) ;
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon Wind2;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";WINDIR=%04d;", wdir);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", wspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// ea7c UV Sensor: UVN128, UV138
// UV + BAT
// NO CRC YET
// ==================================================================================
if(id == 0xea7c) {
uv=((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
Serial.print(uv);
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon UVN128/138;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";UV=%04x;", uv);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// da78 UV Sensor: UVN800
// UV
// NO CRC YET
// ==================================================================================
if( id == 0xda78) {
uv=(osdata[6] & 0xf0) + (osdata[5] &0x0f) ;
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Oregon UVN800;ID=")); // Label
PrintHexByte(rc);
PrintHexByte(osdata[2]);
// ----------------------------------
sprintf(pbuffer, ";UV=%04x;", uv);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print(F("BAT=LOW;"));
} else {
Serial.print(F("BAT=OK;"));
}
Serial.println();
} else
// ==================================================================================
// *aec Date&Time: RTGR328N
// 8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
// 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9+1=6B -A=61 != 30
// 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9=6a-A=60 0=0
// NO CRC YET
//20;06;Oregon Unknown;DEBUG=8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
//20;20;Oregon Unknown;DEBUG=8A EC 13 FC 40 33 44 91 11 30 0 0 0 ;
// OSV3 2A19048E399393250010
// 01234567890123456789
// 0 1 2 3 4 5 6 7 8 9
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
// ==================================================================================
// 8AEA1378077214924242C16CBD 21:49 29/04/2014
// 0 1 2 3 4 5 6 7 8 9 0 1 2
// 8+A+E+A+1+3+7+8+0+7+7+2+1+4+9+2+4+2+4+2+C+1+6+C=88 != BD
// Date & Time
// ==================================================================================
// eac0 Ampere meter: cent-a-meter, OWL CM113, Electrisave
// ==================================================================================
if(id == 0xeac0) {
//Serial.println("UNKNOWN LAYOUT");
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
// ----------------------------------
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
PrintHex8( osdata, 13);
Serial.println(";");
} else
// ==================================================================================
// 0x1a* / 0x2a* 0x3a** Power meter: OWL CM119
// ==================================================================================
// 0x628* Power meter: OWL CM180
// ==================================================================================
// OSV3 6284 3C 7801 D0
// OSV3 6280 3C 2801 A0A8BA05 00 00 ?? ?? ??
// ==================================================================================
// 1a99 Anemometer: WGTR800
// WIND + TEMP + HUM + CRC
// ==================================================================================
if(id == 0x1a99) { // Wind sensor
//Serial.println("UNKNOWN LAYOUT");
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
// ----------------------------------
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
PrintHex8( osdata, 13);
Serial.println(";");
} else
// ==================================================================================
if( (id&0xf00)==0xA00 ) { // Any Oregon sensor with id xAxx
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
// ----------------------------------
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
PrintHex8( osdata, 13);
Serial.println(";");
}
// ==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_048

78
Plugins/Plugin_060.c Normal file
View File

@@ -0,0 +1,78 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-060 AlarmSensor ##
//#######################################################################################################
/*********************************************************************************************\
* This protocol provides support for some Alarm sensors that are part of a Varel/Chubb/Ajax alarm
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical data:
* Devices send 25 pulses, first pulse is part of the start bit. Remaining bits are Manchester encoded, 24 bits
*
* The PCB contains a Holtec HT12E Encoder chip
* The PCB has two switch blocks: SW1 with switches 1-8 (Device code?)
* SW2 with switches 1-4 (House code?)
*
* Sample:
* 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;
* 1001101010101010 01100110
* 10000000 1010
\*********************************************************************************************/
#define ALARMPIRV2_PULSECOUNT 26
#define ALARMPIRV2_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV2_PULSEMAX 1000/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV2_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV2_PULSEMIN 250/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_060
boolean Plugin_060(byte function, char *string) {
if (RawSignal.Number != ALARMPIRV2_PULSECOUNT) return false;
unsigned long bitstream=0L;
byte data[3];
if (RawSignal.Pulses[1] > ALARMPIRV2_PULSESHORT) return false; // First pulse is start bit and should be short!
for(byte x=2;x < ALARMPIRV2_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMID) { // long pulse 800-875 (700-1000 accepted)
if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMAX) return false; // pulse too long
if (RawSignal.Pulses[x+1] > ALARMPIRV2_PULSEMID) return false; // invalid manchester code
bitstream = bitstream << 1;
} else { // short pulse 350-425 (250-550 accepted)
if (RawSignal.Pulses[x] < ALARMPIRV2_PULSEMIN) return false; // pulse too short
if (RawSignal.Pulses[x+1] < ALARMPIRV2_PULSEMID) return false; // invalid manchester code
bitstream = (bitstream << 1) | 0x1;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("X10;")); // Label
sprintf(pbuffer, "ID=%04x;", (bitstream)&0xffff);
Serial.print( pbuffer );
Serial.print(F("SWITCH=01;"));
Serial.print(F("CMD=ON;")); // this device does report movement only
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_060

93
Plugins/Plugin_061.c Normal file
View File

@@ -0,0 +1,93 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-061 AlarmSensor ##
//#######################################################################################################
/*********************************************************************************************\
* This protocol provides support for some chinese Alarm "gadgets" (Motion detectors and door/window contacts)
* Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technical data:
* Devices send 50 pulses. Manchester encoded, 25 bits
*
* PIR Motion detection unit:
* PCB contains 2 chips: biss0001 & ev1527
* BISS0001 = Micro Power PIR Motion Detector IC
* EV1527 = OTP Encoder, max. of 20 bits providing up to 1 million codes.
*
* Sample:
* Pulses=50, Pulses(uSec)=900,225,200,850,225,850,825,225,225,850,225,850,825,225,225,850,200,850,225,850,825,225,225,850,825,225,225,850,825,225,825,225,825,225,825,225,825,225,825,225,825,225,225,850,225,850,825,225,225,
* 100101100101100101011001100110101010101010010110
* 01101101 1101010000000110 6D D406
* 20;9A;DEBUG;Pulses=50;Pulses(uSec)=475,925,400,950,1150,175,400,950,375,950,1125,200,1100,225,1100,250,1075,250,1075,275,1050,275,1050,275,1050,275,1050,275,275,1050,1050,275,300,1050,1050,275,300,1050,300,1050,1050,275,300,1050,275,1050,1050,275,275;
* 010110010110101010101010101001100110010110010110
* 00100111 1111110101001001 27 FD49
* 11011000 0000001010110110 D8 02B6
* 1975,275,900,250,225,975,250,975,250,975,225,975,900,250,900,250,900,250,250,950,225,975,900,250,225,950,225,975,250,950,225,975,900,250,900,250,900,250,250,950,900,250,250,950,225,950,925,250,250;
* 101001010101101010010110010101011010100110010110
* 001111000110111100010110 3C6F16
* 110000111001000011101001 c390E9
\*********************************************************************************************/
#define ALARMPIRV1_PULSECOUNT 50
#define ALARMPIRV1_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMAX 1300/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMIN 150/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_061
boolean Plugin_061(byte function, char *string) {
if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) return false;
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
unsigned long bitstream=0L;
unsigned long bitstream2=0L;
//==================================================================================
for(byte x=2;x<=48;x=x+2) {
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID) {
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long
if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
bitstream = bitstream << 1;
} else {
if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short
if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
bitstream = (bitstream << 1) | 0x1;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
bitstream2=(bitstream)>>16;
if ( (bitstream2)==0xff) {
if ( (bitstream)&0xffff==0xff) return false;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("X10;")); // Label
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID
Serial.print( pbuffer );
Serial.print(F("SWITCH=01;"));
Serial.print(F("CMD=ON;")); // this device reports movement only
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // Plugin_061

76
Plugins/Plugin_062.c Normal file
View File

@@ -0,0 +1,76 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-062 Chuango AlarmSensors ##
//#######################################################################################################
/*********************************************************************************************\
* This protocol provides support for Chuango Alarm sensors (Motion detectors and door/window contacts)
* Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technical data:
* Devices send 50 pulses, 24 bits
*
* Sample:
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=1725,325,1650,325,1625,350,575,1400,1600,400,1525,475,450,1550,1475,500,1500,500,450,1475,550,1450,
* 550,1425,1600,400,525,1475,1500,450,1500,525,1475,500,425,1525,475,1475,500,1450,525,1450,1575,400,1550,425,1500,500,400;
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=1620,420,1530,450,1560,390,510,1440,1560,420,1530,420,450,1530,1440,510,1440,540,360,1500,450,1470,480,1470,1560,390,510,1440,1530,420,1500,480,1470,570,330,1590,390,1530,450,1500,480,1470,1530,420,1530,420,1530,420,450,3360;
* 101010011010011010010101100110101001010101101010 0
* 00010010 01110100 01111000 = 0x 12 74 78
\*********************************************************************************************/
#define ALARMPIRV1_PULSECOUNT 50
#define ALARMPIRV1_PULSEMID_062 700/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMAX_062 2000/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMIN_062 150/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_062
boolean Plugin_062(byte function, char *string) {
if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) return false;
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
unsigned long bitstream=0L;
//==================================================================================
for(byte x=2;x<=48;x=x+2) {
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID_062) {
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX_062) return false; // pulse too long
if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID_062) return false; // invalid pulse sequence 10/01
bitstream = (bitstream << 1) | 0x1;
} else {
if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN_062) return false; // pulse too short
if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID_062) return false; // invalid pulse sequence 10/01
bitstream = bitstream << 1;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Validity checks
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Chuango;")); // Label
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID
Serial.print( pbuffer );
Serial.print(F("SWITCH=02;"));
Serial.print(F("CMD=ON;")); // this device reports movement only
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // Plugin_062

86
Plugins/Plugin_063.c Normal file
View File

@@ -0,0 +1,86 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-063 Oregon PIR/LED/ALARM ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin provides support for Oregon PIR/LED/ALARM devices
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technical data:
* Devices send 50/52 pulses using typical Oregon bit encoding
*
* Sample:
* 570,390,570,360,570,360,540,360,540,360,570,360,570,330,570,330,570,330,570,330,570,330,570,360,540,360,540,360,1110,330,570,900,1110,900,540,330,570,330,1110,900,1110,360,540,360,540,900,1110,330,570,330,570,1620
* 00101110 10001000 = 2E88
\*********************************************************************************************/
#define OREGON_PLA_PULSECOUNT 52
#ifdef PLUGIN_063
boolean Plugin_063(byte function, char *string) {
//Serial.println("P003");
if (RawSignal.Pulses[0] != 63) return false; // Only accept RF packets converted by plugin 1
//Serial.println("P004");
RawSignal.Pulses[0]=0;
if ((RawSignal.Number < OREGON_PLA_PULSECOUNT-2) || (RawSignal.Number > OREGON_PLA_PULSECOUNT) ) return false;
unsigned long bitstream=0L;
//==================================================================================
//Serial.println("P005");
byte bits=0;
byte rfbit = 1;
if ( (RawSignal.Number < 50) || (RawSignal.Number > 52)) return false;
// Check preamble
for(byte x=1;x<28;x=x+2){
if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) return false;
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 600) return false;
}
// Check bits
for(byte x=29;x<=RawSignal.Number;x++){
if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) { // toggle bit value
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1600) break; // done..
rfbit = (~rfbit)&1;
bitstream = (bitstream << 1) | rfbit;
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++;
} else {
bitstream = (bitstream << 1) | rfbit; // short pulse keep bit value
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false;
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// calculate sensor and channel
bitstream=(bitstream)>>4;
bits=(bitstream)&0x3;
bits=bits+0x30; // signal 3 for plugin 63
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("X10;")); // Label
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID + channel number
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", bits); // channel number
Serial.print( pbuffer );
Serial.print(F("CMD=ON;")); // this device reports movement only
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // Plugin_063

163
Plugins/Plugin_070.c Normal file
View File

@@ -0,0 +1,163 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-70 Select Plus Wireless Doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of reception of the Select Plus wireless doorbell (Sold at Action for 6 euro's)
* PCB markings: Quhwa QH-C-CE-3V aka QH-832AC
* Also sold as "1 by One" and "Delta" wireless doorbell.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
*
* There are two known models:
* SelectPlus (200689103 - Black - Datecode:0614) also sold as "1 by One" (O00 QH-0031)
* PCB details: Quhwa, QH-C-CE-3V, 09.10.16, CPU: MC908T
* SelectPlus (200689101 - White - Datecode:0914)
* PCB details: Quhwa, QH-C-CE-3V, REV1.0, CPU: MC908T
*
* Each frame is 35 pulses long. It is composed of:
* 101011001010110010110011010 10101010
* The first block appears to be an unique ID
* The second block appears to be some kind of identifier which always is 0xAA (10101010)
* Converting the pulses into bits results in a 13 bit unique address and a 4 bit identifier:
*
* B) 1110000110011 0000 => 1C33 0 B)lack push button
* W) 1101110110100 0000 => 1BB4 0 W)hite push button
*
* Note: The transmitter sends 43 times the same packet when the bell button is pressed
* the retransmit is killed to prevent reporting the same press multiple times
*
* Sample:
* 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;
* 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;
* 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;
* 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;
\*********************************************************************************************/
#define SELECTPLUS_PULSECOUNT 36
#define SELECTPLUS_PULSEMID 650/RAWSIGNAL_SAMPLE_RATE
#define SELECTPLUS_PULSEMAX 2125/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_070
boolean Plugin_070(byte function, char *string) {
if (RawSignal.Number !=SELECTPLUS_PULSECOUNT) return false;
unsigned long bitstream=0L;
byte checksum=0;
//==================================================================================
// get bytes
for(byte x=2;x < SELECTPLUS_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x] < SELECTPLUS_PULSEMID) {
if (RawSignal.Pulses[x+1] < SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01
bitstream = (bitstream << 1);
} else {
if (RawSignal.Pulses[x] > SELECTPLUS_PULSEMAX) return false; // invalid pulse duration, pulse too long
if (RawSignal.Pulses[x+1] > SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01
bitstream = (bitstream << 1) | 0x1;
}
}
if (bitstream == 0) return false; // sanity check
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000)<millis()) || (SignalCRC != bitstream) ) {
SignalCRC=bitstream; // not seen the RF packet recently
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
// all bytes received, make sure checksum is okay
//==================================================================================
checksum = (bitstream)&0xf; // Second block
if (checksum != 0) return false; // last 4 bits should always be 0
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";SelectPlus;")); // Label
// ----------------------------------
sprintf(pbuffer, "ID=%04x;",((bitstream)>>4)&0xffff ); // ID
Serial.print( pbuffer );
Serial.print(F("SWITCH=1;CMD=ON;"));
Serial.print(F("CHIME=01;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
#endif // PLUGIN_070
#ifdef PLUGIN_TX_070
void SelectPlus_Send(unsigned long address);
boolean PluginTX_070(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0L;
//10;SELECTPLUS;001c33;1;OFF;
//012345678901234567890123456
if (strncasecmp(InputBuffer_Serial+3,"SELECTPLUS;",11) == 0) {
InputBuffer_Serial[12]=0x30;
InputBuffer_Serial[13]=0x78;
InputBuffer_Serial[20]=0;
bitstream=str2int(InputBuffer_Serial+12);
bitstream=bitstream << 4;
SelectPlus_Send(bitstream); // Send RF packet
success=true;
}
return success;
}
void SelectPlus_Send(unsigned long address) {
int fpulse = 364; // Pulse witdh in microseconds
int fretrans = 16; // number of RF packet retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x10000;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver (if wired that way) to protect against interference
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff=address;
// send SYNC 3P High
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
// end send SYNC
// Send command
for (int i = 0; i < 17;i++) { // SelectPlus address is only 13 bits, last 4 bits are always zero
// read data bit7
fdatabit = fsendbuff & fdatamask; // Get most left bit
fsendbuff = (fsendbuff << 1); // Shift left
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, LOW); // short low
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, HIGH); // long high
delayMicroseconds(fpulse * 3);
} else { // Write 1
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3); // long low
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1); // short high
}
}
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
if (nRepeat < fretrans) {
delayMicroseconds(fpulse * 16); // delay between RF transmits
}
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver
RFLinkHW();
}
#endif // PLUGIN_070

95
Plugins/Plugin_071.c Normal file
View File

@@ -0,0 +1,95 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-71 Plieger York doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the Plieger York Doorbell protocol
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Plieger York Doorbell, (66 pulses, 32 bits, 433 MHz).
* Plieger Message Format:
* 0000000001010101 00000000 00011100 c2 0x1c
* 00000011 c3 0x03
* 11100000 c1 0xE0
* -------- 8 bits chime number (3 chimes, can be changed with a jumped on the transmitter)
* -------- 8 bits always 0
* ---------------- 16 bits code which can be changed with a button on the inside of the transmitter
*
* Note: The transmitter sends two times the same packet when the bell button is pressed
* the retransmit is killed to prevent reporting the same press twice
*
* Sample packet: (Nodo Pulse timing)
* Pulses=66, Pulses(uSec)=700,250,275,725,750,250,275,725,750,250,275,725,750,250,275,725,750,250,
* 275,725,750,250,275,725,750,250,275,725,750,250,275,725,275,725,275,725,275,725,275,725,275,725,
* 275,725,275,725,275,725,275,725,275,725,275,725,750,250,750,250,750,250,275,725,275,725,225,
* 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;
* 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;
* 20;2E;Plieger York;ID=aaaa;SWITCH=1;CMD=ON;CHIME=02;
\*********************************************************************************************/
#define PLIEGER_PULSECOUNT 66
#define PLIEGER_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
#define PLIEGER_PULSEMAX 1900/RAWSIGNAL_SAMPLE_RATE
#ifdef PLUGIN_071
boolean Plugin_071(byte function, char *string) {
if (RawSignal.Number != PLIEGER_PULSECOUNT) return false;
unsigned long bitstream=0L;
unsigned int id=0;
byte chime=0;
//==================================================================================
// get all 32 bits
for(byte x=1;x <=PLIEGER_PULSECOUNT-2;x+=2) {
if(RawSignal.Pulses[x] > PLIEGER_PULSEMID) {
if (RawSignal.Pulses[x] > PLIEGER_PULSEMAX) return false;
if (RawSignal.Pulses[x+1] > PLIEGER_PULSEMID) return false; // Valid Manchester check
bitstream = (bitstream << 1) | 0x1;
} else {
if (RawSignal.Pulses[x+1] < PLIEGER_PULSEMID) return false; // Valid Manchester check
bitstream = (bitstream << 1);
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// first perform two checks to validate the data
if (((bitstream >> 8) &0xff) != 0x00) return false; // these 8 bits are always 0
chime=bitstream &0xff;
if (chime != 0x1c && chime !=0x03 && chime != 0xE0) return false; // the chime number can only have 3 values
//==================================================================================
id=(bitstream >> 16) & 0xffff; // get 16 bits unique address
if (chime == 0xE0) chime =1;
if (chime == 0x1C) chime =2;
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Plieger;")); // Label
// ----------------------------------
sprintf(pbuffer, "ID=%04x;", id); // ID
Serial.print( pbuffer );
Serial.print("SWITCH=1;CMD=ON;");
sprintf(pbuffer, "CHIME=%02x;", chime); // chime number
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
#endif // PLUGIN_071

139
Plugins/Plugin_072.c Normal file
View File

@@ -0,0 +1,139 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-072 Byron Wireless Doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of reception And sending of the Byron SX doorbell
*
* Author : Maurice Ruiter (Dodge)
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* 26 pulses, manchester code, 12 bits
*
* 111111110001
* AAAAAAAABBBB
*
* A = 8 bit Address
* B = chime number
* Valid chime numbers: 1,2,6,9,a,c,d,e ?
* ---------------------------------------------------------
* 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;
* 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;
* 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;
* 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;
\*********************************************************************************************/
#define PLUGIN_ID 72
#define BYRON_PULSECOUNT 26
#define BYRONSTART 3000
#define BYRONSPACE 250
#define BYRONLOW 350
#define BYRONHIGH 675
#ifdef PLUGIN_072
boolean Plugin_072(byte function, char *string){
if (RawSignal.Number !=BYRON_PULSECOUNT) return false;
if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 425) return false; // first pulse is start bit and must be short
unsigned long bitstream=0L;
//==================================================================================
for(byte x=2;x < BYRON_PULSECOUNT-1;x=x+2) {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 350) { // 200-275 (150-350 is accepted)
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 150) return false; // pulse too short
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 350) return false; // bad manchester code
bitstream = (bitstream << 1);
} else { // 500-575 (450-650 is accepted)
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 450) return false; // bad manchester code
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 450) return false; // pulse too short
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 650) return false; // pulse too long
bitstream = (bitstream << 1) | 0x1;
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ){
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Byron SX;")); // Label
// ----------------------------------
sprintf(pbuffer, "ID=%04x;", ((bitstream)>>4)&0xff);// ID
Serial.print( pbuffer );
Serial.print(F("SWITCH=1;CMD=ON;"));
sprintf(pbuffer, "CHIME=%02x;", (bitstream)&0xf); // chime number
Serial.print( pbuffer );
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_072
#ifdef PLUGIN_TX_072
boolean PluginTX_072(byte function, char *string) {
boolean success=false;
//10;BYRON;112233;01;OFF;
//01234567890123456789012
if (strncasecmp(InputBuffer_Serial+3,"BYRON;",5) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[15] != ';') return false;
InputBuffer_Serial[9]='0';
InputBuffer_Serial[10]='x';
InputBuffer_Serial[15]=0;
unsigned int tempbyte1=0;
tempbyte1=str2int(InputBuffer_Serial+9); // get parameter 1
int tempbyte2=0;
InputBuffer_Serial[14]='0';
InputBuffer_Serial[15]='x';
InputBuffer_Serial[18]=0;
tempbyte2=str2int(InputBuffer_Serial+14); // get parameter 2
//-----------------------------------------------
unsigned long bitstream1=tempbyte1; // address
unsigned long bitstream=tempbyte2; // ringtone
RawSignal.Multiply=50;
RawSignal.Repeats=20;
RawSignal.Delay=3; // 1 = 900 3=2825 5= 6= x
RawSignal.Pulses[1]=BYRONLOW/RawSignal.Multiply;
//RawSignal.Pulses[1]=BYRONSTART/RawSignal.Multiply;
for (byte x=17;x>=2;x=x-1) {
if ((bitstream1 & 1) == 1)
RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply;
else
RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply;
bitstream1 = bitstream1 >> 1;
}
for (byte x=25;x>=18;x=x-1) {
if ((bitstream & 1) == 1)
RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply;
else
RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply;
bitstream = bitstream >> 1;
}
//RawSignal.Pulses[26]=BYRONSTART/RawSignal.Multiply;
RawSignal.Pulses[26]=BYRONSPACE/RawSignal.Multiply;
RawSignal.Number=26;
RawSendRF();
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE;
success=true;
//-----------------------------------------------
}
return success;
}
#endif // PLUGIN_TX_072

166
Plugins/Plugin_073.c Normal file
View File

@@ -0,0 +1,166 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-073 Deltronic Doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of reception And sending of the Deltronic doorbell
*
* Author : Stuntteam / Jonas Jespersen
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technical information:
*
* The doorbell uses the UM3750 circuit which sends out a 12 bit signal:
*
* AAAAAAAA BBBB
*
* A = Always 1
* B = Address (Can be either 1, 5 or 9)
*
* Address 1
* 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;
* 000000001110
* Address 5
* 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;
* 000000001010
* Address 9
* 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;
* 000000000110
\*********************************************************************************************/
#define DELTRONIC_PULSECOUNT 26
#define LENGTH_DEVIATION 300
#ifdef PLUGIN_073
boolean Plugin_073(byte function, char *string) {
if (RawSignal.Number != DELTRONIC_PULSECOUNT) return false;
//==================================================================================
unsigned long bitstream = 0L;
unsigned long checksum = 0L;
//==================================================================================
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 675) return false; // First pulse is start bit and should be short!
for(byte x=2;x < DELTRONIC_PULSECOUNT;x=x+2) {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 800) { // long pulse (800-1275)
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1275) return false; // pulse too long to be valid
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 675) return false; // invalid manchestercode (10 01)
bitstream = (bitstream << 1) | 0x1; // 10 => 1 bit
} else { // short pulse
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 250) return false; // too short
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 700) return false; // invalid manchestercode (10 01)
bitstream = bitstream << 1; // 01 => 0 bit
}
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
// not seen the RF packet recently
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
// all bytes received, make sure checksum is okay
//==================================================================================
checksum = (bitstream) & 0x00000FF0L;
if (checksum != 0x00000FF0L) { // First 8 bits should always be 1
//Serial.println("crc error");
return false;
}
if (bitstream == 0) return false; // sanity check
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Deltronic;")); // Label
// ----------------------------------
sprintf(pbuffer, "ID=%04x;",(bitstream) & 0x0000000FL); // ID
Serial.print( pbuffer );
Serial.print(F("SWITCH=1;CMD=ON;"));
Serial.print(F("CHIME=01;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
#endif // PLUGIN_073
#ifdef PLUGIN_TX_073
void Deltronic_Send(unsigned long address);
boolean PluginTX_073(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0L;
//10;DELTRONIC;001c33;1;OFF;
//012345678901234567890123456
if (strncasecmp(InputBuffer_Serial+3,"DELTRONIC;",10) == 0) {
InputBuffer_Serial[11]=0x30;
InputBuffer_Serial[12]=0x78;
InputBuffer_Serial[19]=0;
bitstream=str2int(InputBuffer_Serial+11);
bitstream = (bitstream) | 0x00000FF0L;
Deltronic_Send(bitstream); // Send RF packet
success=true;
}
return success;
}
void Deltronic_Send(unsigned long address) {
byte repeatTimes = 16;
byte repeat, index;
int periodLong, periodSync;
unsigned long bitmask;
int period = 640;
periodLong = 2 * period;
periodSync = 36 * period;
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver (if wired that way) to protect against interference
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
// Send seperator
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(period);
// Send sync
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(periodSync);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(period);
for(repeat = 0; repeat < repeatTimes; repeat++) {
bitmask = 0x00000800L;
for (index = 0; index < 12; index++) {
if (address & bitmask) {
// Send 1
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(periodLong);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(period);
} else {
// Send 0
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(period);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(periodLong);
}
bitmask >>= 1;
}
// Send sync
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(periodSync);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(period);
}
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver
RFLinkHW();
}
#endif // PLUGIN_TX_073

192
Plugins/Plugin_074.c Normal file
View File

@@ -0,0 +1,192 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-74: RL-02 Digital Doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of sending and receiving the RL-02 Digital Doorbell protocol.
*
* Author : Jonas Jespersen
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical information:
*
* The RL-02 Digital Doorbell uses a protocol similar to PT2262 which send 12 bits that can be either
* 1, 0 or f (float).
*
* The doorbell transmitter has 2 buttons; One for ringing the doorbell and a button inside the transmitter
* for changing the chime. Everytime the change chime button is pressed the doorbell toggles through a number
* of available chimes, and when ring button is pressed the chime last selected with the change chime button
* will sound.
*
* AAAAAAAAAAA B
*
* A = Always f0ff0f0ffff
* B = f or 1 (f = Change chime button, 1 = Ring button)
*
* Ring:
* 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;
*
* Change chime:
* 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;
\*********************************************************************************************/
#define RL02_CodeLength 12
#define RL02_T 125 // 175 uS
#ifdef PLUGIN_074
boolean Plugin_074(byte function, char *string) {
if (RawSignal.Number != (RL02_CodeLength * 4) + 2) return false;
unsigned long bitstream = 0L;
unsigned long checksum = 0L;
int i, j;
boolean error = false;
// ==========================================================================
for (i = 0; i < RL02_CodeLength; i++) {
j = (RL02_T * 2) / RAWSIGNAL_SAMPLE_RATE;
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
bitstream = (bitstream >> 1); // 0
} else
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
bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // float
} else
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
bitstream = (bitstream >> 1); // 1
} else {
if (i == 0) {
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
bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // 1
} else {
error = true;
}
} else {
error = true;
}
}
}
// ==========================================================================
// all bytes received, make sure packet is valid and checksum is okay
// ==========================================================================
if (error == true) return false;
if (bitstream == 0) return false; // sanity check
checksum = (bitstream) & 0x000007FFL;
if (checksum != 0x000007ADL) return false;
if (bitstream == 0) return false; // sanity check
// ==========================================================================
// ----------------------------------
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
Serial.print(F(";Byron MP;")); // Label
// ----------------------------------
sprintf(pbuffer, "ID=%04x;", (bitstream & 0x00000800L) ? 1 : 0); // ID: 0 = Ring button, 1 = Change chime button
Serial.print( pbuffer );
Serial.print(F("SWITCH=1;CMD=ON;"));
Serial.print(F("CHIME=01;"));
Serial.println();
// ----------------------------------
RawSignal.Repeats=true;
RawSignal.Number=0;
return true;
}
#endif //PLUGIN_074
#ifdef PLUGIN_TX_074
void RL02_Send(unsigned long address);
boolean PluginTX_074(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0;
//10;Byron MP;001c33;1;OFF;
//012345678901234567890123456
if (strncasecmp(InputBuffer_Serial+3,"BYRON MP;",9) == 0) {
InputBuffer_Serial[10]=0x30;
InputBuffer_Serial[11]=0x78;
InputBuffer_Serial[18]=0;
bitstream=str2int(InputBuffer_Serial+10);
bitstream = ((bitstream) << 11) | 0x000007ADL;
RL02_Send(bitstream); // Send RF packet
success=true;
}
return success;
}
void RL02_Send(unsigned long address) {
int fpulse = 175; // Pulse witdh in microseconds
int fretrans = 7; // Number of code retransmissions
uint32_t fdatabit;
uint32_t fdatamask = 0x00000001;
uint32_t fsendbuff;
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
fsendbuff = address;
// Send command
for (int i = 0; i < 11; i++) { // RL-02 packet is 12 bits
// read data bit
fdatabit = fsendbuff & fdatamask; // Get most right bit
fsendbuff = (fsendbuff >> 1); // Shift right
// PT2262 data can be 0, 1 or float.
if (fdatabit != fdatamask) { // Write 0
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
} else { // Write float
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
}
fdatabit = fsendbuff & fdatamask; // Get most right bit
// Send last bit. Can be either 1 or float
if (fdatabit != fdatamask) { // Write 1
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse);
} else { // Write float
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 3);
digitalWrite(PIN_RF_TX_DATA, LOW);
delayMicroseconds(fpulse * 1);
}
// Send sync bit
digitalWrite(PIN_RF_TX_DATA, HIGH);
delayMicroseconds(fpulse * 1);
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
delayMicroseconds(fpulse * 31);
}
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
RFLinkHW();
}
#endif // PLUGIN_TX_074

143
Plugins/Plugin_075.c Normal file
View File

@@ -0,0 +1,143 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-75 Lidl doorbell ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin takes care of decoding the Lidl/SilverCrest Doorbell protocol for model Z31370-TX
*
* Author : StuntTeam
* Support : www.nodo-domotica.nl
* Date : 9-02-2015
* Version : 1.0
* Compatibility : RFLink 1.0
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical Information:
* Decodes signals from a Lidl Doorbell, (90 pulses, 40 bits, 433 MHz).
* Lidl Doorbell Message Format:
* 1010 1111 1000 0010 0001 1011 0011 0000 0000 0000 AF821B3000
* -------------- always zero
*
* Sample packet: (Nodo Pulse timing)
* 1850,1200,1400,1200,1400,1200,1400,1200,1400, (Preamble)
* 700,400,200,900,700,400,200,900,700,400,700,400,700,400,700,400,700,400,200,900,200,900,200,900,200,900,200,900,700,400,250,900,200,900,200,900,700,
* 400,700,400,700,400,200,900,700,400,700,400,200,900,200,900,700,400,700,400,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900,
* 200,900,200,900,250,900,200
*********************************************************************************************
* Technical Information:
* Decodes signals from a Lidl SilverCrest Z31370-TX Doorbell, (114 pulses, 48 bits, 433 MHz).
* SilverCrest Doorbell Message Format:
* 01011100 10100101 10001000 | 00000100 11010110 10111011 10010111 5CA588 04D6BB97
* always the same | device unique number
*
* Sample packet:
* 20;14;DEBUG;Pulses=114;Pulses(uSec)=360,60,60,390,360,60,60,390,60,390,60,390,390,60,360,60,60,390,360,60,60,390,360,60,360,60,60,390,360,60,60,390,60,390,360,60,360,60,360,60,30,390,360,60,360,60,360,60,390,60,360,60,60,390,390,60,360,60,360,60,390,60,360,60,390,60,360,60,360,60,390,60,60,390,60,390,30,390,60,390,60,390,360,60,60,390,60,390,60,390,60,390,360,60,360,60,60,390,60,390,60,390,360,60,60,390,60,390,360,60,60,390,360,1260;
\*********************************************************************************************/
// ==================================================================================
#define LIDL_PULSECOUNT 90 // type 0
#define LIDL_PULSECOUNT2 114 // type 1
#define PLUGIN_ID 75
#ifdef PLUGIN_075
boolean Plugin_075(byte function, char *string) {
if ((RawSignal.Number != LIDL_PULSECOUNT) && (RawSignal.Number != LIDL_PULSECOUNT2)) return false;
unsigned long bitstream=0;
unsigned long bitstream2=0;
int bitcount=0;
byte type=0;
//==================================================================================
// get all bits
if (RawSignal.Number == LIDL_PULSECOUNT) {
if (RawSignal.Pulses[1]*RawSignal.Multiply > 1000 && RawSignal.Pulses[2]*RawSignal.Multiply > 1000 &&
RawSignal.Pulses[3]*RawSignal.Multiply > 1000 && RawSignal.Pulses[4]*RawSignal.Multiply > 1000 &&
RawSignal.Pulses[5]*RawSignal.Multiply > 1000 && RawSignal.Pulses[6]*RawSignal.Multiply > 1000 &&
RawSignal.Pulses[7]*RawSignal.Multiply > 1000 && RawSignal.Pulses[8]*RawSignal.Multiply > 1000 && RawSignal.Pulses[9]*RawSignal.Multiply > 1000 ) {
//
} else {
return false;
}
for(int x=10;x <=90;x+=2) {
if (bitcount < 28){
if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) {
bitstream = (bitstream << 1);
bitcount++;
} else {
bitstream = (bitstream << 1) | 0x1;
bitcount++;
}
} else {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) {
bitstream2 = (bitstream2 << 1);
bitcount++;
} else {
bitstream2 = (bitstream2 << 1) | 0x1;
bitcount++;
}
}
}
} else {
if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets
type=1;
for(byte x=1;x < LIDL_PULSECOUNT2-1;x+=2) {
if (RawSignal.Pulses[x]*RawSignal.Multiply > 200) {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 200) return false; // invalid pulse length
if (bitcount > 23) {
bitstream2 = (bitstream2 << 1);
} else {
bitstream = (bitstream << 1);
}
bitcount++;
} else {
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 200) return false; // invalid pulse length
if (bitcount > 23) {
bitstream2 = (bitstream2 << 1) | 0x1;
} else {
bitstream = (bitstream << 1) | 0x1;
}
bitcount++;
}
}
}
//==================================================================================
// all bytes received, make sure checksum is okay
//==================================================================================
if (type==0) {
if ((bitstream2 &0xfff) != 0x00) return false; // these 8 bits are always 0
} else {
if (bitstream != 0x5ca588) return false;
}
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000)<millis()) || (SignalCRC != bitstream) ) {
SignalCRC=bitstream; // not seen the RF packet recently
} else {
return true; // already seen the RF packet recently
}
//==================================================================================
// Output
// ----------------------------------
Serial.print("20;");
PrintHexByte(PKSequenceNumber++);
// ----------------------------------
if (type == 0) {
Serial.print(";SilverCrest;"); // Label
sprintf(pbuffer, "ID=%08lx;", bitstream); // ID
} else {
Serial.print(";SilverCrest;"); // Label
sprintf(pbuffer, "ID=%08lx;", bitstream2); // ID
}
Serial.print( pbuffer );
Serial.print(F("SWITCH=1;CMD=ON;"));
Serial.print(F("CHIME=01;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
#endif // PLUGIN_075_CORE

119
Plugins/Plugin_080.c Normal file
View File

@@ -0,0 +1,119 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-80 Flamingo FA20RF Rookmelder ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst van Flamingo FA20RF rookmelder
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
* The Flamingo FA20RF/FA21RF Smokedetector contains both a RF receiver and transmitter.
* Every unit has a unique ID. The detector has a "learn" button to learn the ID of other units.
* That is what links the units to each other. After linking multiple units, they all have the same ID!
* Normally, one unit is used as master and the code of the master is learned to the slaves
*
* Attention: The smoke detector gives an alarm as long as the message is transmitted
*
* Sample:
* 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,
* 650,2550,650,1275,650,2550,650,2550,650,1275,650,1275,650,2550,650,1200,650;
* 000000010100110110110010 = 014DB2
* 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,
* 625,2575,625,1275,625,2575,625,2575,625,1300,625,1275,625,2575,625,1225,625;
* 100101111110001110110010 = 97E3B2
* 20;0D;FA20RF;ID=97e3b2;SMOKEALERT=ON;
*
* False positive:
* 20;52;DEBUG;Pulses=52;Pulses(uSec)=420,1860,330,3810,360,3960,360,1950,390,1920,360,3960,360,3960,360,3960,390,3960,390,3960,390,3960,390,1920,390,1920,390,1920,390,1890,480,1800,390,3930,390,1920,390,1920,420,1920,390,1920,420,1890,450,1860,420,1890,390,3930,390,6990;
\*********************************************************************************************/
#define FA20RFSTART 3000 // 8000
#define FA20RFSPACE 675 // 800
#define FA20RFLOW 1250 // 1300
#define FA20RFHIGH 2550 // 2600
#define FA20_PULSECOUNT 52
#ifdef PLUGIN_080
boolean Plugin_080(byte function, char *string) {
if (RawSignal.Number != FA20_PULSECOUNT) return false;
unsigned long bitstream=0L;
//==================================================================================
for(byte x=4;x<=FA20_PULSECOUNT-2;x=x+2) {
if (RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE > 1000) return false; // every preceding pulse must be below 1000!
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2000) { // long pulse
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2800) return false; // long pulse too long
bitstream = (bitstream << 1) | 0x1;
} else {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1500) return false; // short pulse too long
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 1000) return false; // short pulse too short
bitstream = bitstream << 1;
}
}
//==================================================================================
if (bitstream == 0) return false;
if (bitstream == 0xFFFFFF) return false;
if (((bitstream)&0xffff) == 0xffff) return false;
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("FA20RF;")); // Label
sprintf(pbuffer, "ID=%06lx;", bitstream ); // ID
Serial.print( pbuffer );
Serial.print(F("SMOKEALERT=ON;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
#endif // PLUGIN_080
#ifdef PLUGIN_TX_080
boolean PluginTX_080(byte function, char *string) {
boolean success=false;
//10;FA20RF;67f570;1;ON;
//012345678901234567890
unsigned long bitstream=0;
if (strncasecmp(InputBuffer_Serial+3,"FA20RF;",7) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[18] != ';') return false;
InputBuffer_Serial[8]=0x30;
InputBuffer_Serial[9]=0x78;
InputBuffer_Serial[16]=0;
bitstream=str2int(InputBuffer_Serial+8);
byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF
if (cmd!=VALUE_ON) return true; // pretend command was ok but we dont have to send anything..
// ---------- SMOKEALERT SEND -----------
RawSignal.Multiply=50;
RawSignal.Repeats=10;
RawSignal.Delay=20;
RawSignal.Pulses[1]=FA20RFSTART/RawSignal.Multiply;
//RawSignal.Pulses[2]=FA20RFSPACE/RawSignal.Multiply;
//RawSignal.Pulses[3]=FA20RFSPACE/RawSignal.Multiply;
RawSignal.Pulses[2]=(FA20RFSPACE+125)/RawSignal.Multiply;
RawSignal.Pulses[3]=(FA20RFSPACE+25)/RawSignal.Multiply;
for(byte x=49;x>=3;x=x-2) {
RawSignal.Pulses[x]=FA20RFSPACE/RawSignal.Multiply;
if ((bitstream & 1) == 1)
RawSignal.Pulses[x+1] = FA20RFHIGH/RawSignal.Multiply;
else
RawSignal.Pulses[x+1] = FA20RFLOW/RawSignal.Multiply;
bitstream = bitstream >> 1;
}
RawSignal.Pulses[51]=FA20RFSPACE/RawSignal.Multiply;
RawSignal.Pulses[52]=0;
RawSignal.Number=52;
RawSendRF();
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // restore setting
success=true;
}
return success;
}
#endif // PLUGIN_080

177
Plugins/Plugin_081.c Normal file
View File

@@ -0,0 +1,177 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-082 Mertik Maxitrol ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces
* PCB markings: G6R H4TB / G6R 4HT.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
*
* 0001100101101001011001101
* ----------------------- data bits (10=1 01=0)
* -- preamble, always 00?
* Shortened: (10=1 01=0)
* 01100101101001011001101
* 0 1 0 0 1 1 0 0 1 0 1 1
*
* 010011001011
* ---- command => 4 bits
* -------- address => 8 bits
*
* command bits:
* 0111 7 off
* 0011 3 on
* 1011 b up
* 1101 d down
* 1000 8 stop
* 1010 a go up
* 1100 c go down
*
* Sample RF packet:
* 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;
\*********************************************************************************************/
#define MAXITROL_PULSECOUNT 46
#define PLUGIN_081_RFSTART 100
#define PLUGIN_081_RFSPACE 250
#define PLUGIN_081_RFLOW 400
#define PLUGIN_081_RFHIGH 750
#ifdef PLUGIN_081
boolean Plugin_081(byte function, char *string) {
if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false;
unsigned int bitstream=0L;
byte address=0;
byte command=0;
byte status=0;
//==================================================================================
// get bits
for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) {
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false;
bitstream = (bitstream << 1); // 0
} else {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false;
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
bitstream = (bitstream << 1) | 0x1; // 1
}
}
//==================================================================================
// all bytes received, make sure packet is valid
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
command=(bitstream) & 0x0f; // get address from pulses
address=((bitstream)>>4)&0xff;
if (command == 0xB) status=1; // up
else if (command == 0xD) status=2; // down
else if (command == 0x7) status=3; // off
else if (command == 0x3) status=4; // on
else if (command == 0x8) status=5; // stop
else if (command == 0xa) status=6; // go up
else if (command == 0xc) status=7; // go down
else {
return false;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("Mertik;")); // Label
sprintf(pbuffer, "ID=%02x;", address); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", status);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if (status==1) Serial.print(F("UP;"));
if (status==2) Serial.print(F("DOWN;"));
if (status==3) Serial.print(F("OFF;"));
if (status==4) Serial.print(F("ON;"));
if (status==5) Serial.print(F("STOP;"));
if (status==6) Serial.print(F("GOUP;"));
if (status==7) Serial.print(F("GODOWN;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_081
#ifdef PLUGIN_TX_081
boolean PluginTX_081(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0L;
//10;MERTIK;64;UP;
//0123456789012345
if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[12] != ';') return false;
unsigned int bitstream2=0; // holds last 8 bits
InputBuffer_Serial[8]=0x30;
InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value
InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value
bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits)
if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8;
else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3;
else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7;
else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB;
else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD;
else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA;
else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC;
if (bitstream2==0) return false;
//-----------------------------------------------
RawSignal.Multiply=50;
RawSignal.Repeats=10;
RawSignal.Delay=20;
RawSignal.Pulses[1]=PLUGIN_081_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[2]=PLUGIN_081_RFLOW/RawSignal.Multiply;
for(byte x=18;x>=3;x=x-2) {
if ((bitstream & 1) == 1) {
RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
} else {
RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply;
}
bitstream = bitstream >> 1;
}
for(byte x=26;x>=19;x=x-2) {
if ((bitstream2 & 1) == 1) {
RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
} else {
RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply;
}
bitstream2 = bitstream2 >> 1;
}
RawSignal.Pulses[27]=PLUGIN_081_RFSTART/RawSignal.Multiply;
RawSignal.Number=27;
RawSendRF();
success=true;
//-----------------------------------------------
}
return success;
}
#endif // PLUGIN_081

177
Plugins/Plugin_082.c Normal file
View File

@@ -0,0 +1,177 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-082 Mertik Maxitrol ##
//#######################################################################################################
/*********************************************************************************************\
* This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces
* PCB markings: G6R H4T1.
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v1.0 initial release
*********************************************************************************************
* Technical information:
*
* 0001100101101001011001101
* ----------------------- data bits (10=1 01=0)
* -- preamble, always 00?
* Shortened: (10=1 01=0)
* 01100101101001011001101
* 0 1 0 0 1 1 0 0 1 0 1 1
*
* 010011001011
* ---- command => 4 bits
* -------- address => 8 bits
*
* command bits:
* 0111 7 off
* 0011 3 on
* 1011 b up
* 1101 d down
* 1000 8 stop
* 1010 a go up
* 1100 c go down
*
* Sample RF packet:
* 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;
\*********************************************************************************************/
#define MAXITROL_PULSECOUNT 26
#define PLUGIN_082_RFSTART 100
#define PLUGIN_082_RFSPACE 250
#define PLUGIN_082_RFLOW 400
#define PLUGIN_082_RFHIGH 750
#ifdef PLUGIN_082
boolean Plugin_082(byte function, char *string) {
if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false;
unsigned int bitstream=0L;
byte address=0;
byte command=0;
byte status=0;
//==================================================================================
// get bits
for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) {
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false;
bitstream = (bitstream << 1); // 0
} else {
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false;
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
bitstream = (bitstream << 1) | 0x1; // 1
}
}
//==================================================================================
// all bytes received, make sure packet is valid
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
//==================================================================================
// Prevent repeating signals from showing up
//==================================================================================
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
// not seen the RF packet recently
if (bitstream == 0) return false; // sanity check
} else {
// already seen the RF packet recently
return true;
}
//==================================================================================
command=(bitstream) & 0x0f; // get address from pulses
address=((bitstream)>>4)&0xff;
if (command == 0xB) status=1; // up
else if (command == 0xD) status=2; // down
else if (command == 0x7) status=3; // off
else if (command == 0x3) status=4; // on
else if (command == 0x8) status=5; // stop
else if (command == 0xa) status=6; // go up
else if (command == 0xc) status=7; // go down
else {
return false;
}
//==================================================================================
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
Serial.print(F("Mertik;")); // Label
sprintf(pbuffer, "ID=%02x;", address); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "SWITCH=%02x;", status);
Serial.print( pbuffer );
Serial.print(F("CMD="));
if (status==1) Serial.print(F("UP;"));
if (status==2) Serial.print(F("DOWN;"));
if (status==3) Serial.print(F("OFF;"));
if (status==4) Serial.print(F("ON;"));
if (status==5) Serial.print(F("STOP;"));
if (status==6) Serial.print(F("GOUP;"));
if (status==7) Serial.print(F("GODOWN;"));
Serial.println();
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_082
#ifdef PLUGIN_TX_082
boolean PluginTX_082(byte function, char *string) {
boolean success=false;
unsigned long bitstream=0L;
//10;MERTIK;64;UP;
//0123456789012345
if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg.
if (InputBuffer_Serial[12] != ';') return false;
unsigned int bitstream2=0; // holds last 8 bits
InputBuffer_Serial[8]=0x30;
InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value
InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value
bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits)
if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8;
else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3;
else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7;
else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB;
else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD;
else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA;
else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC;
if (bitstream2==0) return false;
//-----------------------------------------------
RawSignal.Multiply=50;
RawSignal.Repeats=10;
RawSignal.Delay=20;
RawSignal.Pulses[1]=PLUGIN_082_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[2]=PLUGIN_082_RFLOW/RawSignal.Multiply;
for(byte x=18;x>=3;x=x-2) {
if ((bitstream & 1) == 1) {
RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
} else {
RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply;
}
bitstream = bitstream >> 1;
}
for(byte x=26;x>=19;x=x-2) {
if ((bitstream2 & 1) == 1) {
RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
} else {
RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply;
}
bitstream2 = bitstream2 >> 1;
}
RawSignal.Pulses[27]=PLUGIN_082_RFSTART/RawSignal.Multiply;
RawSignal.Number=27;
RawSendRF();
success=true;
//-----------------------------------------------
}
return success;
}
#endif // PLUGIN_082

217
Plugins/Plugin_090.c Normal file
View File

@@ -0,0 +1,217 @@
//#######################################################################################################
//## This Plugin is only for use with Nodo 3.7 Slave Devices (variablesend support) ##
//## Plugin-090 Nodo Slave ##
//#######################################################################################################
// *********************************************************************************************
// * This Plugin takes care of reception of Nodo 3.7 Slave Devices
// *
// * Author : StuntTeam
// * Support : http://sourceforge.net/projects/rflink/
// * License : This code is free for use in any open source project when this header is included.
// * Usage of any parts of this code in a commercial application is prohibited!
// *********************************************************************************************
// * Changelog: v1.0 initial release
// *********************************************************************************************
// ----------------------------------
// Nodo Slave Unit 1, 2 and 4 till 9: // Individual sensor data
//
// Variabele 5 : Temperature
// Variabele 6 : Humidity 0 - 100
// Variabele 7 : Rain fall
// Variabele 8 : Wind speed
// Variabele 9 : Wind direction 0 - 15
// Variabele 10 : Wind gust
// Variabele 11, 12 en 13 : Temperature
// Variabele 14 : Humidity 0 - 100
// Variabele 15 : UV meter 0 - 1024
// Variabele 16 : Barometric pressure
//
// ----------------------------------
// Nodo Slave Unit 10 till 16: // Combined sensor data
//
// Variabele 5 : Temperature
// Variabele 6 : Humidity 0 - 100
// Variabele 7 : Rain fall
// Variabele 8 : Wind speed
// Variabele 9 : Wind direction 0 - 15
// Variabele 10 : Wind gust
// Variabele 11, 12 en 13 : Temperature
// Variabele 14 : Humidity 0 - 100
// Variabele 15 : UV meter 0 - 1024
// Variabele 16 : Barometric pressure
//
// ----------------------------------
// Nodo Slave Unit 3: // Pulse Meters
//
// Variabele 1 till 16 : Pulse value 1 till 16
//
// You can use a Nodo slave device with ID 03 to send variabel numbers 1 til 16
// which will be passed to Domoticz as pulse meter values (electricity/water/gas etc.)
// ----------------------------------
//
// * Sample:
// * 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;
// * 20;9F;Slave;ID=0307;DEBUG=0014;
// * slave nodo 7, var 3 value 14
// 3100,900,
/*( 194-2=192/2 = 96
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;
01010000 11100100 00000000 00000000 10000000 00100000 11000000 00000000 00000001 00000101 10000010 11000000
00001010 00100111 00000000 00000000 00000001 00000100 00000011 00000000 10000000 10100000 01000001 00000011
50E400008020C0010582C0
A270000104030080A04103
*/
// *********************************************************************************************
#define NODO_PULSE_MID 1000/RAWSIGNAL_SAMPLE_RATE // PWM: Pulsen langer zijn '1'
#define NodoSlave_PULSECOUNT 194
#ifdef PLUGIN_090
struct DataBlockStruct { // 16*sizeof(struct DataBlockStruct)+2 = 194 eg. 16*12+2
byte Version;
byte SourceUnit; // event->SourceUnit=DataBlock.SourceUnit&0x1F; // Maskeer de bits van het Home adres.
byte DestinationUnit; // event->DestinationUnit=DataBlock.DestinationUnit; // destination nodo
byte Flags;
byte Type; // event->Type=DataBlock.Type;
byte Command; // event->Command=DataBlock.Command;
byte Par1; // event->Par1=DataBlock.Par1;
unsigned long Par2; // event->Par2=DataBlock.Par2;
byte Checksum;
};
boolean Plugin_090(byte function, char *string) {
if (RawSignal.Number!=NodoSlave_PULSECOUNT ) return false; // Per byte twee posities + startbit.
byte b,x,y,z;
unsigned long varvalue=0L;
struct DataBlockStruct DataBlock;
byte *B=(byte*)&DataBlock; // B wijst naar de eerste byte van de struct
z=3; // RawSignal pulse teller: 0=niet gebruiktaantal, 1=startpuls, 2=space na startpuls, 3=1e pulslengte. Dus start loop met drie.
for(x=0;x<sizeof(struct DataBlockStruct);x++) { // vul alle bytes van de struct
b=0;
for(y=0;y<=7;y++) { // vul alle bits binnen een byte
if((RawSignal.Pulses[z]) > NODO_PULSE_MID)
b|=1<<y; // LSB in signaal wordt als eerste verzonden
z+=2;
}
*(B+x)=b;
}
// xor all bytes to check the checksum value?
DataBlock.SourceUnit=DataBlock.SourceUnit &0x1f;
//==================================================================================
// Er zijn een aantal type Nodo events die op verschillende wijze worden behandeld:
//#define NODO_TYPE_EVENT 1
//#define NODO_TYPE_PLUGIN_EVENT 4
//#define NODO_TYPE_PLUGIN_COMMAND 5
if ((DataBlock.Command == 4) && (DataBlock.Type == 1)){ // event->command = DataBlock.Command = 4 = EVENT_VARIABLE
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Slave;")); // Label
//==================================================================================
// slave id 03 aka source nodo id 03 => variable 1..6 will be pulse meter data
//==================================================================================
if (DataBlock.SourceUnit == 3 ) { // Pulse Meter variables
sprintf(pbuffer, "ID=%02x%02x%02x;", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Par1); // ID
Serial.print( pbuffer );
varvalue = ul2float(DataBlock.Par2); // convert
if ((DataBlock.Par1 < 1) || (DataBlock.Par1 > 16)) { // Unsupported (for now) variable, just show the contents
sprintf(pbuffer, "DEBUG=%08lx;", varvalue); // value
} else {
sprintf(pbuffer, "METER=%08lx;", varvalue); // value
}
Serial.print( pbuffer );
Serial.println();
} else
//==================================================================================
// slave id > 09 aka source nodo id > 09 => Combined variables
// slave id < 10 aka source nodo id < 10 => Regular variables
//==================================================================================
if ((DataBlock.SourceUnit > 0) && (DataBlock.SourceUnit < 17)) {
if (DataBlock.SourceUnit > 9 ) {
sprintf(pbuffer, "ID=%02x%02x;",DataBlock.SourceUnit , DataBlock.DestinationUnit); // ID
} else {
sprintf(pbuffer, "ID=%02x%02x%02x;", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Par1); // ID
}
Serial.print( pbuffer );
if ((DataBlock.Par1 < 5) || (DataBlock.Par1 > 16)) { // Unsupported (for now) variable, just show the contents
int varvalue = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "DEBUG=%04x;", varvalue); // value
} else
if (DataBlock.Par1 == 5){ // Variable 5 : temperature
int temperature = 10 * ul2float(DataBlock.Par2); // convert
if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures
sprintf(pbuffer, "TEMP=%04x;", temperature); // value
} else
if (DataBlock.Par1 == 6){ // Variable 6 : humidity
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
sprintf(pbuffer, "HUM=%02d;", humidity); // value
} else
if (DataBlock.Par1 == 7){ // Variable 7 : Rain in mm.
int rain = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "RAIN=%04x;", rain); // value
} else
if (DataBlock.Par1 == 8){ // Variable 8 : Wind speed
int winsp = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "WINSP=%04x;", winsp); // value
} else
if (DataBlock.Par1 == 9){ // Variable 9 : Wind Direction
int windir = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "WINDIR=%04d;", windir); // value
} else
if (DataBlock.Par1 == 10){ // Variable 10: Wind Gust
int wings = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "WINGS=%04x;", wings); // value
}
if ((DataBlock.Par1 > 10) && (DataBlock.Par1 < 14)) { // Variable 11 12 or 13 : emulate temperature sensor
int temperature = 10 * ul2float(DataBlock.Par2); // convert
if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures
sprintf(pbuffer, "TEMP=%04x;", temperature); // value
} else
if (DataBlock.Par1 == 14){ // Variable 14 : emulate humidity sensor
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
sprintf(pbuffer, "HUM=%02d;", humidity); // value
} else
if (DataBlock.Par1 == 15){ // Variable 15 : UV sensor
int light = ul2float(DataBlock.Par2); // supplied is value between 0 and 1024
light = map(light, 0,1024,1,100); // Map value to 1 - 100
sprintf(pbuffer, "UV=%04x;", light); // value
} else
if (DataBlock.Par1 == 16){ // Variable 16 : Barometric pressure sensor
int baro = ul2float(DataBlock.Par2); // convert
sprintf(pbuffer, "BARO=%04x;", baro); // value
}
Serial.print( pbuffer );
Serial.println();
}
//==================================================================================
} else { // Not a variable event
if ((DataBlock.Command == 0) && (DataBlock.Type==0)) return false;
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("Slave;Debug=")); // Label
sprintf(pbuffer, "%02x %02x %02x %02x %02x ", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Command, DataBlock.Type, DataBlock.Par1);
Serial.print( pbuffer );
sprintf(pbuffer, "%d;", DataBlock.Par2); // ID
Serial.print( pbuffer );
Serial.println();
}
//==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
return true;
}
#endif // PLUGIN_090

166
Plugins/Plugin_100.c Normal file
View File

@@ -0,0 +1,166 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-100 AlectoV2 ##
//## > 868 MHz Plugin < ##
//#######################################################################################################
/*********************************************************************************************\
* Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren
*
* Author : Martinus van den Broek
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Technische informatie:
* DKW2012 Message Format: (11 Bytes, 88 bits):
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH IIIIIIII
* Temperature Humidity Windspd_ Windgust Rain____ ________ Winddir Checksum
* A = start/unknown, first 8 bits are always 11111111
* B = Rolling code
* C = Temperature (10 bit value with -400 base)
* D = Humidity
* E = windspeed (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
* F = windgust (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
* G = Rain ( * 0.3 mm)
* H = winddirection (0 = north, 4 = east, 8 = south 12 = west)
* I = Checksum, calculation is still under investigation
*
* WS3000 and ACH2010 systems have no winddirection, message format is 8 bit shorter
* Message Format: (10 Bytes, 80 bits):
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH
* Temperature Humidity Windspd_ Windgust Rain____ ________ Checksum
*
* --------------------------------------------------------------------------------------------
* DCF Time Message Format: (NOT DECODED!, we already have time sync through webapp)
* AAAAAAAA BBBBCCCC DDDDDDDD EFFFFFFF GGGGGGGG HHHHHHHH IIIIIIII JJJJJJJJ KKKKKKKK LLLLLLLL MMMMMMMM
* 11 Hours Minutes Seconds Year Month Day ? Checksum
* B = 11 = DCF
* C = ?
* D = ?
* E = ?
* F = Hours BCD format (7 bits only for this byte, MSB could be '1')
* G = Minutes BCD format
* H = Seconds BCD format
* I = Year BCD format (only two digits!)
* J = Month BCD format
* K = Day BCD format
* L = ?
* M = Checksum
\*********************************************************************************************/
#define DKW2012_MIN_PULSECOUNT 164
#define DKW2012_MAX_PULSECOUNT 176
#define ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception
#define ACH2010_MAX_PULSECOUNT 160
#ifdef PLUGIN_100
uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len);
boolean Plugin_100(byte function, char *string) {
if (!(((RawSignal.Number >= ACH2010_MIN_PULSECOUNT) && (RawSignal.Number <= ACH2010_MAX_PULSECOUNT)) || ((RawSignal.Number >= DKW2012_MIN_PULSECOUNT) && (RawSignal.Number <= DKW2012_MAX_PULSECOUNT)))) return false;
byte c=0;
byte rfbit;
byte data[10];
byte msgtype=0;
byte rc=0;
byte checksum=0;
byte checksumcalc=0;
byte maxidx = 8;
//==================================================================================
if(RawSignal.Number > ACH2010_MAX_PULSECOUNT) maxidx = 9;
// Get message back to front as the header is almost never received complete for ACH2010
byte idx = maxidx;
for(byte x=RawSignal.Number; x>0; x=x-2) {
if(RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE < 0x300) rfbit = 0x80; else rfbit = 0;
data[idx] = (data[idx] >> 1) | rfbit;
c++;
if (c == 8) {
if (idx == 0) break;
c = 0;
idx--;
}
}
//==================================================================================
checksum = data[maxidx];
checksumcalc = Plugin_100_ProtocolAlectoCRC8(data, maxidx);
msgtype = (data[0] >> 4) & 0xf; // msg type must be 5 or 10
rc = (data[0] << 4) | (data[1] >> 4); // rolling code
if (checksum != checksumcalc) return false;
if ((msgtype != 10) && (msgtype != 5)) return true; // why true?
//==================================================================================
unsigned int temp = 0;
unsigned int rain=0;
byte hum = 0;
int wdir = 0;
int wspeed = 0;
int wgust = 0;
temp = (((data[1] & 0x3) * 256 + data[2]) - 400);
hum = data[3];
wspeed = data[4] * 108;
wspeed = wspeed / 10;
wgust = data[5] * 108;
wgust = wgust / 10;
rain = (data[6] * 256) + data[7];
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
wdir = (data[8] & 0xf);
}
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
Serial.print("DKW2012;"); // Label
} else {
Serial.print("Alecto V2;"); // Label
}
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temp);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", hum);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", wspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "WINGS=%04x;", wgust);
Serial.print( pbuffer );
sprintf(pbuffer, "RAIN=%04x;", rain);
Serial.print( pbuffer );
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
sprintf(pbuffer, "WINDIR=%04d;", wdir);
Serial.print( pbuffer );
}
Serial.println();
// ----------------------------------
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0; // do not process the packet any further
return true;
}
/*********************************************************************************************\
* Calculates CRC-8 checksum
* reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/
* http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/
* https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp
\*********************************************************************************************/
uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len) {
uint8_t crc = 0;
// Indicated changes are from reference CRC-8 function in OneWire library
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
crc <<= 1; // changed from right shift
if (mix) crc ^= 0x31;// changed from 0x8C;
inbyte <<= 1; // changed from right shift
}
}
return crc;
}
#endif // PLUGIN_100

912
Plugins/Plugin_101.c Normal file
View File

@@ -0,0 +1,912 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-48 Oregon V1/2/3 ##
//#######################################################################################################
/*********************************************************************************************\
* This protocol takes care of receiving a few 868 Mhz protocols
*
* Protocols : Visonic,
* ELV EM-Serie: EM-1000S, EM-100-EM, EM-1000-GZ
* ELV KS serie: Thermo (AS3), Thermo/Hygro (AS2000, ASH2000, S2000, S2001A, S2001IA, ASH2200, S300IA)
* Rain (S2000R), Wind (S2000W), Thermo/Hygro/Baro (S2001I, S2001ID), UV (S2500H)
* Pyrano (Strahlungsleistung), Kombi (KS200, KS300)
* FS20 FS serie
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
*********************************************************************************************
* Changelog: v0.1 beta
*********************************************************************************************
* Technical information:
* Supports Oregon V1, V2 and V3 protocol messages
* Core code from https://github.com/Cactusbone/ookDecoder/blob/master/ookDecoder.ino
* Copyright (c) 2014 Charly Koza cactusbone@free.fr Copyright (c) 2012 Olivier Lebrun olivier.lebrun@connectingstuff.net
* Copyright (c) 2012 Dominique Pierre (zzdomi) Copyright (c) 2010 Jean-Claude Wippler jcw@equi4.com
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
\*********************************************************************************************/
#define PLUGIN_ID 101
#define PLUGIN_NAME "Few868"
#define OSV3_PULSECOUNT_MIN 126
#define OSV3_PULSECOUNT_MAX 278
// =====================================================================================================
class DecodeOOK {
protected:
byte total_bits, bits, flip, state, pos, data[25];
virtual char decode(word width) = 0;
public:
enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };
// -------------------------------------
DecodeOOK() { resetDecoder(); }
// -------------------------------------
bool nextPulse(word width) {
if (state != DONE)
switch (decode(width)) {
case -1: resetDecoder(); break;
case 1: done(); break;
}
return isDone();
}
// -------------------------------------
bool isDone() const { return state == DONE; }
// -------------------------------------
const byte* getData(byte& count) const {
count = pos;
return data;
}
// -------------------------------------
void resetDecoder() {
total_bits = bits = pos = flip = 0;
state = UNKNOWN;
}
// -------------------------------------
// add one bit to the packet data pbuffer
// -------------------------------------
virtual void gotBit(char value) {
total_bits++;
byte *ptr = data + pos;
*ptr = (*ptr >> 1) | (value << 7);
if (++bits >= 8) {
bits = 0;
if (++pos >= sizeof data) {
resetDecoder();
return;
}
}
state = OK;
}
// -------------------------------------
// store a bit using Manchester encoding
// -------------------------------------
void manchester(char value) {
flip ^= value; // manchester code, long pulse flips the bit
gotBit(flip);
}
// -------------------------------------
// move bits to the front so that all the bits are aligned to the end
// -------------------------------------
void alignTail(byte max = 0) {
// align bits
if (bits != 0) {
data[pos] >>= 8 - bits;
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] >> bits) | (data[i + 1] << (8 - bits));
bits = 0;
}
// optionally shift bytes down if there are too many of 'em
if (max > 0 && pos > max) {
byte n = pos - max;
pos = max;
for (byte i = 0; i < pos; ++i)
data[i] = data[i + n];
}
}
// -------------------------------------
void reverseBits() {
for (byte i = 0; i < pos; ++i) {
byte b = data[i];
for (byte j = 0; j < 8; ++j) {
data[i] = (data[i] << 1) | (b & 1);
b >>= 1;
}
}
}
// -------------------------------------
void reverseNibbles() {
for (byte i = 0; i < pos; ++i)
data[i] = (data[i] << 4) | (data[i] >> 4);
}
// -------------------------------------
void done() {
while (bits)
gotBit(0); // padding
state = DONE;
}
};
// 868 MHz decoders
/// OOK decoder for Visonic devices.
class VisonicDecoder : public DecodeOOK {
public:
VisonicDecoder () {}
virtual char decode (word width) {
if (200 <= width && width < 1000) {
byte w = width >= 600;
switch (state) {
case UNKNOWN:
case OK:
state = w == 0 ? T0 : T1;
break;
case T0:
gotBit(!w);
if (w)
return 0;
break;
case T1:
gotBit(!w);
if (!w)
return 0;
break;
}
// sync error, flip all the preceding bits to resync
for (byte i = 0; i <= pos; ++i)
data[i] ^= 0xFF;
} else if (width >= 2500 && 8 * pos + bits >= 36 && state == OK) {
for (byte i = 0; i < 4; ++i)
gotBit(0);
alignTail(5); // keep last 40 bits
// only report valid packets
byte b = data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4];
if ((b & 0xF) == (b >> 4))
return 1;
} else
return -1;
return 0;
}
};
/// OOK decoder for FS20 type EM devices.
class EMxDecoder : public DecodeOOK {
public:
EMxDecoder () : DecodeOOK (30) {} // ignore packets repeated within 3 sec
// see also http://fhz4linux.info/tiki-index.php?page=EM+Protocol
virtual char decode (word width) {
if (200 <= width && width < 1000) {
byte w = width >= 600;
switch (state) {
case UNKNOWN:
if (w == 0)
++flip;
else if (flip > 20)
state = OK;
else
return -1;
break;
case OK:
if (w == 0)
state = T0;
else
return -1;
break;
case T0:
gotBit(w);
break;
}
} else if (width >= 1500 && pos >= 9)
return 1;
else
return -1;
return 0;
}
};
/// OOK decoder for FS20 type KS devices.
class KSxDecoder : public DecodeOOK {
public:
KSxDecoder () {}
// see also http://www.dc3yc.homepage.t-online.de/protocol.htm
virtual char decode (word width) {
if (200 <= width && width < 1000) {
byte w = width >= 600;
switch (state) {
case UNKNOWN:
gotBit(w);
bits = pos = 0;
if (data[0] != 0x95)
state = UNKNOWN;
break;
case OK:
state = w == 0 ? T0 : T1;
break;
case T0:
gotBit(1);
if (!w)
return -1;
break;
case T1:
gotBit(0);
if (w)
return -1;
break;
}
} else if (width >= 1500 && pos >= 6)
return 1;
else
return -1;
return 0;
}
};
/// OOK decoder for FS20 type FS devices.
class FSxDecoder : public DecodeOOK {
public:
FSxDecoder () {}
// see also http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol
virtual char decode (word width) {
if (300 <= width && width < 775) {
byte w = width >= 500;
switch (state) {
case UNKNOWN:
if (w == 0)
++flip;
else if (flip > 20)
state = T1;
else
return -1;
break;
case OK:
state = w == 0 ? T0 : T1;
break;
case T0:
gotBit(0);
if (w)
return -1;
break;
case T1:
gotBit(1);
if (!w)
return -1;
break;
}
} else if (width >= 1500 && pos >= 5)
return 1;
else
return -1;
return 0;
}
};
// =====================================================================================================
// =====================================================================================================
OregonDecoderV1 orscV1;
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;
volatile word pulse;
// =====================================================================================================
// =====================================================================================================
byte osdata[13];
void reportSerial(class DecodeOOK& decoder) {
byte pos;
const byte* data = decoder.getData(pos);
for (byte i = 0; i < pos; ++i) {
if (i < 13) osdata[i]=data[i];
}
decoder.resetDecoder();
}
// =====================================================================================================
// calculate a packet checksum by performing a
byte checksum(byte type, int count, byte check) {
byte calc=0;
// type 1, add all nibbles, deduct 10
if (type == 1) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
} else
// type 2, add all nibbles up to count, add the 13th nibble , deduct 10
if (type == 2) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc += (osdata[6]&0xF);
calc=calc-10;
} else
// type 3, add all nibbles up to count, subtract 10 only use the low 4 bits for the compare
if (type == 3) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
calc=(calc&0x0f);
} else
if (type == 4) {
for(byte i = 0; i<count;i++) {
calc += (osdata[i]&0xF0) >> 4;
calc += (osdata[i]&0xF);
}
calc=calc-10;
}
if (check == calc ) return 0;
return 1;
}
// =====================================================================================================
boolean Plugin_048(byte function, char *string) {
boolean success=false;
#ifdef PLUGIN_048_CORE
if ((RawSignal.Number < OSV3_PULSECOUNT_MIN) || (RawSignal.Number > OSV3_PULSECOUNT_MAX) ) return false;
byte basevar=0;
byte rc=0;
byte found = 0;
byte channel = 0;
int temp = 0;
byte hum = 0;
int comfort = 0;
int baro = 0;
int forecast = 0;
int uv = 0;
int wdir = 0;
int wspeed = 0;
int awspeed = 0;
int rain = 0;
int raintot = 0;
word p = pulse;
// ==================================================================================
for (int x = 0; x < RawSignal.Number; x++) {
p = RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE;
if (p != 0) {
if (orscV1.nextPulse(p)) {
reportSerial(orscV1);
found=1;
}
if (orscV2.nextPulse(p)) {
reportSerial(orscV2);
found=2;
}
if (orscV3.nextPulse(p)) {
reportSerial(orscV3);
found=3;
}
}
}
if (found == 0) break;
// ==================================================================================
// Protocol and device info:
// ==================================================================================
//Serial.print("Oregon V");
//Serial.print(found);
//Serial.print(": ");
//for(byte x=0; x<13;x++) {
// Serial.print( osdata[x],HEX );
// Serial.print((" "));
//}
//Serial.println();
//Serial.print("Oregon ID=");
unsigned int id=(osdata[0]<<8)+ (osdata[1]);
rc=osdata[0];
//Serial.println(id,HEX);
// ==================================================================================
// Process the various device types:
// ==================================================================================
// Oregon V1 packet structure
// SL-109H, AcuRite 09955
// TEMP + CRC
// ==================================================================================
// 8487101C
// 84+87+10=11B > 1B+1 = 1C
if (found==1) { // OSV1
int sum = osdata[0]+osdata[1]+osdata[2]; // max. value is 0x2FD
sum= (sum &0xff) + (sum>>8); // add overflow to low byte
if (osdata[3] != (sum & 0xff) ) {
//Serial.println("CRC Error");
break;
}
// -------------
temp = ((osdata[2]>>4) * 100) + ((osdata[1] & 0x0F) * 10) + ((osdata[1] >> 4));
if ((osdata[2] & 0x02) == 2) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("OregonV1;"); // Label
sprintf(pbuffer, "ID=00%02x;", rc); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temp);
Serial.print( pbuffer );
Serial.println();
}
// ==================================================================================
// ea4c Outside (Water) Temperature: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131
// TEMP + BAT + CRC
// ca48 Pool (Water) Temperature: THWR800
// 0a4d Indoor Temperature: THR128, THR138, THC138
// ==================================================================================
// OSV2 EA4C20725C21D083 // THN132N
// OSV2 EA4C101360193023 // THN132N
// OSV2 EA4C40F85C21D0D4 // THN132N
// OSV2 EA4C20809822D013
// 0123456789012345
// 0 1 2 3 4 5 6 7
if(id == 0xea4c || id == 0xca48 || id == 0x0a4d) {
byte sum=(osdata[7]&0x0f) <<4;
sum=sum+(osdata[6]>>4);
if ( checksum(2,6, sum) !=0) { // checksum = all nibbles 0-11+13 results is nibbles 15 <<4 + 12
//Serial.println("CRC Error");
break;
}
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Temp;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temp);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// 1a2d Indoor Temp/Hygro: THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, THGR268, THGR122X
// 1a3d Outside Temp/Hygro: THGR918, THGRN228NX, THGN500
// fa28 Indoor Temp/Hygro: THGR810
// *aac Outside Temp/Hygro: RTGR328N
// ca2c Outside Temp/Hygro: THGR328N
// fab8 Outside Temp/Hygro: WTGR800
// TEMP + HUM sensor + BAT + CRC
// ==================================================================================
// OSV2 AACC13783419008250AD[RTGR328N,...] Id:78 ,Channel:0 ,temp:19.30 ,hum:20 ,bat:10
// OSV2 1A2D40C4512170463EE6[THGR228N,...] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
// OSV2 1A2D1072512080E73F2C[THGR228N,...] Id:72 ,Channel:1 ,temp:20.50 ,hum:78 ,bat:90
// OSV2 1A2D103742197005378E // THGR228N
// OSV3 FA28A428202290834B46 //
// OSV2 1A2D1002 02060552A4C
// 1A3D10D91C273083..
// 1A3D10D90C284083..
// OSV3 FA2814A93022304443BE // THGR810
// 01234567890123456789
// 0 1 2 3 4 5
// F+A+2+8+1+4+A+9+3+0+2+2+3+0+4+4=4d-a=43
if(id == 0xfa28 || id == 0x1a2d || id == 0x1a3d || (id&0xfff)==0xACC || id == 0xca2c || id == 0xfab8 ) {
if ( checksum(1,8,osdata[8]) !=0) break; // checksum = all nibbles 0-15 results is nibbles 16.17
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// -------------
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon TempHygro;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temp);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", hum);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// 5a5d Indoor Temp/Hygro/Baro: Huger - BTHR918
// 5a6d Indoor Temp/Hygro/Baro: BTHR918N, BTHR968. BTHG968
// TEMP + HUM + BARO + FORECAST + BAT
// NO CRC YET
// ==================================================================================
// 5A 6D 00 7A 10 23 30 83 86 31
// 5+a+6+d+7+a+1+2+3+3+8+3=47 -a=3d +8=4f +8+6=55
// 5+a+6+d+7+a+1+2+3+3=3c-a=32
// 0 1 2 3 4 5 6 7 8 9
if(id == 0x5a6d || id == 0x5a5d || id == 0x5d60) {
// -------------
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
// -------------
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
//0: normal, 4: comfortable, 8: dry, C: wet
int tmp_comfort = osdata[7] >> 4;
if (tmp_comfort == 0x00)
comfort=0;
else if (tmp_comfort == 0x04)
comfort=1;
else if (tmp_comfort == 0x08)
comfort=2;
else if (tmp_comfort == 0x0C)
comfort=3;
// -------------
baro = (osdata[8] + 856); // max value = 1111 / 0x457
//2: cloudy, 3: rainy, 6: partly cloudy, C: sunny
int tmp_forecast = osdata[9]>>4;
if (tmp_forecast == 0x02)
forecast = 3;
else if (tmp_forecast == 0x03)
forecast = 4;
else if (tmp_forecast == 0x06)
forecast = 2;
else if (tmp_forecast == 0x0C)
forecast = 1;
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon BTHR;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "TEMP=%04x;", temp);
Serial.print( pbuffer );
sprintf(pbuffer, "HUM=%02x;", hum);
Serial.print( pbuffer );
sprintf(pbuffer, "HSTATUS=%d;", comfort);
Serial.print( pbuffer );
sprintf(pbuffer, "BARO=%04x;", baro);
Serial.print( pbuffer );
sprintf(pbuffer, "BFORECAST=%d;", forecast);
Serial.print( pbuffer );
//below is not correct, and for now discarded
//if (((osdata[3] & 0x0F) & 0x04) != 0) {
// Serial.print("BAT=LOW;");
//} else {
// Serial.print("BAT=OK;");
//}
Serial.println();
} else
// ==================================================================================
// 2914 Rain Gauge:
// 2d10 Rain Gauge:
// 2a1d Rain Gauge: RGR126, RGR682, RGR918, PCR122
// 2A1D0065502735102063
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0=3e-a=34 != 63
// ==================================================================================
if(id == 0x2a1d || id == 0x2d10 || id == 0x2914) { // Rain sensor
//Checksum - add all nibbles from 0 to 8, subtract 9 and compare
/*
int cs = 0;
for (byte i = 0; i < pos-2; ++i) { //all but last byte
cs += data[i] >> 4;
cs += data[i] & 0x0F;
}
int csc = (data[8] >> 4) + ((data[9] & 0x0F)*16);
cs -= 9; //my version as A fails?
Serial.print(csc);
Serial.print(" vs ");
Serial.println(cs);
*/
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Rain;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[3]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "RAIN=%04x;", rain);
Serial.print( pbuffer );
sprintf(pbuffer, "RAINTOT=%04x;", raintot);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// 2a19 Rain Gauge: PCR800
// RAIN + BAT + CRC
// ==================================================================================
// OSV3 2A19048E399393250010
// 01234567890123456789
// 0 1 2 3 4 5 6 7 8 9
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
if(id == 0x2a19) { // Rain sensor
int sum = (osdata[9] >> 4);
if ( checksum(3,9,sum) !=0) { // checksum = all nibbles 0-17 result is nibble 18
//Serial.print("CRC Error, ");
break;
}
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
//Serial.print(" RainTotal=");
//raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
//Serial.print(raintot);
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Rain2;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[4]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "RAIN=%04x;", rain);
Serial.print( pbuffer );
//sprintf(pbuffer, "RAINTOT=%04x;", raintot);
//Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// 1a89 Anemometer: WGR800
// WIND DIR + SPEED + AV SPEED + CRC
// ==================================================================================
// OSV3 1A89048800C026400543
// OSV3 1A89048800C00431103B
// OSV3 1a89048848c00000003e W
// OSV3 1a890488c0c00000003e E
// 1A89042CB0C047000147
// 0 1 2 3 4 5 6 7 8 9
// 1+A+8+9+0+4+8+8+0+0+C+0+0+4+3+1+1+0=45-a=3b
if(id == 0x1a89) { // Wind sensor
if ( checksum(1,9,osdata[9]) !=0) break;
Serial.print(" WINDIR=");
wdir=(osdata[4] >> 4);
wdir=wdir*225;
wdir=wdir/10;
Serial.print(wdir);
// -------------
wspeed = (osdata[6] >> 4) * 10;
wspeed = wspeed + (osdata[6] &0x0f) * 100;
wspeed = wspeed + (osdata[5] &0x0f);
// -------------
awspeed = (osdata[8] >> 4) * 100;
awspeed = awspeed + (osdata[7] &0x0f) * 10;
awspeed = awspeed + (osdata[7] >> 4);
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Wind;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "WINDIR=%04x;", wdir);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", wspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// 3a0d Anemometer: Huger-STR918, WGR918
// 1984 Anemometer:
// 1994 Anemometer:
// WIND DIR + SPEED + AV SPEED + BAT + CRC
// 3A0D006F400800000031
// ==================================================================================
if(id == 0x3A0D || id == 0x1984 || id == 0x1994 ) {
if ( checksum(1,9,osdata[9]) !=0) {
Serial.print("CRC Error, ");
//break;
}
wdir = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F * 10) ) + (osdata[4] >> 4);
wspeed = ((osdata[7] & 0x0F) * 100) + ((osdata[6]>>4) * 10) + ((osdata[6] & 0x0F)) ;
awspeed = ((osdata[8]>>4) * 100) + ((osdata[8] & 0x0F) * 10)+((osdata[7] >>4)) ;
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Wind2;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "WINDIR=%04x;", wdir);
Serial.print( pbuffer );
sprintf(pbuffer, "WINSP=%04x;", wspeed);
Serial.print( pbuffer );
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// ea7c UV Sensor: UVN128, UV138
// UV + BAT
// NO CRC YET
// ==================================================================================
if(id == 0xea7c) {
uv=((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
Serial.print(uv);
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon UVN128/138;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "UV=%04x;", uv);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// da78 UV Sensor: UVN800
// UV
// NO CRC YET
// ==================================================================================
if( id == 0xda78) {
uv=(osdata[6] & 0xf0) + (osdata[5] &0x0f) ;
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon UVN800;"); // Label
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
Serial.print( pbuffer );
sprintf(pbuffer, "UV=%04x;", uv);
Serial.print( pbuffer );
if ((osdata[3] & 0x0F) >= 4) {
Serial.print("BAT=LOW;");
} else {
Serial.print("BAT=OK;");
}
Serial.println();
} else
// ==================================================================================
// *aec Date&Time: RTGR328N
// NO CRC YET
// ==================================================================================
// 8AEA1378077214924242C16CBD 21:49 29/04/2014
// 0 1 2 3 4 5 6 7 8 9 0 1 2
// 8+A+E+A+1+3+7+8+0+7+7+2+1+4+9+2+4+2+4+2+C+1+6+C=88 != BD
// Date & Time
//if( (id &0xfff) == 0xaea) {
// Serial.print("RTGR328N RC: ");
// Serial.print(osdata[3], HEX);
// Serial.print(" Date: ");
// Serial.print( (osdata[9] >> 4) + 10 * (osdata[10] & 0xf) );
// Serial.print(" - ");
// Serial.print( osdata[8] >> 4 );
// Serial.print(" - ");
// Serial.print( (osdata[7] >> 4) + 10 * (osdata[8] & 0xf) );
// Serial.print(" Time: ");
// Serial.print( (osdata[6] >> 4) + 10 * (osdata[7] & 0xf) );
// Serial.print(":");
// Serial.print((osdata[5] >> 4) + 10 * (osdata[6] & 0xf));
// Serial.print(":");
// Serial.print((osdata[4] >> 4) + 10 * (osdata[5] & 0xf));
// Serial.println();
// break;
//}
// ==================================================================================
// eac0 Ampere meter: cent-a-meter, OWL CM113, Electrisave
// ==================================================================================
if(id == 0xeac0) {
//Serial.println("UNKNOWN LAYOUT");
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Unknown;"); // Label
for(byte x=0; x<13;x++) {
Serial.print( osdata[x],HEX );
Serial.print((" "));
}
Serial.println(";");
return success;
} else
// ==================================================================================
// 0x1a* / 0x2a* 0x3a** Power meter: OWL CM119
// ==================================================================================
// ==================================================================================
// 1a99 Anemometer: WGTR800
// WIND + TEMP + HUM + CRC
// ==================================================================================
if(id == 0x1a99) { // Wind sensor
//Serial.println("UNKNOWN LAYOUT");
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Unknown;"); // Label
for(byte x=0; x<13;x++) {
Serial.print( osdata[x],HEX );
Serial.print((" "));
}
Serial.println(";");
return success;
} else
// ==================================================================================
if( (id&0xf00)==0xA00 ) { // Wind sensor
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print("Oregon Unknown;"); // Label
for(byte x=0; x<13;x++) {
Serial.print( osdata[x],HEX );
Serial.print((" "));
}
Serial.println(";");
}
// ==================================================================================
RawSignal.Repeats=true; // suppress repeats of the same RF packet
RawSignal.Number=0;
success = true;
#endif // PLUGIN_048_CORE
return success;
}

58
Plugins/Plugin_254.c Normal file
View File

@@ -0,0 +1,58 @@
//#######################################################################################################
//## This Plugin is only for use with the RFLink software package ##
//## Plugin-254: Signal Analyzer ##
//#######################################################################################################
/*********************************************************************************************\
* This plugin shows pulse lengths that have been received on RF and have not been decoded by
* one of the other plugins. The primary use of this plugin is to provide an easy way to debug and
* analyse currently unsupported RF signals
*
* Author : StuntTeam
* Support : http://sourceforge.net/projects/rflink/
* License : This code is free for use in any open source project when this header is included.
* Usage of any parts of this code in a commercial application is prohibited!
***********************************************************************************************
* Technical description:
* This plugin just outputs unsupported RF packets, use this plugin to find signals from new devices
* Even if you do not know what to do with the data yourself you might want to share your data so
* others can analyse it.
\*********************************************************************************************/
#ifdef PLUGIN_254
boolean Plugin_254(byte function, char *string) {
if (QRFDebug==true) { // debug is on?
if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("DEBUG;Pulses=")); // debug data
Serial.print(RawSignal.Number); // print number of pulses
Serial.print(F(";Pulses(uSec)=")); // print pulse durations
//PrintHex8(RawSignal.Pulses+1,RawSignal.Number-1);
PrintHex8(RawSignal.Pulses+1,RawSignal.Number);
} else {
if (RFUDebug==false) return false; // debug is on?
if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning
// ----------------------------------
// Output
// ----------------------------------
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
Serial.print( pbuffer );
// ----------------------------------
Serial.print(F("DEBUG;Pulses=")); // debug data
Serial.print(RawSignal.Number); // print number of pulses
Serial.print(F(";Pulses(uSec)=")); // print pulse durations
//for(int x=1;x<RawSignal.Number;x++) {
for(int x=1;x<RawSignal.Number+1;x++) {
Serial.print(RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE);
//if (x < RawSignal.Number-1) Serial.write(',');
if (x < RawSignal.Number) Serial.write(',');
}
}
Serial.println(";");
RawSignal.Number=0; // Last plugin, kill packet
return true; // stop processing
}
#endif // PLUGIN_254