This commit is contained in:
Jan-Willem de Bruyn 2018-06-22 10:29:56 +02:00
commit 0c3af5d9c7
59 changed files with 14439 additions and 0 deletions

228
Base.ino Normal file
View File

@ -0,0 +1,228 @@
#define BUILDNR 0x07 // shown in version
#define REVNR 0x33 // shown in version and startup string
#define MIN_RAW_PULSES 20 // =8 bits. Minimal number of bits*2 that need to have been received before we spend CPU time on decoding the signal.
#define RAWSIGNAL_SAMPLE_RATE 30 // Sample width / resolution in uSec for raw RF pulses.
#define MIN_PULSE_LENGTH 25 // Pulses shorter than this value in uSec. will be seen as garbage and not taken as actual pulses.
#define SIGNAL_TIMEOUT 7 // Timeout, after this time in mSec. the RF signal will be considered to have stopped.
#define SIGNAL_REPEAT_TIME 500 // Time in mSec. in which the same RF signal should not be accepted again. Filters out retransmits.
#define BAUD 57600 // Baudrate for serial communication.
#define TRANSMITTER_STABLE_DELAY 500 // delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms).
#define RAW_BUFFER_SIZE 512 // Maximum number of pulses that is received in one go.
#define PLUGIN_MAX 55 // Maximum number of Receive plugins
#define PLUGIN_TX_MAX 26 // Maximum number of Transmit plugins
#define SCAN_HIGH_TIME 50 // tijdsinterval in ms. voor achtergrondtaken snelle verwerking
#define FOCUS_TIME 50 // Duration in mSec. that, after receiving serial data from USB only the serial port is checked.
#define INPUT_COMMAND_SIZE 60 // Maximum number of characters that a command via serial can be.
#define PRINT_BUFFER_SIZE 60 // Maximum number of characters that a command should print in one go via the print buffer.
// to include Config_xx.c files:
#define stringify(x) #x
#define CONFIGFILE2(a, b) stringify(a/Config/b)
#define CONFIGFILE(a, b) CONFIGFILE2(a, b)
#define CONFIG_FILE Config_01.c
#include CONFIGFILE(SKETCH_PATH,CONFIG_FILE)
#define VALUE_PAIR 44
#define VALUE_ALLOFF 55
#define VALUE_OFF 74
#define VALUE_ON 75
#define VALUE_DIM 76
#define VALUE_BRIGHT 77
#define VALUE_UP 78
#define VALUE_DOWN 79
#define VALUE_STOP 80
#define VALUE_CONFIRM 81
#define VALUE_LIMIT 82
#define VALUE_ALLON 141
// PIN Definition
#define PIN_BSF_0 22 // Board Specific Function lijn-0
#define PIN_BSF_1 23 // Board Specific Function lijn-1
#define PIN_BSF_2 24 // Board Specific Function lijn-2
#define PIN_BSF_3 25 // Board Specific Function lijn-3
#define PIN_RF_TX_VCC 15 // +5 volt / Vcc power to the transmitter on this pin
#define PIN_RF_TX_DATA 14 // Data to the 433Mhz transmitter on this pin
#define PIN_RF_RX_VCC 16 // Power to the receiver on this pin
#define PIN_RF_RX_DATA 19 // On this input, the 433Mhz-RF signal is received. LOW when no signal.
//****************************************************************************************************************************************
byte dummy=1; // get the linker going. Bug in Arduino. (old versions?)
void(*Reboot)(void)=0; // reset function on adres 0.
byte PKSequenceNumber=0; // 1 byte packet counter
boolean RFDebug=false; // debug RF signals with plugin 001
boolean RFUDebug=false; // debug RF signals with plugin 254
boolean QRFDebug=false; // debug RF signals with plugin 254 but no multiplication
uint8_t RFbit,RFport; // for processing RF signals.
char pbuffer[PRINT_BUFFER_SIZE]; // Buffer for printing data
char InputBuffer_Serial[INPUT_COMMAND_SIZE]; // Buffer for Seriel data
// Van alle devices die worden mee gecompileerd, worden in een tabel de adressen opgeslagen zodat hier naar toe gesprongen kan worden
void PluginInit(void);
void PluginTXInit(void);
boolean (*Plugin_ptr[PLUGIN_MAX])(byte, char*); // Receive plugins
byte Plugin_id[PLUGIN_MAX];
boolean (*PluginTX_ptr[PLUGIN_TX_MAX])(byte, char*); // Transmit plugins
byte PluginTX_id[PLUGIN_TX_MAX];
void PrintHex8(uint8_t *data, uint8_t length); // prototype
void PrintHexByte(uint8_t data); // prototype
byte reverseBits(byte data); // prototype
void RFLinkHW( void ); // prototype
struct RawSignalStruct // Raw signal variabelen places in a struct
{
int Number; // Number of pulses, times two as every pulse has a mark and a space.
byte Repeats; // Number of re-transmits on transmit actions.
byte Delay; // Delay in ms. after transmit of a single RF pulse packet
byte Multiply; // Pulses[] * Multiply is the real pulse time in microseconds
unsigned long Time; // Timestamp indicating when the signal was received (millis())
byte Pulses[RAW_BUFFER_SIZE+2]; // Table with the measured pulses in microseconds divided by RawSignal.Multiply. (halves RAM usage)
// First pulse is located in element 1. Element 0 is used for special purposes, like signalling the use of a specific plugin
} RawSignal={0,0,0,0,0,0L};
// ===============================================================================
unsigned long RepeatingTimer=0L;
unsigned long SignalCRC=0L; // holds the bitstream value for some plugins to identify RF repeats
unsigned long SignalHash=0L; // holds the processed plugin number
unsigned long SignalHashPrevious=0L; // holds the last processed plugin number
void setup() {
Serial.begin(BAUD); // Initialise the serial port
pinMode(PIN_RF_RX_DATA, INPUT); // Initialise in/output ports
pinMode(PIN_RF_TX_DATA, OUTPUT); // Initialise in/output ports
pinMode(PIN_RF_TX_VCC, OUTPUT); // Initialise in/output ports
pinMode(PIN_RF_RX_VCC, OUTPUT); // Initialise in/output ports
digitalWrite(PIN_RF_RX_VCC,HIGH); // turn VCC to RF receiver ON
digitalWrite(PIN_RF_RX_DATA,INPUT_PULLUP); // pull-up resister on (to prevent garbage)
pinMode(PIN_BSF_0,OUTPUT); // rflink board switch signal
digitalWrite(PIN_BSF_0,HIGH); // rflink board switch signal
RFbit=digitalPinToBitMask(PIN_RF_RX_DATA);
RFport=digitalPinToPort(PIN_RF_RX_DATA);
Serial.print(F("20;00;Nodo RadioFrequencyLink - RFLink Gateway V1.1 - "));
sprintf(InputBuffer_Serial,"R%02x;",REVNR);
Serial.println(InputBuffer_Serial);
PKSequenceNumber++;
PluginInit();
PluginTXInit();
}
void loop() {
byte SerialInByte=0; // incoming character value
int SerialInByteCounter=0; // number of bytes counter
byte ValidCommand=0;
unsigned long FocusTimer=0L; // Timer to keep focus on the task during communication
InputBuffer_Serial[0]=0; // erase serial buffer string
while(true) {
ScanEvent(); // Scan for RF events
// SERIAL: *************** kijk of er data klaar staat op de seriele poort **********************
if(Serial.available()) {
FocusTimer=millis()+FOCUS_TIME;
while(FocusTimer>millis()) { // standby
if(Serial.available()) {
SerialInByte=Serial.read();
if(isprint(SerialInByte))
if(SerialInByteCounter<(INPUT_COMMAND_SIZE-1))
InputBuffer_Serial[SerialInByteCounter++]=SerialInByte;
if(SerialInByte=='\n') { // new line character
InputBuffer_Serial[SerialInByteCounter]=0; // serieel data is complete
//Serial.print("20;incoming;");
//Serial.println(InputBuffer_Serial);
if (strlen(InputBuffer_Serial) > 7){ // need to see minimal 8 characters on the serial port
// 10;....;..;ON;
if (strncmp (InputBuffer_Serial,"10;",3) == 0) { // Command from Master to RFLink
// -------------------------------------------------------
// Handle Device Management Commands
// -------------------------------------------------------
if (strcasecmp(InputBuffer_Serial+3,"PING;")==0) {
sprintf(InputBuffer_Serial,"20;%02X;PONG;",PKSequenceNumber++);
Serial.println(InputBuffer_Serial);
} else
if (strcasecmp(InputBuffer_Serial+3,"REBOOT;")==0) {
strcpy(InputBuffer_Serial,"reboot");
Reboot();
} else
if (strncasecmp(InputBuffer_Serial+3,"RFDEBUG=O",9) == 0) {
if (InputBuffer_Serial[12] == 'N' || InputBuffer_Serial[12] == 'n' ) {
RFDebug=true; // full debug on
RFUDebug=false; // undecoded debug off
QRFDebug=false; // undecoded debug off
sprintf(InputBuffer_Serial,"20;%02X;RFDEBUG=ON;",PKSequenceNumber++);
} else {
RFDebug=false; // full debug off
sprintf(InputBuffer_Serial,"20;%02X;RFDEBUG=OFF;",PKSequenceNumber++);
}
Serial.println(InputBuffer_Serial);
} else
if (strncasecmp(InputBuffer_Serial+3,"RFUDEBUG=O",10) == 0) {
if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') {
RFUDebug=true; // undecoded debug on
QRFDebug=false; // undecoded debug off
RFDebug=false; // full debug off
sprintf(InputBuffer_Serial,"20;%02X;RFUDEBUG=ON;",PKSequenceNumber++);
} else {
RFUDebug=false; // undecoded debug off
sprintf(InputBuffer_Serial,"20;%02X;RFUDEBUG=OFF;",PKSequenceNumber++);
}
Serial.println(InputBuffer_Serial);
} else
if (strncasecmp(InputBuffer_Serial+3,"QRFDEBUG=O",10) == 0) {
if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') {
QRFDebug=true; // undecoded debug on
RFUDebug=false; // undecoded debug off
RFDebug=false; // full debug off
sprintf(InputBuffer_Serial,"20;%02X;QRFDEBUG=ON;",PKSequenceNumber++);
} else {
QRFDebug=false; // undecoded debug off
sprintf(InputBuffer_Serial,"20;%02X;QRFDEBUG=OFF;",PKSequenceNumber++);
}
Serial.println(InputBuffer_Serial);
} else
if (strncasecmp(InputBuffer_Serial+3,"VERSION",7) == 0) {
sprintf(InputBuffer_Serial,"20;%02X;VER=1.1;REV=%02x;BUILD=%02x;",PKSequenceNumber++,REVNR, BUILDNR);
Serial.println(InputBuffer_Serial);
} else {
// -------------------------------------------------------
// Handle Generic Commands / Translate protocol data into Nodo text commands
// -------------------------------------------------------
// check plugins
if (InputBuffer_Serial[SerialInByteCounter-1]==';') InputBuffer_Serial[SerialInByteCounter-1]=0; // remove last ";" char
if(PluginTXCall(0, InputBuffer_Serial)) {
ValidCommand=1;
} else {
// Answer that an invalid command was received?
ValidCommand=2;
}
}
}
} // if > 7
if (ValidCommand != 0) {
if (ValidCommand==1) {
sprintf(InputBuffer_Serial,"20;%02X;OK;",PKSequenceNumber++);
Serial.println( InputBuffer_Serial );
} else {
sprintf(InputBuffer_Serial, "20;%02X;CMD UNKNOWN;", PKSequenceNumber++); // Node and packet number
Serial.println( InputBuffer_Serial );
}
}
SerialInByteCounter=0;
InputBuffer_Serial[0]=0; // serial data has been processed.
ValidCommand=0;
FocusTimer=millis()+FOCUS_TIME;
}// if(SerialInByte
}// if(Serial.available())
}// while
}// if(Serial.available())
}// while
} // void
/*********************************************************************************************/

112
Config/Config_01.c Normal file
View File

@ -0,0 +1,112 @@
// ****************************************************************************************************************************************
// RFLink List of Plugins
// ****************************************************************************************************************************************
// Here are all plugins listed that are supported and used after compilation.
// When needed additional plugins can be added or selected plugins can be enabled/disabled.
//
// BEWARE OF THE PLUGIN_MAX setting!! TX: 51 RX: 24
// ****************************************************************************************************************************************
// Translation Plugin for oversized packets due to their breaks/pause being too short between packets
// Used for Flamingo FA500R and various others, do NOT exclude this plugin.
#define PLUGIN_001 // DO NOT CHANGE OR EXCLUDE!!
// ------------------------------------------------------------------------
// -- Any of the following protocols can be excluded whenever not needed --
// ------------------------------------------------------------------------
#define PLUGIN_002 // Lacrosse v2 2300/3600
#define PLUGIN_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC
#define PLUGIN_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno.
#define PLUGIN_005 // Eurodomest
#define PLUGIN_006 // Blyss
#define PLUGIN_007 // Conrad RSL2
#define PLUGIN_008 // Kambrook
#define PLUGIN_009 // X10 RF
#define PLUGIN_010 // TRC02 RGB Switch
#define PLUGIN_011 // Home Confort
#define PLUGIN_012 // Flamingo FA500R
#define PLUGIN_013 // Powerfix/Quigg
#define PLUGIN_014 // Ikea Koppla
#define PLUGIN_015 // Home Easy EU
// -------------------
// Weather sensors
// -------------------
#define PLUGIN_030 // Alecto V1 (WS3500) 434 MHz.
#define PLUGIN_031 // Alecto V3 (WS1100/WS1200/WSD-19) 433.9 MHz.
#define PLUGIN_032 // Alecto V4
#define PLUGIN_033 // Conrad Pool Thermometer
#define PLUGIN_034 // Cresta
#define PLUGIN_035 // Imagintronix
#define PLUGIN_040 // Mebus
#define PLUGIN_041 // LaCrosse v3 ws7000
#define PLUGIN_042 // UPM/Esic
#define PLUGIN_043 // LaCrosse v1
#define PLUGIN_044 // Auriol v3
#define PLUGIN_045 // Auriol
#define PLUGIN_046 // Auriol v2 / Xiron
#define PLUGIN_048 // Oregon V1/2/3
// -------------------
// Motion Sensors, include when needed
// -------------------
#define PLUGIN_060 // Ajax Chubb Varel 433 MHz. motion sensors
#define PLUGIN_061 // Chinese PIR motion door and window sensors
#define PLUGIN_062 // Chuango Alarm Devices
#define PLUGIN_063 // Oregon PIR/ALARM/LIGHT
// -------------------
// Doorbells
// -------------------
#define PLUGIN_070 // Select Plus (Action - Quhwa)
#define PLUGIN_071 // Plieger York
#define PLUGIN_072 // Byron SX doorbell
#define PLUGIN_073 // Deltronic doorbell
#define PLUGIN_074 // RL02
#define PLUGIN_075 // Silvercrest
// -------------------
// Smoke detectors / Fire Places
// -------------------
#define PLUGIN_080 // Flamingo FA20 / KD101 smoke detector
#define PLUGIN_082 // Mertik Maxitrol / Dru fireplace
//#define PLUGIN_083 // Alecto SA33
// -------------------
// 868 MHZ
// -------------------
#define PLUGIN_100 // Alecto V2 (DKW2012/ACH2010) 868 MHz. => PLANNED
// -------------------
// Housekeeping
// -------------------
#define PLUGIN_090 // Nodo Slave conversion plugin
#define PLUGIN_254 // Debug to show unsupported packets
// ****************************************************************************************************************************************
// RFLink List of Plugins that have TRANSMIT functionality
// ****************************************************************************************************************************************
// Here are all plugins listed that are supported and used after compilation.
// When needed additional plugins can be added or selected plugins can be enabled/disabled.
// ****************************************************************************************************************************************
// ------------------------------------------------------------------------
// -- Any of the following protocols can be excluded whenever not needed --
// ------------------------------------------------------------------------
#define PLUGIN_TX_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC
#define PLUGIN_TX_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno.
#define PLUGIN_TX_005 // Eurodomest
#define PLUGIN_TX_006 // Blyss
#define PLUGIN_TX_007 // Conrad RSL2
#define PLUGIN_TX_008 // Kambrook
#define PLUGIN_TX_009 // X10 RF
#define PLUGIN_TX_010 // TRC02 RGB switch
#define PLUGIN_TX_011 // Home Confort
#define PLUGIN_TX_012 // Flamingo FA500R (11)
#define PLUGIN_TX_013 // Powerfix/Quigg
#define PLUGIN_TX_015 // Home Easy EU (14)
// -------------------
// Doorbells
// -------------------
#define PLUGIN_TX_070 // Select Plus (Action - Quhwa)
#define PLUGIN_TX_072 // Byron SX doorbell
#define PLUGIN_TX_073 // Deltronic doorbell
#define PLUGIN_TX_074 // RL02
// -------------------
// Smoke detectors
// -------------------
#define PLUGIN_TX_080 // Flamingo FA20 / KD101 smoke detector
#define PLUGIN_TX_082 // Mertik Maxitrol / Dru fireplace
// -------------------
// -=#=-
// -------------------

View File

@ -0,0 +1,161 @@
RFLink Gateway Commands and Data fields
The use of this protocol is free for both server and client sides of the implementation
Data is send serial (via USB) as "text" at a speed of 57600 baud (N,8,1)
It is sufficient to open a port and listen to the data.
Each text line contains information that has been received via RF signals.
Packet structure - Received data from RF:
-----------------------------------------
20;ID=9999;Name;LABEL=data;
20 => Node number 20 means from the RFLink Gateway to the master, 10 means from the master to the RFLink Gateway
; => field separator
NAME => Device name (can be used to display in applications etc.)
LABEL=data => contains the field type and data for that field, can be present multiple times per device
Data Fields: (LABEL=data)
------------
ID=9999 => device ID (often a rolling code and/or device channel number)
SWITCH=A16 => House/Unit code like A1, P2, B16 or a button number etc.
CMD=ON => Command (ON/OFF/ALLON/ALLOFF)
SET_LEVEL=15 => Direct dimming level setting value
TEMP=9999 => Temperature (hexadecimal), high bit contains negative sign, needs devision by 10
HUM=99 => Humidity (hexadecimal)
BARO=9999 => Barometric pressure (hexadecimal)
HSTATUS=99 => 0=Normal, 1=Comfortable, 2=Dry, 3=Wet
BFORECAST=99 => 0=No Info/Unknown, 1=Sunny, 2=Partly Cloudy, 3=Cloudy, 4=Rain
UV=9999 => UV intensity (hexadecimal)
LUX=9999 => Light intensity (hexadecimal)
BAT=OK => Battery status indicator (OK/LOW)
RAIN=1234 => rain rate in mm. (hexadecimal)
RAINTOT=1234 => total rain in mm. (hexadecimal)
WINSP=9999 => Wind speed in km. p/h (hexadecimal) needs devision by 10
AWINSP=9999 => Average Wind speed in km. p/h (hexadecimal) needs devision by 10
WINGS=9999 => Wind Gust in km. p/h (hexadecimal)
WINDIR=123 => Wind direction 0-15 reflecting 0-360 degrees in 22.5 degree steps (decimal)
WINCHL => wind chill (hexadecimal)
WINTMP=1234 => Wind meter temperature reading (hexadecimal)
CHIME=123 => Chime/Doorbell melody number
SMOKEALERT=ON => ON/OFF
PIR=ON => ON/OFF
CO2=1234 => CO2 air quality
SOUND=1234 => Noise level
KWATT=1234 => KWatt
WATT=1234 => Watt
DIST=1234 => Distance
METER=1234 => Water flow meter
VOLT=1234 => Voltage
CURRENT=1234 => Current
Sample data of received RF packets:
-----------------------------------
20;2D;UPM/Esic;ID=0001;TEMP=00cf;HUM=16;BAT=OK;
20;6A;UPM/Esic;ID=1002;WINSP=0041;WINDIR=5A;BAT=OK;
20;08;UPM/Esic;ID=1003;RAIN=0010;BAT=OK;
20;31;Mebus;ID=c201;TEMP=00cf;
20;32;Auriol;ID=008f;TEMP=00d3;BAT=OK;
20;A2;Auriol V2;ID=008f;TEMP=00a3;BAT=LOW;
20;33;Cresta;ID=3001;TEMP=00b0;HUM=50;
20;0C;Cresta;ID=8001;RAIN=001c;
20;47;Cresta;ID=8001;WINDIR=0002;WINSP=0060;WINGS=0088;WINCHL=b0;
20;47;Cresta;ID=8001;TEMP=00b0;UV=00d0;
20;36;Alecto V1;ID=ec02;TEMP=00d1;HUM=14;
20;07;Mebus;ID=ea01;TEMP=0017;
20;3D;Alecto V1;ID=2000;TEMP=0011;HUM=61;
20;26;Alecto V1;ID=0086;RAIN=02ac;
20;30;Alecto V1;ID=0020;WINSP=0068;
20;16;Alecto V1;ID=0020;WINSP=0020;
20;17;Alecto V1;ID=0020;WINDIR=0002;WINGS=0088;
20;36;Alecto V1;ID=0020;WINDIR=0002;WINGS=0040;
20;74;Oregon TempHygro;ID=0ACC;TEMP=00be;HUM=40;BAT=OK;
20;b3;Oregon TempHygro;ID=1a2d;TEMP=00dd;HUM=43;BAT=OK;
20;e5;Oregon BTHR;ID=5a6d;TEMP=00be;HUM=40;BARO=03d7;BAT=OK;
20;46;Oregon Rain;ID=2a1d;RAIN=0012;RAINTOT=0012;BAT=OK;
20;83;Oregon Rain2;ID=2a19;RAIN=002a;RAINTOT=0054;BAT=OK;
20;32;Oregon Wind;ID=1a89;WDIR=0045;WINSP=0068;AWINSP=0050;BAT=OK;
20;4a;Oregon Wind2;ID=3a0d;WDIR=0021;WINSP=0040;AWINSP=005a;BAT=OK;
20;ba;Oregon UVN128/138;ID=ea7c;UV=0030;BAT=OK;
20;AF;SelectPlus;ID=1bb4;CHIME=01;
20;FC;Plieger York;ID=dd01;CHIME=02;
20;47;Byron SX;ID=a66a;CHIME=A9;
20;12;Pir;ID=aa66;PIR=ON;
20;63;SmokeAlert;ID=123456;SMOKEALERT=ON;
20;06;Kaku;ID=41;SWITCH=1;CMD=ON;
20;0C;Kaku;ID=41;SWITCH=2;CMD=OFF;
20;0D;Kaku;ID=41;SWITCH=2;CMD=ON;
20;46;Kaku;ID=44;SWITCH=4;CMD=OFF;
20;E0;NewKaku;ID=cac142;SWITCH=1;CMD=ALLOFF;
20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF;
20;0B;NewKaku;ID=000005;SWITCH=2;CMD=ON;
20;0E;NewKaku;ID=000005;SWITCH=2;CMD=OFF;
20;12;NewKaku;ID=000002;SWITCH=2;CMD=OFF;
20;1E;NewKaku;ID=00000a;SWITCH=2;CMD=OFF;
20;1F;NewKaku;ID=00000a;SWITCH=2;CMD=ON;
20;01;NewKaku;ID=000007;SWITCH=2;CMD=OFF;
20;04;NewKaku;ID=000007;SWITCH=2;CMD=ON;
20;04;NewKaku;ID=000007;SWITCH=2;CMD=SET_LEVEL=14;
20;0C;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLON;
20;AD;FA500;ID=0d00b900;SWITCH=0001;CMD=UNKOWN;
20;AE;FA500;ID=0a01;SWITCH=0a01;CMD=OFF;
20;03;Eurodomest;ID=03696b;SWITCH=00;CMD=OFF;
20;04;Eurodomest;ID=03696b;SWITCH=07;CMD=ALLOFF;
20;41;Conrad RSL2;ID=010002;SWITCH=03;CMD=ON;
20;47;Blyss;ID=ff98;SWITCH=A1;CMD=ON;
20;73;Kambrook;ID=010203;SWITCH=A1;CMD=OFF;
Note that for sensors that only report values like temperature, only the data and the ID are required.
Name labels can be thrown away or used for cosmetic purposes.
For switches, the protocol name has to be stored and re-used on the transmission side.
Thus, when a remote control is used to control a device data like below will be send from the RFLink Gateway over USB:
20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF;
When the state of this switch needs to be changed the following command has to be send:
10;NewKaku;0cac142;3;ON;
The name label (here "NewKaku") is used to tell the RFLink Gateway what protocol it has to use for the RF broadcast.
Special Control Commands - Send:
--------------------------------
10;REBOOT; => Reboot RFLink Gateway hardware
10;PING; => a "keep alive" function. Is replied with: 20;99;PONG;
10;VERSION; => Version and build indicator. Is replied with: 20;99;"RFLink Gateway software version";
10;RFDEBUG=ON; => ON/OFF to Enable/Disable showing of RF packets. Is replied with: 20;99;RFDEBUG="state";
10;RFUDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;RFUDEBUG="state";
10;QRFDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;QRFDEBUG="state";
QRFDEBUG is a faster version of RFUDEBUG but all pulse times are shown in hexadecimal and need to be multiplied by 30
Packet structure - To Send data via RF:
---------------------------------------
10;Protocol Name;device address,button number;action;
Sample data of transmitted RF packets:
--------------------------------------
10;Kaku;00004d;1;OFF; => Kaku/ARC protocol;address;action (ON/OFF)
10;AB400D;00004d;1;OFF; => Sartano protocol;address;action (ON/OFF)
10;Impuls;00004d;1;OFF; => Impuls protocol;address;action (ON/OFF)
10;NewKaku;00c142;1;ON; => Newkaku/AC protocol;address (24 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level)
10;NewKaku;128ac4d;1;OFF; => Newkaku/AC protocol;address (28 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level)
10;Eurodomest;123456;01;ON; => Eurodomest protocol;address;button number;action (ON/OFF/ALLON/ALLOFF)
10;Blyss;ff98;A1;OFF; => Blyss protocol;address;button;action (ON/OFF/ALLON/ALLOFF)
10;Conrad;ff0607;1;OFF; => Conrad RSL protocol, address, button number, action (ON/OFF/ALLON/ALLOFF)
10;Kambrook;050325;a1;ON; => Kambrook protocol, address, unit/button number, action (ON/OFF)
10;X10;000041;1;OFF; => X10 protocol;address;action (ON/OFF)
10;HomeConfort;01b523;D3;ON;=> HomeConfort protocol;address;action (ON/OFF)
10;FA500;001b523;D3;ON; => Flamingo protocol;address;action (ON/OFF)
10;Powerfix;000080;0;ON; => Powerfix/Quigg/Chacon protocol;address;action (ON/OFF)
10;Ikea Koppla;000080;0;ON; => Koppla protocol;address;action (ON/OFF)
10;HomeEasy;7900b100;3;ON; => Home Easy protocol;address;action (ON/OFF/ALLON/ALLOFF)
10;EV1527;000080;0;ON; => EV1527 protocol;address;device 0x00-0x0f,action ON/OFF
10;Chuango;000080;2;ON; => Chuango Protocol;address;action (ON/OFF/ALLON/ALLOFF)
10;Selectplus;001c33; => SelectPlus protocol;address
10;Byron;112233;01;OFF; => Dyron SX protocol;address;ringtone
10;DELTRONIC;001c33; => Deltronic protocol;address
10;BYRON;00009F;01;ON; => Byron protocol;address;chime number,command
10;FA20RF;67f570;1;ON; => Flamingo FA20RF / FA21 / KD101 protocol, address, button number, action (ON/OFF/ALLON/ALLOFF)
10;MERTIK;64;UP; => Mertik protocol, address, command

BIN
Doc/RFLink Schematic.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

23
Doc/Readme_Loader.txt Normal file
View File

@ -0,0 +1,23 @@
RFLink Loader Version 1.02
The RFLink Loader program runs on Windows and can program an Arduino Mega 2560 board
with the RFLink software.
You do not need any Arduino IDE/Compiler etc.
Steps:
------
- Launch the program
- Select the file you want to program (rflink.cpp.hex)
- Select the serial port to which the Arduino is connected.
- Hit the "program" button and wait for the process to finish.
History:
--------
1.02 Fixed: could not use serial ports > 9
1.01 Fixed: could not load the hex file if the path name contained a space
Added: test serial port availability before trying to program the Arduino
1.00 Initial Release

273
Doc/Readme_RFLink.txt Normal file
View File

@ -0,0 +1,273 @@
! ============================================================================
! Only for educational purposes, the source might not be synchronized with the
! latest release!
! For normal operation, use the RFLink Loader that includes the latest release
! ============================================================================
Please note that the RFLink Gateway is a freeware project.
Stuntteam is not making money in any way.
This means that there are no unlimited funds to purchase test devices,
it also means the project has to rely on you, the user, to send debug data.
If you want to contribute to this project, you can send a donation which is more than welcome (see www.nemcon.nl/blog2 donation button),
or help with sending debug data of unsupported devices (you can even write and contribute plugins and/or code fixes),
or donate the device that you would like to see supported.
Right now we are looking for some older remotes and/or switches.
Like for example: Impuls, Ikea Koppla, Powerfix, Blyss, Home Confort, Conrad, Kambrook, Everflourish
For the implementation of the planned 2.4Ghz support we could use some simple MySensor devices.
For the implementation of the planned 868Mhz support we could use some devices as well.
If you have anything that you do not use, send a mail to frankzirrone@gmail.com
Thanks in advance!
------------------------
Synology NAS:
If you want to use RFLink with a Synology NAS you can use:
- an Arduino Mega clone based on CH340 USB/serial chip
In all other cases:
- connect a 10 uF capacitor between reset and ground on the Arduino.
Simply stick the pins of the capacitor in the power connector socket.
When you want to update the firmware of the Arduino, remove the capacitor and reconnect it when done.
For details about the Domoticz Synology package check out: http://www.jadahl.com
------------------------
RFlink via Network Connection:
It is possible to use RFlink via a network connection using ser2net.
------------------------
You can now use the RFLink Gateway with the following home automation software:
Domoticz
Jeedom
------------------------
R35: (Work-In-Progress) Build 05
- Added: Brel motor support
- Fixed: Oregon OWL CM119, CM160, CM180
- Fixed: Corrected WH440 temperature values
- Fixed: Improved Philips SBC
- Fixed: Improved Chacon EMW200
- Fixed: Removed a slash in the UPM/Esic name
- Tested: tested and working: Lidl / Libra TR502MSV switches
R34:
- Added: Heidemann HX Silverline 70290
- Added: Eurochron EAS 301Z / EAS 302
- Added: Znane-01 switch set sold at Biedronka (Impuls clone)
- Added: HomeEasy HE800 protocol support
- Added: Fine Offset Electronics WH2, Agimex Rosenborg 66796, ClimeMET CM9088
- Added: Somfy Smoove Origin RTS (433mhz) (receive)
- Tested: Eurodomest 972086 (Sold at Action in Belgium)
- Added: Eurodomest revised protocol (full autodetection)
- Added: Prologue temperature sensor support
- Tested: tested and working: Home Confort, Smart Home PRF-100 switch set
- Fixed: Auto detection of "Emil Lux"/LUX-Tools remote control/switch set (Sold at Obi.de Art.Nr. 2087971) (Impuls clone)
- Fixed: Alecto WS1100 working properly again (Adjusted pulse range and displayed humidity value)
- Fixed: Byron SX receive and send commands
- Fixed: Ikea Koppla Send routines
- Fixed: Improved the Impuls remote detection
- Fixed: Impuls transmit
- Changed: added checks for valid temperatures in various plugins
R33:
- Updated RFlink loader to version 1.03 to include a serial log option with command sending ability!
- Added: Full automatic 'Flamingo FA500/SilverCrest 91210/60494 RCS AAA3680/Mumbi M-FS300/Toom 1919384' protocol support! (send & receive!)
Note: re-learn your FA500 Remote in Domoticz
- Added: Unitec 48111/48112 (receive)
- Added: Avidsen
- Added: Somfy Telis (433mhz) (receive)
- Fixed: Extreme temperature value rejection for various sensor types (TFA/LaCrosse)
- Fixed: Improved Blyss send routines
- Added: Support for old Xiron temperature sensor in Cresta plugin (Temperature only sensor was not handled)
- Added: Biowin meteo sensor
- Fixed: Imagintronix humidity and temperature values were sometimes incorrect
- Fixed: AB4400/Sartano/Phenix detection corrected
- Fixed: Modification to allow EMW200/203 to work better
- Changed: ARC (and compatible) remote and switch handling improved
- Fixed: Improved Impuls handling
- Fixed: Auriol V3 minus temperature handling
- Fixed: TRC02RGB send
- Fixed: Oregon OWL180 data
- Changed: Aster signal detection so that L^Home model 32311T is recognized as well
- Changed: ID for Nodo Slave 'Wind direction/Wind gust' combined so that Domoticz can handle the data
- Changed: Protocol handling order for 'multi-protocol' transmitting devices
R32:
- Added: Europe RS-200, Conrad TR-200
- Added: Bofu motor transmit
- Added: ARC group command support
- Added: support for ARC based tri-state protocol
- Tested and working: Hormann 868mhz receive
- Changed: Bofu motor signal repetition detection improved
- Fixed: Aster transmit routines
- Fixed: plugin 003 output was not processed correctly by Domoticz
- Fixed: ARC higher address numbers did not work correctly in combination with Domoticz
- Changed: Chacon/Powerfix/Mandolyn/Quigg transmit routine and optimized timing
- Changed: Increased the number of re-transmits in the Home Easy protocol to improve signal reception and distance
- Changed: Sensor plugins now suppressing ARC derived protocols a bit better
R31:
- New Device: Forrinx Wireless Doorbell
- New Device: TRC02 RGB controller
- New Device: OWL CM180
- New Device: ELMES CTX3H and CTX4H contact sensor
- New Device: Bofu Motor (receive)
- New Device: Aster / GEMINI EMC/99/STI/037
- Changed: EV1527 based sensors were reported as X10, now they are reported as EV1527. Note that it might be needed to re-add the devices to Domoticz
- Changed: increased number of retransmits for ARC and AC protocols
- Fixed: Koppla switch number was incorrect
- Fixed: Powerfix/Mandolyn/Chacon Parity calculation in send routines
- Fixed: Powerfix/Mandolyn/Chacon timing
- Fixed Windspeed value for WS2300
- Fixed: Home Easy HE300 ON/OFF signal was reversed
- Changed: HomeEasy suppressing additional protocol data to avoid reporting the same event multiple times under different protocols
- Fixed: More fixes to avoid duplicate reporting of the same event (various protocols)
R30:
- New Device: Conrad 9771 Pool Thermometer
- New Device: SilverCrest Z31370-TX Doorbell
- New Device: Smartwares remote controls (among others: SH5-TDR-K 10.037.17)
- New Device: Chuango Alarm devices Motion/Door/Window etc. (among others: CG-105S)
- New Device: Oregon Scientific NR868 PIR/night light
- New Device: Oregon Scientific MSR939 PIR
- New Device: Imagintronix Temperature/Soil humidity sensor
- New Device: Ikea Koppla (receive)
- New Device: Chacon (TR-502MSV, NR.RC402)
- Fixed: Arc protocol send
- Fixed: Impuls. Note: pair devices with the KAKU protocol, the remote is recognized separately. (Needs more tests!)
- Changed: Plugin 3 send method, combined routines
- Changed: HomeConfort was recognized as Impuls, now using GDR2 name
- Changed: HomeEasy remotes can deliver various signals, now skipping KAKU compatible signals and just reporting the HomeEasy code when both codes are transmitted
- Fixed: HomeEasy group on/off command was reversed for HE8xx devices, now correctly detects differences between HE3xx and HE8xx
- Fixed: HomeEasy was not able to control HE87x switches, changed the entire transmit routine
- Changed: stretched Xiron timing checks
- Changed: Various timing modifications (NewKaku/AC, Blyss) due to the new timing introduced at version R26
- Changed: Plugin 61, Chinese Alarm devices, reversed bits as it seemed to correspond better to bit settings, increased address range
- Fixed: Flamingo Smokedetector packet detection tightened up to prevent false positives
- Fixed: Corrected Conrad RSL command interpretation
- Added: Extended Nodo Slave support to support separate and combined sensors
- Added: Extended Nodo Slave support to support pulse meters
R29:
- Fixed: AC/NewKaku high unit numbers were incorrect.
If you already have devices with high unit numbers in Domoticz, just throw them away and let them be recognized again
R28:
- Fixed: FA20RF smoke detector transmit from Domoticz
R27:
- Added: OSV1 battery status
- Fixed: OSV1 boundaries and removed some debug info
- Fixed: Some plugins set an incorrect sampling rate divider value
- Changed: AlectoV1 false positives filter was too agressive
R26:
- Added: QRFDEBUG command to do faster logging of undecoded data
- Added: VERSION command
- Added: Powerfix/Quigg switches
- Added: proper Lacrosse V3 WS7000 sensor support
- Changed: config file and plugin integration
- Changed: timeout and divider value
- Changed: Lacrosse V2 WS2300/WS3600 plugin number to get faster processing, changed various other parts as well
- Changed: Lacrosse V1 pulse duration checks
- Changed: various parts to improve speed
- Changed: Flamingo Smoke detector signal re-transmits from 8 to 10 times
- Added: Additional tests on Alecto V1 and Alecto V4 to filter out false positives
- Fixed: AC (NewKaku) protocol send for some device numbers
- Fixed: little bug in UPM code
- Fixed: Oregon wind speed reporting
- Fixed: Wind speed calculations
- Fixed: Wind direction reporting in all plugins
- Fixed: AlectoV3 humidity value displaying out of range values
- Fixed: OregonV1 decoding
R25:
- Fixed: Eurodomest address range check
- Fixed: Alecto V1 and V3 humidity handling
- Fixed: Lacrosse WS2300/WS3600 and labelled as LacrosseV2
R24:
- Fixed: Flamingo Smoke Detector timings and device address usage
- Fixed: Timing for Nexa/Jula Anslut
R23:
- Changed: Alecto V1 temperature data filtering
- Added: Alecto V1 battery status now shown for temperature sensors
R22:
- Various additional tests and fixes after intensive tests
- Added: Home Confort send and recognition by Domoticz
R21:
- Re-Activated PIR & Door/Window sensors (plugin 60/61)
R20:
- Switched to Arduino 1.6.5
R19:
- Complete rewrite
- Added: Home Confort Smart Home - TEL-010
- Added: RGB LED Controller
- Added: RL-02 Digital Doorbell
- Added: Deltronic Doorbell
- Added: Sartano 2606 remote & switch
r18:
- Added Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor
- Tested Okay: Promax RSL366T, Profile PR-44N & PR-47N
- Fixed: LaCrosse humidity values are correctly displayed
- Fixed: Humidity values that originate from slave Nodos are correctly displayed
- Fixed: UPM/Esic insane temperature values are skipped
- Removed Xiron & Auriol debug data
- Tightened pulse range on various protocols to prevent false positives
r17:
- Modified Oregon THGR228N code,
- Modified Newkaku(AC) dim values,
- Corrected support for KAKU door switches,
- Fixed Nodo Slave sensors,
- Improved speed and priorities so that group commands are properly transmitting
r16:
- Fixed Aleco V1 temperature ID to match wind sensors
- Fixed HomeEasy transmit
- Added AC(NewKaku) dimmer support
r15:
- Improved large packet translation
r14:
- Changed Motion sensors (60/61)
r13:
- Flamingo Smoke detector fix
- Added Xiron sensor support
r11/12:
- Mertik / Dru Send added
r10:
- Added Auriol Z32171A
r9:
- Fixed Kaku send with high device id's (P1 M1 etc)
r8:
- Improved descriptions
r7:
- Fixed Oregon RTGR328N ID and humidity format
- Fixed UPM/Esic humidity format
- Fixed Alecto humidity format
r6:
- Fixed Auriol V2 plugin
- Updated Auriol plugin
- Fixed Lacrosse Humidity
r1/2/3/4/5:
- Added X10 receive/transmit plugin
- Minor changes & improvements
Special thanks to:
Alex, Benoit, Bert, Christophe, Deennoo, Emmanuel, Gerrit, Goran, Graeme, Jelle, John, Jonas, Marek, Mark, Martinus, Maurice,
Paul, Pim, Remco, Richard, Rob, Sebastien, Thibaut, William
and everyone who contributed with feedback, suggestions, debug data, tests etc.

View File

@ -0,0 +1,233 @@
============================================================================
Nodo - RFLink supported devices list
============================================================================
Remote Controls and Electrical Switches / Dimmers etc.:
-------------------------------------------------------
ARC Protocol: (Send + Receive)
- Klik Aan Klik Uit (Code Wheel)
- Princeton PT2262
- MOSDESIGN M3EB
- Domia Lite
- Intertechno
- CoCo Technologies
- Cogex
- D-IO (Chacon)
- Nexa
- Düwi Terminal
- Promax RSL366T
- Conrad 640472, 640473, 640475, 640476
- ME FLS 100
- Profile PR-44N, PR-47N
- Sartano 2606
- Impuls
- Elro AB400
- Waveman
- Elro Home Comfort AB600
- (Elro) Home Control
- Smarthome YC-4000B
- Phenix YC-4000S
- Pollin Funk-Dimmer HouseLight FD-UP001
- Pollin Funk-Steckdosen-Set 2605
- Conrad 646443 outlet sockets / RSL366R
- Proteam HO1853
- Velleman WRS3B
- "Emil Lux"/LUX-Tools (Obi.de Art.Nr. 2087971)
- Znane-01 switch set sold at Biedronka (Impuls clone)
- Renkforce
Automatic Code Learning Protocols: (Send + Receive)
- Klik Aan Klik Uit
(All products, among others: AWMR210, AWMT230, AWMD250, AWST8800)
- CoCo Technologies
- Trust SmartHome
- Nexa Jula Anslut
(among others: 408-063, 408-064)
- Home Easy EU (among others HE100, HE200, HE300, AB600/HE600, HE800)
- Smartwares (SH5-TDR-K 10.037.17)
Others: (Send + Receive)
- Home Easy (Code Wheel)
- Unitec 48110 EIM 826 / 48111 EIM 821
- Quigg GT-1000 RC / Quigg GT-FSI-08
- Intertek Eurodomest 972080 (Protocol revision 1 & 2 - full autodetection)
- Intertek Eurodomest 972086 (Protocol revision 1 & 2 - full autodetection)
- Blyss
- Conrad RSL2, Conrad RSL88R/B
- Kambrook RF3399/RF3405/RF3672/RF3689/RF4471R
- X10 RF switches
- Home Confort Smart Home - Among others: TEL-010, PRF-100
- Quigg GT-7008BS, Quigg GT-FSI-04
- DMV-7008S
- Mandolyn RC-710
- Powerfix RCB-I 3600
- Quigg GT-8000
- Chacon (TR-502MSV, NR.RC402)
- Rev Ritter REV 8342L
- Ikea Koppla
- TRC02 RGB Controller
- Aster / GEMINI EMC/99/STI/037
- Silvercrest l36-001
- Brennenstuhl RCS 1000 N Comfort
- Lidl / Libra TR502MSV
- Flamingo FA500R/S/DSS/WD
- SilverCrest 91210/60494 RCS AAA3680
- Mumbi M-FS300
- Toom 1919384
============================================================================
Weather Sensors:
----------------
- Alecto V1:
Alecto WS3500, SilverCrest, Otio SH-10, Otio SH-20
Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160
Alecto WS4500, Ventus W044, Balance RF-WS105
- Alecto V2: (868 Mhz!)
ACH2010, DKW2012
- Alecto V3:
WS1100, WS1200
- Alecto V4:
Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor
- Cresta/Hideki:
Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W,
WXR810, DV928, Ventus W906, HomeWizard Rain meter
- Mebus:
Mebus Outdoor Sensor
Stacja Pogody WS-9941-M
- UPM/Esic:
UPM, Esic, Emos, DVM, Clas Ohlson, Dickson
WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700
- LaCrosse:
Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4
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)
- LaCrosseV2:
WS2300 (Temperature/Humidity/Wind/Rain), WS2310, WS2355, WS3600
- Auriol:
Z31743, Rubicson
- Auriol V2:
Z31055A-TX, Xiron, Watshome YT6018-2, Technoline
- Auriol V3:
Z32171A
- FineOffset:
Fine Offset Electronics WH2, Agimex Rosenborg 66796, ClimeMET CM9088
- Eurochron:
EAS 301Z / EAS 302
- Prologue:
Clas Ohlson 36-4741, Clas Ohlson 36-5087
- Oregon V1/2/3:
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, BTHG968, OWL CM180, BTHGN129
============================================================================
Pool/Water Thermometer
Conrad 9771 Pool Thermometer
============================================================================
Soil : Temperature & Moisture/Humidity Sensors
Imagintronix XH300 sensor
TH12 Opus TX300
============================================================================
Dusk Sensors (Light On/Off detection):
-----------------------------------
KAKU ABST-604
Home Easy HE863
Intertechno ITDS-5
============================================================================
Window blinds/shutters/sun screens:
-----------------------------------
Kaku ASUN650
Intertechno CMR-500, ITL-500, ITL-1000
============================================================================
Motion Detectors:
--------------------------------
Low Budget Chinese PIR (only signals motion detection)
Aritech PIR (only signals motion detection)
Ajax Chub Varel PIR (only signals motion detection)
Chuango: among others PIR-900 PIR sensor
Oregon Scientific NR868 PIR/night light
Oregon Scientific MSR939 PIR
============================================================================
Door/Window sensors:
--------------------------------
Low Budget Chinese Door/Window detectors
Intertechno ITM-100
KAKU AMST-606 door/window sensor (separate signals for open and close)
Home Easy HE852 (separate signals for open and close)
CHACON DIO 54781 (separate signals for open and close)
COCO (separate signals for open and close)
Evology door/window contact sensor
ELMES CTX3H, CTX4H
Chuango: among others DWC-100 Door sensor, DWC-102 Door sensor
============================================================================
Fireplace:
----------
Mertik G6R H4T1 / Dru
============================================================================
Smoke Detectors:
----------------
KD101 (Send + Receive)
Diamant Smoke alarm (Send + Receive)
Flamingo FA20RF (Send + Receive)
Chacon 34126 (Send + Receive)
============================================================================
Doorbells:
----------
SelectPlus (200689103 - Black - Date code:0614), 1 by One, Delta (O00 QH-0031) (Send + Receive)
SelectPlus (200689101 - White - Date code:0914) (Send + Receive)
KAKU ACDB 6500BC (Send + Receive)
Deltronic Wireless Doorbell (Send + Receive)
RL-02 Wireless Doorbell (Send + Receive)
Byron SX (Send + Receive)
SilverCrest Z31370-TX (Receive)
Forrinx (Receive)
Heidemann HX Silverline 70290 (Receive)
L^Home model 32311T (Receive)
Plieger York (Receive)
Note that when the Plieger button is detected as Conrad RSL2, you need to use the button
on the inside of the Plieger doorbell to change the address code of the Plieger.
============================================================================
Nodo Slave Sensors:
-------------------
Various Nodo sensor types are supported.
Make sure you use Nodo Slave ID 1,2, 4 till 9 to make the sensor a separate sensor.
If you want to have combined sensors (eg temperature + humidity in one device) make sure
you use Nodo Slave ID 10 till 16
The following variable / sensor types are currently supported
Variabele 5 : Temperature
Variabele 6 : Humidity
Variabele 7 : Rain
Variabele 8 : Wind speed
Variabele 9 : Wind direction
Variabele 10 : Wind gust
Variable 11, 12 en 13 : Temperature
Variable 14 : Humidity
Variable 15 : UV
Variable 16 : Barometric pressure
Electricity/Water/Gas pulse meters are supported when using the following Nodo variable numbers:
Make sure the slave devices are using Nodo Slave ID 3 !!!
Variabele 1 : Pulse value 1
Variabele 2 : Pulse value 2
Variabele 3 : Pulse value 3
Variabele 4 : Pulse value 4
Variabele 5 : Pulse value 5
Variabele 6 : Pulse value 6
If you require support for other sensors just let us know.
============================================================================
Chuango
* G5 GSM/SMS/RFID Touch Alarm System
* DWC-100 Door sensor
* DWC-102 Door sensor
* KP-700 Wireless Keypad
* PIR-900 PIR sensor
* RC-80 Remote Control
* SMK-500 Smoke sensor

65
License.txt Normal file
View File

@ -0,0 +1,65 @@
=====================================================================================================================================
RFLINK GATEWAY LICENSE v1.0
=====================================================================================================================================
Arduino project "RFLink Gateway"
© Copyright 2015..2016 Stuntteam
(Portions © Copyright 2010..2015 Paul Tonkes (some Nodo 3.7 code parts))
Documentation : http://sourceforge.net/projects/rflink/
Questions/Suggestions etc. mail to : frankzirrone@gmail.com
Compiler : http://arduino.cc
=====================================================================================================================================
LICENSE TERMS AND CONDITIONS
The RFLink distributed and pre-compiled code is made available free of charge and without any warranties.
This License explicitly affirms your unlimited permission to run the unmodified Program.
If someone made you pay for this program, contact us!
The RFLink Gateway Source Code is made available so that third parties can develop their own plugins for the RFLink Gateway.
Availability of the core code and functional sample plugins does not mean that each and every plugin will be open source.
The fact that the code is published does not mean you obtain any kind of ownership or get any rights to the code.
This License explicitly affirms that you have the right to use the source code as a development environment to create your
own plugins which you can share with the community and project maintainers.
When you publish your plugin with the community it automatically falls under this license. However, it is also possible to share your
plugin with the project maintainers and keep your plugin closed source. In that case, the compiled portions of your code will
automatically fall under this license. All contributors hold the copyright for their own work.
The source code is free for use in any open source project when the original copyright notices, headers and this license file are included.
This program is free software: you can redistribute it and/or modify it when the original copyright notices and headers are included.
You are not allowed to sell the pre-compiled code or the source code or distribute it without this license file.
Usage of any parts of this code in a commercial work is prohibited unless express written approval is granted!
Some parts of the code might contain watermarking to identify our work.
You are not allowed to decompile, disassemble or reverse engineer any parts of the pre-compiled program.
The license does not permit incorporating this program into proprietary programs.
Disclaimer of Warranty.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
The copyright holders provide the program "AS IS" without warranty of any kind, either expressed or implied, including, but not limited to,
the implied warranties of merchantability or fitness for a particular purpose. The entire risk as to the quality and performance of the program
is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction.
Limitation of Liability.
In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party who modifies and/or conveys
the program as permitted above, be liable to you for damages, including any general, special, incidental or consequential damages arising out of the
ues or inability to use the program (including but not limited to loss of data being rendered inaccurate or losses sustained by you or third
parties or a failure of the program to operate with any other programs), even if such holder or other party has been advised of the possibility of
such damages.
-------------------------------------------------------------------------------------------------------------------------------------
Warning:
The RFLink Gateway should not be used in any life-threatening situations.
The RFLink Gateway is NOT justified to be used as a main part of a primary alarm system.
RFLink may only be used to listen to alarm sensors or activate a siren to complement a home automation system.
Note that if you own an alarm system which RFLink could disarm by broadcasting a recorded signal, it is time to upgrade your alarm system.
-------------------------------------------------------------------------------------------------------------------------------------
Installation information:
All files should be located in a directory named "RFLink".
Install the Arduino compiler. You can download the compiler at www.arduino.cc
Preffered is 1.6.5 or similar
Open from the Arduino IDE the file RFlink.ino
-------------------------------------------------------------------------------------------------------------------------------------

78
Misc.ino Normal file
View File

@ -0,0 +1,78 @@
/*********************************************************************************************\
* Convert HEX or DEC tring to unsigned long HEX, DEC
\*********************************************************************************************/
unsigned long str2int(char *string) {
return(strtoul(string,NULL,0));
}
/*********************************************************************************************\
* Convert string to command code
\*********************************************************************************************/
int str2cmd(char *command) {
if(strcasecmp(command,"ON") == 0) return VALUE_ON;
if(strcasecmp(command,"OFF") == 0) return VALUE_OFF;
if(strcasecmp(command,"ALLON") == 0) return VALUE_ALLON;
if(strcasecmp(command,"ALLOFF") == 0) return VALUE_ALLOFF;
if(strcasecmp(command,"PAIR") == 0) return VALUE_PAIR;
if(strcasecmp(command,"DIM") == 0) return VALUE_DIM;
if(strcasecmp(command,"BRIGHT") == 0) return VALUE_BRIGHT;
if(strcasecmp(command,"UP") == 0) return VALUE_UP;
if(strcasecmp(command,"DOWN") == 0) return VALUE_DOWN;
if(strcasecmp(command,"STOP") == 0) return VALUE_STOP;
if(strcasecmp(command,"CONFIRM") == 0) return VALUE_CONFIRM;
if(strcasecmp(command,"LIMIT") == 0) return VALUE_LIMIT;
return false;
}
/********************************************************************************************\
* Convert unsigned long to float long through memory
\*********************************************************************************************/
float ul2float(unsigned long ul) {
float f;
memcpy(&f, &ul,4);
return f;
}
/*********************************************************************************************/
void PrintHex8(uint8_t *data, uint8_t length) { // prints 8-bit data in hex (lowercase)
char tmp[length*2+1];
byte first ;
int j=0;
for (uint8_t i=0; i<length; i++) {
first = (data[i] >> 4) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first ;
j++;
first = (data[i] & 0x0F) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first;
j++;
}
tmp[length*2] = 0;
Serial.print(tmp);
}
/*********************************************************************************************/
// todo: make uppercase? 3a = 3 or 48 (0x30) = 0x33 >57 (0x39) a>3a >39 > +27
void PrintHexByte(uint8_t data) { // prints 8-bit value in hex (single byte)
char tmp[3];
byte first ;
first = (data >> 4) | 48; // or with 0x30
if (first > 57) tmp[0] = first + (byte)7; // 39; // if > 0x39 add 0x27
else tmp[0] = first ;
first = (data & 0x0F) | 48;
if (first > 57) tmp[1] = first + (byte)7; // 39;
else tmp[1] = first;
tmp[2] = 0;
Serial.print(tmp);
}
/*********************************************************************************************/
// Reverse all bits in a byte
byte reverseBits(byte data) {
byte b = data;
for (byte i = 0; i < 8; ++i) {
data = (data << 1) | (b & 1);
b >>= 1;
}
return data;
}
/*********************************************************************************************/

1532
Plugin.ino Normal file

File diff suppressed because it is too large Load Diff

617
Plugins/Plugin_001.c Normal file
View File

@ -0,0 +1,617 @@
//#######################################################################################################
//## 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) {
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
// ==========================================================================
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
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 700/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMAX 2000/RAWSIGNAL_SAMPLE_RATE
#define ALARMPIRV1_PULSEMIN 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) {
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) | 0x1;
} 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;
}
}
//==================================================================================
// 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

83
Plugins/Plugin_063.c Normal file
View File

@ -0,0 +1,83 @@
//#######################################################################################################
//## 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) {
if (RawSignal.Pulses[0] != 63) return false; // Only accept RF packets converted by plugin 1
RawSignal.Pulses[0]=0;
if ((RawSignal.Number < OREGON_PLA_PULSECOUNT-2) || (RawSignal.Number > OREGON_PLA_PULSECOUNT) ) return false;
unsigned long bitstream=0L;
//==================================================================================
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

28
RFLink.ino Normal file
View File

@ -0,0 +1,28 @@
// *********************************************************************************************************************************
// * Arduino project "Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1"
// * © Copyright 2015 StuntTeam - NodoRFLink
// * Portions © Copyright 2010..2015 Paul Tonkes (original Nodo 3.7 code)
// *
// * Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1
// *
// ********************************************************************************************************************************
// * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
// * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// * You received a copy of the GNU General Public License along with this program in file 'COPYING.TXT'.
// * For more information on GPL licensing: http://www.gnu.org/licenses
// ********************************************************************************************************************************
// ================================================================================================================================
// Supply the full path to the RFLink files in the define below
//
// Geef in onderstaande "define" regel het volledige pad op waar de .ino bestanden zich bevinden die je nu geopend hebt.
// ================================================================================================================================
#define SKETCH_PATH D:\arduino\RFLink
// ================================================================================================================================
// IMPORTANT NOTE: This code only runs on an Arduino MEGA !!!!!!!!!!!!!!!!!!!!!! It was designed that way for various reasons.
// ================================================================================================================================

119
RawSignal.ino Normal file
View File

@ -0,0 +1,119 @@
/*********************************************************************************************/
boolean ScanEvent(void) { // Deze routine maakt deel uit van de hoofdloop en wordt iedere 125uSec. doorlopen
unsigned long Timer=millis()+SCAN_HIGH_TIME;
while(Timer>millis() || RepeatingTimer>millis()) {
if (FetchSignal(PIN_RF_RX_DATA,HIGH)) { // RF: *** data start ***
if ( PluginRXCall(0,0) ) { // Check all plugins to see which plugin can handle the received signal.
RepeatingTimer=millis()+SIGNAL_REPEAT_TIME;
return true;
}
}
}// while
return false;
}
/**********************************************************************************************\
* Haal de pulsen en plaats in buffer.
* bij de TSOP1738 is in rust is de uitgang hoog. StateSignal moet LOW zijn
* bij de 433RX is in rust is de uitgang laag. StateSignal moet HIGH zijn
*
\*********************************************************************************************/
const unsigned long LoopsPerMilli=345;
const unsigned long Overhead=0;
// Because this is a time critical routine, we use global variables so that the variables
// do not need to be initialized at each function call.
int RawCodeLength=0;
unsigned long PulseLength=0L;
unsigned long numloops=0L;
unsigned long maxloops=0L;
boolean Ftoggle=false;
uint8_t Fbit=0;
uint8_t Fport=0;
uint8_t FstateMask=0;
/*********************************************************************************************/
boolean FetchSignal(byte DataPin, boolean StateSignal) {
uint8_t Fbit = digitalPinToBitMask(DataPin);
uint8_t Fport = digitalPinToPort(DataPin);
uint8_t FstateMask = (StateSignal ? Fbit : 0);
if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is
// Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze
// routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit
// geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte
// rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht.
if (RawSignal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel...
if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer!
PulseLength=micros()+SIGNAL_TIMEOUT*1000; // delay
while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros())
if ((*portInputRegister(Fport) & Fbit) == FstateMask)
PulseLength=micros()+SIGNAL_TIMEOUT*1000;
while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && (*portInputRegister(Fport) & Fbit) != FstateMask);
}
}
RawCodeLength=1; // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc.
Ftoggle=false;
maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli);
do{ // read the pulses in microseconds and place them in temporary buffer RawSignal
numloops = 0;
while (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) // while() loop *A*
if (numloops++ == maxloops) break; // timeout
PulseLength=((numloops + Overhead)* 1000) / LoopsPerMilli; // Contains pulslength in microseconds
if (PulseLength<MIN_PULSE_LENGTH) break; // Pulse length too short
Ftoggle=!Ftoggle;
RawSignal.Pulses[RawCodeLength++]=PulseLength/(unsigned long)(RAWSIGNAL_SAMPLE_RATE); // store in RawSignal !!!!
} while (RawCodeLength<RAW_BUFFER_SIZE && numloops<=maxloops); // For as long as there is space in the buffer, no timeout etc.
if (RawCodeLength>=MIN_RAW_PULSES) {
RawSignal.Repeats=0; // no repeats
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // sample size.
RawSignal.Number=RawCodeLength-1; // Number of received pulse times (pulsen *2)
RawSignal.Pulses[RawSignal.Number+1]=0; // Last element contains the timeout.
RawSignal.Time=millis(); // Time the RF packet was received (to keep track of retransmits
return true;
} else {
RawSignal.Number=0;
}
}
return false;
}
/*********************************************************************************************/
// RFLink Board specific: Generate a short pulse to switch the Aurel Transceiver from TX to RX mode.
void RFLinkHW( void ) {
delayMicroseconds(36);
digitalWrite(PIN_BSF_0,LOW);
delayMicroseconds(16);
digitalWrite(PIN_BSF_0,HIGH);
return;
}
/*********************************************************************************************\
* Send rawsignal buffer to RF * DEPRICATED * DO NOT USE *
\*********************************************************************************************/
void RawSendRF(void) { // * DEPRICATED * DO NOT USE *
int x;
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)
RawSignal.Pulses[RawSignal.Number]=1; // due to a bug in Arduino 1.0.1
for(byte y=0; y<RawSignal.Repeats; y++) { // herhaal verzenden RF code
x=1;
noInterrupts();
while(x<RawSignal.Number) {
digitalWrite(PIN_RF_TX_DATA,HIGH);
delayMicroseconds(RawSignal.Pulses[x++]*RawSignal.Multiply-5); // min een kleine correctie
digitalWrite(PIN_RF_TX_DATA,LOW);
delayMicroseconds(RawSignal.Pulses[x++]*RawSignal.Multiply-7); // min een kleine correctie
}
interrupts();
if (y+1 < RawSignal.Repeats) delay(RawSignal.Delay); // Delay buiten het gebied waar de interrupts zijn uitgeschakeld! Anders werkt deze funktie niet.
}
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();
}
/*********************************************************************************************/

40
Readme_RFLink.txt Normal file
View File

@ -0,0 +1,40 @@
! ============================================================================
! Only for educational purposes, this source is not be synchronized with the
! latest release!
! For normal operation, use the RFLink Loader that includes the latest release
! This source code tree is made available so that you can develop your own plugins
! ============================================================================
Please note that the RFLink Gateway is a freeware project.
Stuntteam is not making money in any way.
This means that there are no unlimited funds to purchase test devices,
it also means the project has to rely on you, the user, to send debug data.
If you want to contribute to this project, you can send a donation which is more than welcome (see www.nemcon.nl/blog2 donation button),
or help with sending debug data of unsupported devices (you can even write and contribute plugins and/or code fixes),
or donate the device that you would like to see supported.
Right now we are looking for some older remotes and/or switches.
Like for example: Impuls, Ikea Koppla, Powerfix, Blyss, Home Confort, Conrad, Kambrook, Everflourish
For the implementation of the planned 2.4Ghz support we could use some simple MySensor devices.
For the implementation of the planned 868Mhz support we could use some devices as well.
If you have anything that you do not use, send a mail to frankzirrone@gmail.com
Thanks in advance!
------------------------
Synology NAS:
If you want to use RFLink with a Synology NAS you can use:
- an Arduino Mega clone based on CH340 USB/serial chip
In all other cases:
- connect a 10 uF capacitor between reset and ground on the Arduino.
Simply stick the pins of the capacitor in the power connector socket.
When you want to update the firmware of the Arduino, remove the capacitor and reconnect it when done.
For details about the Domoticz Synology package check out: http://www.jadahl.com
------------------------
RFlink via Network Connection:
It is possible to use RFlink via a network connection using ser2net.
------------------------
You can now use the RFLink Gateway with the following home automation software:
Domoticz
Jeedom
------------------------